2 #include <SecureObjectSync/SOSPeer.h>
3 #include <SecureObjectSync/SOSTransportCoder.h>
4 #include <SecureObjectSync/SOSTransportMessage.h>
5 #include <SecureObjectSync/SOSCoder.h>
6 #include <SecureObjectSync/SOSAccount.h>
7 #include <SecureObjectSync/SOSAccountPriv.h>
8 #include <SecureObjectSync/SOSEngine.h>
10 #include <utilities/debugging.h>
11 #include <utilities/SecCFWrappers.h>
13 #include <AssertMacros.h>
14 #include <SOSInternal.h>
17 // For now transport (the abstract class) consumes the Transport data in engine to hold
19 static SOSCoderRef
SOSTransportMessageCopyPeerCoder(SOSTransportMessageRef transport
, CFStringRef peer_id
){
20 SOSCoderRef coder
= NULL
;
22 CFDataRef coderData
= SOSEngineGetTransportData(SOSTransportMessageGetEngine(transport
), peer_id
);
25 CFErrorRef localError
= NULL
;
26 coder
= SOSCoderCreateFromData(coderData
, &localError
);
29 secerror("Failed to make coder from valid data for peer %@ (%@). THIS IS FATAL, WE CAN'T COMMUNICATE.", peer_id
, localError
);
32 CFReleaseNull(localError
);
35 secerror("Failed to get coderData from engine for peer %@. THIS IS FATAL, WE CAN'T COMMUNICATE.", peer_id
);
40 bool SOSTransportMessageSavePeerCoderData(SOSTransportMessageRef transport
, SOSCoderRef coder
, CFStringRef peer_id
, CFErrorRef
*error
) {
41 CFDataRef coderData
= NULL
;
45 coderData
= SOSCoderCopyDER(coder
, error
);
46 if (coderData
== NULL
) {
47 secerror("%@ coder data failed to export %@, zapping data", transport
, error
? *error
: 0);
50 require_action_quiet(coderData
, exit
, ok
= SOSErrorCreate(kSOSErrorAllocationFailure
, error
, NULL
, CFSTR("Creation of coder data failed")));
52 ok
= SOSEngineSetTransportData(SOSTransportMessageGetEngine(transport
), peer_id
, coderData
, error
);
55 CFReleaseNull(coderData
);
59 bool SOSTransportCoderInitializeForPeer(SOSTransportMessageRef transport
, SOSFullPeerInfoRef myPeerInfo
, SOSPeerInfoRef peerInfo
, CFErrorRef
*error
){
60 SOSCoderRef coder
= NULL
;
61 CFStringRef peer_id
= SOSPeerInfoGetPeerID(peerInfo
);
62 CFDataRef coderData
= SOSEngineGetTransportData(SOSTransportMessageGetEngine(transport
), peer_id
);
63 if(coderData
!= NULL
) {
64 CFErrorRef coderError
= NULL
;
65 coder
= SOSCoderCreateFromData(coderData
, &coderError
);
68 secerror("Found data but couldn't make coder for %@: %@", peer_id
, coderError
);
70 CFReleaseNull(coderError
);
73 bool haveGoodCoder
= coder
;
75 secnotice("transport", "New coder for id %@.", peer_id
);
76 coder
= SOSCoderCreate(peerInfo
, myPeerInfo
, error
);
79 haveGoodCoder
= SOSTransportMessageSavePeerCoderData(transport
, coder
, peer_id
, error
);
81 secerror("Couldn't make coder for %@", peer_id
);
86 SOSCoderDispose(coder
);
90 enum SOSCoderUnwrapStatus
SOSTransportMessageHandleCoderMessage(SOSTransportMessageRef transport
, CFStringRef peer_id
, CFDataRef codedMessage
, CFDataRef
*decodedMessage
, CFErrorRef
*error
){
92 enum SOSCoderUnwrapStatus result
= SOSCoderUnwrapError
;
93 CFMutableDataRef localDecodedMessage
= NULL
;
95 SOSCoderStatus coderStatus
= kSOSCoderDataReturned
;
96 SOSCoderRef coder
= SOSTransportMessageCopyPeerCoder(transport
, peer_id
);
98 SOSAccountEnsurePeerRegistration(SOSTransportMessageGetAccount(transport
), error
);
99 coder
= SOSTransportMessageCopyPeerCoder(transport
, peer_id
);
100 secnotice("transport", "Building new coder!");
102 CFErrorRef localError
= NULL
;
104 coderStatus
= SOSCoderUnwrap(coder
, codedMessage
, &localDecodedMessage
, peer_id
, error
);
106 switch(coderStatus
) {
107 case kSOSCoderDataReturned
: {
108 logRawMessage(localDecodedMessage
, false, 0);
109 result
= SOSCoderUnwrapDecoded
;
112 case kSOSCoderNegotiating
: // Sent message already in Unwrap.
113 result
= SOSCoderUnwrapHandled
;
114 secnotice("transport", "%@ transport negotiating", peer_id
);
116 case kSOSCoderNegotiationCompleted
:
117 if(SOSEnginePeerDidConnect(SOSTransportMessageGetEngine(transport
), peer_id
, error
))
118 result
= SOSCoderUnwrapHandled
;
119 secnotice("transport", "%@ transport negotiation complete", peer_id
);
121 case kSOSCoderFailure
: // Probably restart coder
122 secnotice("transport", "%@ transport failed handling message %@", peer_id
, error
? *error
: NULL
);
123 SOSCoderReset(coder
);
124 if(SOSCoderStart(coder
, &localError
) == kSOSCoderFailure
){
125 secerror("Attempt to recover coder failed to restart: %@", localError
);
128 case kSOSCoderStaleEvent
: // We received an event we have already processed in the past.
129 secnotice("transport", "%@ transport stale event ignored", peer_id
);
136 *decodedMessage
= CFRetainSafe(localDecodedMessage
);
137 CFReleaseNull(localDecodedMessage
);
139 SOSTransportMessageSavePeerCoderData(transport
, coder
, peer_id
, NULL
);
140 SOSCoderDispose(coder
);
143 secerror("SOSTransportMessageHandleCoderMessage: Could not make a new coder!");
146 CFReleaseNull(localError
);
152 #warning this should be SOSTransportMessage and be split up into coder/message pieces
153 /* Send a message to peer if needed. Return false if there was an error, true otherwise. */
154 bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport
, CFStringRef circle_id
, CFStringRef peer_id
, CFErrorRef
*error
) {
155 SOSCoderRef coder
= SOSTransportMessageCopyPeerCoder(transport
, peer_id
);
158 SOSAccountEnsurePeerRegistration(SOSTransportMessageGetAccount(transport
), error
);
159 coder
= SOSTransportMessageCopyPeerCoder(transport
, peer_id
);
161 CFDataRef message_to_send
= NULL
;
163 SOSEnginePeerMessageSentBlock sent
= NULL
;
165 require_action_quiet(coder
, fail
, SOSCreateError(kSOSErrorAllocationFailure
, CFSTR("SOSTransportMessageCopyPeerCoder failed"), *error
, error
));
167 if (SOSCoderCanWrap(coder
)) {
168 secnotice("transport", "%@ Coder can wrap, getting message from engine", peer_id
);
169 CFMutableDataRef codedMessage
= NULL
;
170 CFDataRef message
= SOSEngineCreateMessageToSyncToPeer(SOSTransportMessageGetEngine(transport
), peer_id
, &sent
, error
);
172 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@",peer_id
, *error
);
174 ok
= message
&& (SOSCoderWrap(coder
, message
, &codedMessage
, peer_id
, error
) == kSOSCoderDataReturned
);
176 secnotice("transport", "%@ SOSCoderWrap failed: %@",peer_id
, *error
);
180 CFRetainAssign(message_to_send
, codedMessage
);
182 CFReleaseNull(codedMessage
);
183 CFReleaseNull(message
);
185 message_to_send
= SOSCoderCopyPendingResponse(coder
);
186 secnotice("transport", "%@ Negotiating, %@", peer_id
, message_to_send
? CFSTR("Sending negotiation message.") : CFSTR("waiting for negotiation message."));
187 sent
= Block_copy(^(bool wasSent
){
189 SOSCoderConsumeResponse(coder
);
194 if (message_to_send
) {
195 CFDictionaryRef peer_dict
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
196 peer_id
, message_to_send
,
198 CFDictionaryRef circle_peers
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
199 circle_id
, peer_dict
,
202 ok
= ok
&& SOSTransportMessageSendMessages(transport
, circle_peers
, error
);
207 CFReleaseSafe(peer_dict
);
208 CFReleaseSafe(circle_peers
);
213 CFReleaseSafe(message_to_send
);
215 SOSTransportMessageSavePeerCoderData(transport
, coder
, peer_id
, NULL
);
219 SOSCoderDispose(coder
);