Commit | Line | Data |
---|---|---|
5c19dc3a A |
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> | |
7 | ||
8 | #include <utilities/debugging.h> | |
9 | #include <utilities/SecCFWrappers.h> | |
10 | ||
11 | #include <AssertMacros.h> | |
12 | #include "SOSInternal.h" | |
13 | ||
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); | |
19 | }); | |
20 | return ok; | |
21 | } | |
22 | ||
23 | void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock *sent, bool ok) { | |
24 | if (*sent) | |
25 | (*sent)(ok); | |
26 | } | |
27 | ||
28 | enum SOSCoderUnwrapStatus SOSPeerHandleCoderMessage(SOSPeerRef peer, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, bool *forceSave, CFErrorRef *error) { | |
29 | ||
30 | enum SOSCoderUnwrapStatus result = SOSCoderUnwrapError; | |
31 | CFMutableDataRef localDecodedMessage = NULL; | |
32 | ||
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; | |
37 | if (coder) { | |
38 | coderStatus = SOSCoderUnwrap(coder, codedMessage, &localDecodedMessage, peer_id, error); | |
39 | ||
40 | switch(coderStatus) { | |
41 | case kSOSCoderDataReturned: { | |
42 | logRawMessage(localDecodedMessage, false, 0); | |
43 | result = SOSCoderUnwrapDecoded; | |
44 | break; | |
45 | } | |
46 | case kSOSCoderNegotiating: // Sent message already in Unwrap. | |
47 | result = SOSCoderUnwrapHandled; | |
48 | secnotice("engine", "%@ engine negotiating", peer_id); | |
49 | break; | |
50 | case kSOSCoderNegotiationCompleted: | |
51 | SOSPeerDidConnect(peer); | |
52 | result = SOSCoderUnwrapHandled; | |
53 | *forceSave = true; | |
54 | secnotice("engine", "%@ engine negotiation complete", peer_id); | |
55 | break; | |
56 | case kSOSCoderFailure: // Probably restart coder | |
57 | secnotice("engine", "%@ engine failed handling message %@", peer_id, error ? *error : NULL); | |
58 | SOSCoderReset(coder); | |
59 | if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){ | |
60 | secerror("Attempt to recover coder failed to restart: %@", localError); | |
61 | } | |
62 | break; | |
63 | case kSOSCoderStaleEvent: // We received an event we have already processed in the past. | |
64 | secinfo("engine", "%@ engine stale event ignored", peer_id); | |
e3d460c9 | 65 | result = SOSCoderUnwrapHandled; |
5c19dc3a | 66 | break; |
e3d460c9 | 67 | case kSOSCoderTooNew: // We received an event from the future! |
5c19dc3a A |
68 | secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id); |
69 | SOSCoderReset(coder); | |
70 | if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){ | |
71 | secerror("Attempt to recover coder failed to restart: %@", localError); | |
72 | } | |
73 | break; | |
74 | default: | |
75 | assert(false); | |
76 | break; | |
77 | } | |
78 | if(decodedMessage) | |
79 | *decodedMessage = CFRetainSafe(localDecodedMessage); | |
80 | CFReleaseNull(localDecodedMessage); | |
81 | } | |
82 | ||
83 | CFReleaseNull(localError); | |
84 | xit: | |
85 | return result; | |
86 | } | |
87 | ||
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); | |
90 | bool ok = false; | |
91 | require_action_quiet(coder, xit, secerror("%@ getCoder: %@", peer_id, error ? *error : NULL)); | |
92 | ||
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); | |
97 | if (!message) { | |
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); | |
102 | if (!ok) { | |
103 | secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id, *error); | |
104 | } else { | |
105 | CFRetainAssign(*message_to_send, codedMessage); | |
106 | } | |
107 | CFReleaseNull(codedMessage); | |
108 | } else { | |
109 | // Zero length message means we have no work to do. | |
110 | ok = true; | |
111 | } | |
112 | CFReleaseNull(message); | |
113 | } else { | |
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){ | |
117 | if (wasSent) | |
118 | SOSCoderConsumeResponse(coder); | |
119 | }); | |
120 | ok = true; | |
121 | } | |
122 | ||
123 | xit: | |
124 | return ok; | |
125 | } |