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
); 
 107 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine
, SOSTransactionRef txn
, SOSPeerRef peer
, SOSCoderRef coder
, CFDataRef 
*message_to_send
, CFStringRef peer_id
, SOSEnginePeerMessageSentBlock 
*sent
, CFErrorRef 
*error
) { 
 109     secnotice("transport", "coder state: %@", coder
); 
 110     require_action_quiet(coder
, xit
, secerror("%@ getCoder: %@", peer_id
, error 
? *error 
: NULL
)); 
 112     if (SOSCoderCanWrap(coder
)) { 
 113         secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id
); 
 114         CFMutableDataRef codedMessage 
= NULL
; 
 115         CFDataRef message 
= SOSEngineCreateMessage_locked(engine
, txn
, peer
, error
, sent
); 
 117             secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id
, *error
); 
 118         } else if (CFDataGetLength(message
) || SOSPeerMustSendMessage(peer
)) { 
 119             // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead 
 120             ok 
= message 
&& (SOSCoderWrap(coder
, message
, &codedMessage
, peer_id
, error
) == kSOSCoderDataReturned
); 
 122                 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id
, *error
); 
 124                 CFRetainAssign(*message_to_send
, codedMessage
); 
 125                 engine
->codersNeedSaving 
= true; 
 127             CFReleaseNull(codedMessage
); 
 129             // Zero length message means we have no work to do. 
 132         CFReleaseNull(message
); 
 134         *message_to_send 
= SOSCoderCopyPendingResponse(coder
); 
 135         engine
->codersNeedSaving 
= true; 
 136         secinfo("transport", "%@ negotiating, %@", peer_id
, (message_to_send 
&& *message_to_send
) ? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message.")); 
 137         *sent 
= Block_copy(^(bool wasSent
){ 
 139                 SOSCoderConsumeResponse(coder
);