1 #include <Security/SecureObjectSync/SOSPeer.h>
2 #include <Security/SecureObjectSync/SOSPeerCoder.h>
3 #include <Security/SecureObjectSync/SOSTransportMessage.h>
4 #include <Security/SecureObjectSync/SOSCoder.h>
5 #include <Security/SecureObjectSync/SOSAccount.h>
6 #include <Security/SecureObjectSync/SOSEngine.h>
8 #include <utilities/debugging.h>
9 #include <utilities/SecCFWrappers.h>
11 #include <AssertMacros.h>
12 #include "SOSInternal.h"
14 // TODO: This could possibly move to SOSEngine?
15 bool SOSPeerCoderInitializeForPeer(SOSEngineRef engine
, SOSFullPeerInfoRef myPeerInfo
, SOSPeerInfoRef peerInfo
, CFErrorRef
*error
) {
16 __block
bool ok
= true;
17 ok
&= SOSEngineForPeerID(engine
, SOSPeerInfoGetPeerID(peerInfo
), error
, ^(SOSPeerRef peer
) {
18 ok
= SOSPeerEnsureCoder(peer
, myPeerInfo
, peerInfo
, error
);
23 void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock
*sent
, bool ok
) {
28 enum SOSCoderUnwrapStatus
SOSPeerHandleCoderMessage(SOSPeerRef peer
, CFStringRef peer_id
, CFDataRef codedMessage
, CFDataRef
*decodedMessage
, bool *forceSave
, CFErrorRef
*error
) {
30 enum SOSCoderUnwrapStatus result
= SOSCoderUnwrapError
;
31 CFMutableDataRef localDecodedMessage
= NULL
;
33 SOSCoderStatus coderStatus
= kSOSCoderDataReturned
;
34 SOSCoderRef coder
= SOSPeerGetCoder(peer
, error
);
35 require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error
? *error
: NULL
));
36 CFErrorRef localError
= NULL
;
38 coderStatus
= SOSCoderUnwrap(coder
, codedMessage
, &localDecodedMessage
, peer_id
, error
);
41 case kSOSCoderDataReturned
: {
42 logRawMessage(localDecodedMessage
, false, 0);
43 result
= SOSCoderUnwrapDecoded
;
46 case kSOSCoderNegotiating
: // Sent message already in Unwrap.
47 result
= SOSCoderUnwrapHandled
;
48 secnotice("engine", "%@ engine negotiating", peer_id
);
50 case kSOSCoderNegotiationCompleted
:
51 SOSPeerDidConnect(peer
);
52 result
= SOSCoderUnwrapHandled
;
54 secnotice("engine", "%@ engine negotiation complete", peer_id
);
56 case kSOSCoderFailure
: // Probably restart coder
57 secnotice("engine", "%@ engine failed handling message %@", peer_id
, error
? *error
: NULL
);
59 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
60 secerror("Attempt to recover coder failed to restart: %@", localError
);
63 case kSOSCoderStaleEvent
: // We received an event we have already processed in the past.
64 secinfo("engine", "%@ engine stale event ignored", peer_id
);
66 case kSOSCoderTooNew
: //We received an event from the future!
67 secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id
);
69 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
70 secerror("Attempt to recover coder failed to restart: %@", localError
);
78 *decodedMessage
= CFRetainSafe(localDecodedMessage
);
79 CFReleaseNull(localDecodedMessage
);
82 CFReleaseNull(localError
);
87 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine
, SOSPeerRef peer
, CFDataRef
*message_to_send
, CFStringRef circle_id
, CFStringRef peer_id
, SOSEnginePeerMessageSentBlock
*sent
, CFErrorRef
*error
) {
88 SOSCoderRef coder
= SOSPeerGetCoder(peer
, error
);
90 require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error
? *error
: NULL
));
92 if (SOSCoderCanWrap(coder
)) {
93 secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id
);
94 CFMutableDataRef codedMessage
= NULL
;
95 CFDataRef message
= SOSEngineCreateMessage_locked(engine
, peer
, error
, sent
);
97 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id
, *error
);
98 } else if (CFDataGetLength(message
) || SOSPeerMustSendMessage(peer
)) {
99 // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead
100 ok
= message
&& (SOSCoderWrap(coder
, message
, &codedMessage
, peer_id
, error
) == kSOSCoderDataReturned
);
102 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id
, *error
);
104 CFRetainAssign(*message_to_send
, codedMessage
);
106 CFReleaseNull(codedMessage
);
108 // Zero length message means we have no work to do.
111 CFReleaseNull(message
);
113 *message_to_send
= SOSCoderCopyPendingResponse(coder
);
114 secinfo("transport", "%@ negotiating, %@", peer_id
, message_to_send
? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message."));
115 *sent
= Block_copy(^(bool wasSent
){
117 SOSCoderConsumeResponse(coder
);