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
);
65 result
= SOSCoderUnwrapHandled
;
67 case kSOSCoderTooNew
: // We received an event from the future!
68 secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id
);
70 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
71 secerror("Attempt to recover coder failed to restart: %@", localError
);
79 *decodedMessage
= CFRetainSafe(localDecodedMessage
);
80 CFReleaseNull(localDecodedMessage
);
83 CFReleaseNull(localError
);
88 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine
, SOSPeerRef peer
, CFDataRef
*message_to_send
, CFStringRef circle_id
, CFStringRef peer_id
, SOSEnginePeerMessageSentBlock
*sent
, CFErrorRef
*error
) {
89 SOSCoderRef coder
= SOSPeerGetCoder(peer
, error
);
91 require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error
? *error
: NULL
));
93 if (SOSCoderCanWrap(coder
)) {
94 secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id
);
95 CFMutableDataRef codedMessage
= NULL
;
96 CFDataRef message
= SOSEngineCreateMessage_locked(engine
, peer
, error
, sent
);
98 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id
, *error
);
99 } else if (CFDataGetLength(message
) || SOSPeerMustSendMessage(peer
)) {
100 // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead
101 ok
= message
&& (SOSCoderWrap(coder
, message
, &codedMessage
, peer_id
, error
) == kSOSCoderDataReturned
);
103 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id
, *error
);
105 CFRetainAssign(*message_to_send
, codedMessage
);
107 CFReleaseNull(codedMessage
);
109 // Zero length message means we have no work to do.
112 CFReleaseNull(message
);
114 *message_to_send
= SOSCoderCopyPendingResponse(coder
);
115 secinfo("transport", "%@ negotiating, %@", peer_id
, message_to_send
? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message."));
116 *sent
= Block_copy(^(bool wasSent
){
118 SOSCoderConsumeResponse(coder
);