1#include <SecureObjectSync/SOSTransport.h> 2#include <SecureObjectSync/SOSTransportMessage.h> 3#include <SecureObjectSync/SOSKVSKeys.h> 4#include <SecureObjectSync/SOSPeerCoder.h> 5#include <SecureObjectSync/SOSEngine.h> 6#include <utilities/SecCFWrappers.h> 7#include <SOSInternal.h> 8#include <SecureObjectSync/SOSAccountPriv.h> 9#include <SOSCloudKeychainClient.h> 10 11CFGiblisWithHashFor(SOSTransportMessage); 12 13SOSTransportMessageRef SOSTransportMessageCreateForSubclass(size_t size, 14 SOSAccountRef account, CFStringRef circleName, 15 CFErrorRef *error) 16{ 17 SOSTransportMessageRef tpt = CFTypeAllocateWithSpace(SOSTransportMessage, size, kCFAllocatorDefault); 18 19 SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account->factory, circleName, error); 20 21 tpt->engine = CFRetainSafe(engine); 22 tpt->account = CFRetainSafe(account); 23 return tpt; 24} 25 26 27static CFStringRef SOSTransportMessageCopyDescription(CFTypeRef aObj){ 28 SOSTransportMessageRef t = (SOSTransportMessageRef) aObj; 29 30 return t->copyDescription ? t->copyDescription(t) 31 : CFStringCreateWithFormat(NULL, NULL, CFSTR("<SOSTransportMessage@%p\n>"), t); 32} 33 34static void SOSTransportMessageDestroy(CFTypeRef aObj){ 35 SOSTransportMessageRef transport = (SOSTransportMessageRef) aObj; 36 37 if (transport->destroy) 38 transport->destroy(transport); 39 40 CFReleaseSafe(transport->engine); 41} 42 43SOSAccountRef SOSTransportMessageGetAccount(SOSTransportMessageRef transport){ 44 return transport->account; 45} 46 47static CFHashCode SOSTransportMessageHash(CFTypeRef obj){ 48 return (intptr_t) obj; 49} 50 51static Boolean SOSTransportMessageCompare(CFTypeRef lhs, CFTypeRef rhs){ 52 return SOSTransportMessageHash(lhs) == SOSTransportMessageHash(rhs); 53} 54 55bool SOSTransportMessageSendMessages(SOSTransportMessageRef transport, CFDictionaryRef circle_messages, CFErrorRef *error) { 56 return transport->sendMessages(transport, circle_messages, error); 57} 58 59bool SOSTransportMessageFlushChanges(SOSTransportMessageRef transport, CFErrorRef *error){ 60 return transport->flushChanges(transport, error); 61} 62 63bool SOSTransportMessageSyncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error){ 64 return transport->syncWithPeers(transport, circleToPeerIDs, error); 65} 66 67bool SOSTransportMessageCleanupAfterPeerMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef* error){ 68 return transport->cleanupAfterPeerMessages(transport, circleToPeerIDs, error); 69} 70 71CF_RETURNS_RETAINED 72CFDictionaryRef SOSTransportMessageHandleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error){ 73 return transport->handleMessages(transport, circle_peer_messages_table, error); 74} 75 76SOSEngineRef SOSTransportMessageGetEngine(SOSTransportMessageRef transport){ 77 return transport->engine; 78} 79 80 81bool SOSTransportMessageHandlePeerMessage(SOSTransportMessageRef transport, CFStringRef peer_id, CFDataRef codedMessage, CFErrorRef *error){ 82 83 CFDataRef decodedMessage = NULL; 84 bool result = false; 85 86 SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peer_id); 87 88 enum SOSCoderUnwrapStatus uwstatus = SOSPeerHandleCoderMessage(peer, peer_id, codedMessage, &decodedMessage, error); 89 90 if (uwstatus == SOSCoderUnwrapDecoded) { 91 result = SOSEngineHandleMessage(SOSTransportMessageGetEngine(transport), peer_id, decodedMessage, error); 92 } else { 93 result = uwstatus != SOSCoderUnwrapError; 94 } 95 CFReleaseNull(decodedMessage); 96 CFReleaseNull(peer); 97 return result; 98} 99 100bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) { 101 102 SOSEnginePeerMessageSentBlock sent = NULL; 103 CFDataRef message_to_send = NULL; 104 bool ok = false; 105 SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peer_id); 106 CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peer_id); 107 require(coderData, fail); 108 109 SOSCoderRef coder = SOSCoderCreateFromData(coderData, error); 110 require(coder, fail); 111 SOSPeerSetCoder(peer, coder); 112 113 ok = SOSPeerCoderSendMessageIfNeeded(peer, &message_to_send, circle_id, peer_id, &sent, error); 114 coder = SOSPeerGetCoder(peer); 115 116 if (message_to_send) { 117 CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, 118 peer_id, message_to_send, 119 NULL); 120 CFDictionaryRef circle_peers = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, 121 circle_id, peer_dict, 122 NULL); 123 124 ok = ok && SOSTransportMessageSendMessages(transport, circle_peers, error); 125 126 SOSPeerCoderConsume(&sent, ok); 127 128 CFReleaseSafe(peer_dict); 129 CFReleaseSafe(circle_peers); 130 } 131 132 133 Block_release(sent); 134 135 136 CFReleaseSafe(message_to_send); 137 138 coderData = SOSCoderCopyDER(coder, error); 139 140 if(!SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error)){ 141 secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state"); 142 } 143 CFReleaseNull(coderData); 144 145 if (coder) 146 SOSCoderDispose(coder); 147 148fail: 149 CFReleaseNull(peer); 150 return ok; 151} 152 153bool SOSTransportMessageSendMessagesIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFArrayRef handledPeers, CFErrorRef *error) { 154 CFArrayForEach(handledPeers, ^(const void *value) { 155 if (isString(value)) { 156 CFStringRef peer_id = (CFStringRef) value; 157 CFErrorRef sendError = NULL; 158 159 if (!SOSTransportMessageSendMessageIfNeeded(transport, circle_id, peer_id, &sendError)) { 160 secerror("Error sending message in circle %@ to peer %@ (%@)", circle_id, peer_id, sendError); 161 }; 162 163 CFReleaseNull(sendError); 164 } 165 }); 166 167 return true; 168} 169 170 171 172 173