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>
30 #include <Security/SecureObjectSync/SOSEnginePriv.h>
32 #include <utilities/debugging.h>
33 #include <utilities/SecCFWrappers.h>
35 #include <AssertMacros.h>
36 #include "SOSInternal.h"
38 void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock
*sent
, bool ok
) {
43 enum SOSCoderUnwrapStatus
SOSPeerHandleCoderMessage(SOSPeerRef peer
, SOSCoderRef coder
, CFStringRef peer_id
, CFDataRef codedMessage
, CFDataRef
*decodedMessage
, bool *forceSave
, CFErrorRef
*error
) {
45 enum SOSCoderUnwrapStatus result
= SOSCoderUnwrapError
;
46 CFMutableDataRef localDecodedMessage
= NULL
;
48 SOSCoderStatus coderStatus
= kSOSCoderDataReturned
;
49 require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error
? *error
: NULL
));
50 CFErrorRef localError
= NULL
;
52 coderStatus
= SOSCoderUnwrap(coder
, codedMessage
, &localDecodedMessage
, peer_id
, error
);
55 case kSOSCoderDataReturned
: {
56 logRawMessage(localDecodedMessage
, false, 0);
57 result
= SOSCoderUnwrapDecoded
;
60 case kSOSCoderNegotiating
: // Sent message already in Unwrap.
61 result
= SOSCoderUnwrapHandled
;
62 secnotice("engine", "%@ engine negotiating", peer_id
);
64 case kSOSCoderNegotiationCompleted
:
65 SOSPeerDidConnect(peer
);
66 result
= SOSCoderUnwrapHandled
;
68 secnotice("engine", "%@ engine negotiation complete", peer_id
);
70 case kSOSCoderFailure
: // Probably restart coder
71 secnotice("engine", "%@ engine failed handling message %@", peer_id
, error
? *error
: NULL
);
73 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
74 secerror("Attempt to recover coder failed to restart: %@", localError
);
77 case kSOSCoderStaleEvent
: // We received an event we have already processed in the past.
78 secinfo("engine", "%@ engine stale event ignored", peer_id
);
79 result
= SOSCoderUnwrapHandled
;
81 case kSOSCoderForceMessage
:
82 SOSPeerSetMustSendMessage(peer
, true);
83 result
= SOSCoderUnwrapHandled
;
85 case kSOSCoderTooNew
: // We received an event from the future!
86 secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id
);
88 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
89 secerror("Attempt to recover coder failed to restart: %@", localError
);
97 *decodedMessage
= CFRetainSafe(localDecodedMessage
);
98 CFReleaseNull(localDecodedMessage
);
101 CFReleaseNull(localError
);
106 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine
, SOSTransactionRef txn
, SOSPeerRef peer
, SOSCoderRef coder
, CFDataRef
*message_to_send
, CFStringRef circle_id
, CFStringRef peer_id
, SOSEnginePeerMessageSentBlock
*sent
, CFErrorRef
*error
) {
108 secnotice("transport", "coder state: %@", coder
);
109 require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error
? *error
: NULL
));
111 if (SOSCoderCanWrap(coder
)) {
112 secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id
);
113 CFMutableDataRef codedMessage
= NULL
;
114 CFDataRef message
= SOSEngineCreateMessage_locked(engine
, txn
, peer
, error
, sent
);
116 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id
, *error
);
117 } else if (CFDataGetLength(message
) || SOSPeerMustSendMessage(peer
)) {
118 // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead
119 ok
= message
&& (SOSCoderWrap(coder
, message
, &codedMessage
, peer_id
, error
) == kSOSCoderDataReturned
);
121 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id
, *error
);
123 CFRetainAssign(*message_to_send
, codedMessage
);
124 engine
->codersNeedSaving
= true;
126 CFReleaseNull(codedMessage
);
128 // Zero length message means we have no work to do.
131 CFReleaseNull(message
);
133 *message_to_send
= SOSCoderCopyPendingResponse(coder
);
134 engine
->codersNeedSaving
= true;
135 secinfo("transport", "%@ negotiating, %@", peer_id
, message_to_send
? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message."));
136 *sent
= Block_copy(^(bool wasSent
){
138 SOSCoderConsumeResponse(coder
);