2 * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <Security/SecureObjectSync/SOSPeer.h>
25 #include <Security/SecureObjectSync/SOSPeerCoder.h>
26 #include <Security/SecureObjectSync/SOSTransportMessage.h>
27 #include <Security/SecureObjectSync/SOSCoder.h>
28 #include <Security/SecureObjectSync/SOSAccount.h>
29 #include <Security/SecureObjectSync/SOSEngine.h>
31 #include <utilities/debugging.h>
32 #include <utilities/SecCFWrappers.h>
34 #include <AssertMacros.h>
35 #include "SOSInternal.h"
37 void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock
*sent
, bool ok
) {
42 enum SOSCoderUnwrapStatus
SOSPeerHandleCoderMessage(SOSPeerRef peer
, SOSCoderRef coder
, CFStringRef peer_id
, CFDataRef codedMessage
, CFDataRef
*decodedMessage
, bool *forceSave
, CFErrorRef
*error
) {
44 enum SOSCoderUnwrapStatus result
= SOSCoderUnwrapError
;
45 CFMutableDataRef localDecodedMessage
= NULL
;
47 SOSCoderStatus coderStatus
= kSOSCoderDataReturned
;
48 require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error
? *error
: NULL
));
49 CFErrorRef localError
= NULL
;
51 coderStatus
= SOSCoderUnwrap(coder
, codedMessage
, &localDecodedMessage
, peer_id
, error
);
54 case kSOSCoderDataReturned
: {
55 logRawMessage(localDecodedMessage
, false, 0);
56 result
= SOSCoderUnwrapDecoded
;
59 case kSOSCoderNegotiating
: // Sent message already in Unwrap.
60 result
= SOSCoderUnwrapHandled
;
61 secnotice("engine", "%@ engine negotiating", peer_id
);
63 case kSOSCoderNegotiationCompleted
:
64 SOSPeerDidConnect(peer
);
65 result
= SOSCoderUnwrapHandled
;
67 secnotice("engine", "%@ engine negotiation complete", peer_id
);
69 case kSOSCoderFailure
: // Probably restart coder
70 secnotice("engine", "%@ engine failed handling message %@", peer_id
, error
? *error
: NULL
);
72 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
73 secerror("Attempt to recover coder failed to restart: %@", localError
);
76 case kSOSCoderStaleEvent
: // We received an event we have already processed in the past.
77 secinfo("engine", "%@ engine stale event ignored", peer_id
);
78 result
= SOSCoderUnwrapHandled
;
80 case kSOSCoderForceMessage
:
81 SOSPeerSetMustSendMessage(peer
, true);
82 result
= SOSCoderUnwrapHandled
;
84 case kSOSCoderTooNew
: // We received an event from the future!
85 secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id
);
87 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
88 secerror("Attempt to recover coder failed to restart: %@", localError
);
96 *decodedMessage
= CFRetainSafe(localDecodedMessage
);
97 CFReleaseNull(localDecodedMessage
);
100 CFReleaseNull(localError
);
105 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine
, SOSTransactionRef txn
, SOSPeerRef peer
, SOSCoderRef coder
, CFDataRef
*message_to_send
, CFStringRef circle_id
, CFStringRef peer_id
, SOSEnginePeerMessageSentBlock
*sent
, CFErrorRef
*error
) {
107 require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error
? *error
: NULL
));
109 if (SOSCoderCanWrap(coder
)) {
110 secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id
);
111 CFMutableDataRef codedMessage
= NULL
;
112 CFDataRef message
= SOSEngineCreateMessage_locked(engine
, txn
, peer
, error
, sent
);
114 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id
, *error
);
115 } else if (CFDataGetLength(message
) || SOSPeerMustSendMessage(peer
)) {
116 // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead
117 ok
= message
&& (SOSCoderWrap(coder
, message
, &codedMessage
, peer_id
, error
) == kSOSCoderDataReturned
);
119 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id
, *error
);
121 CFRetainAssign(*message_to_send
, codedMessage
);
123 CFReleaseNull(codedMessage
);
125 // Zero length message means we have no work to do.
128 CFReleaseNull(message
);
130 *message_to_send
= SOSCoderCopyPendingResponse(coder
);
131 secinfo("transport", "%@ negotiating, %@", peer_id
, message_to_send
? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message."));
132 *sent
= Block_copy(^(bool wasSent
){
134 SOSCoderConsumeResponse(coder
);