]>
Commit | Line | Data |
---|---|---|
5c19dc3a A |
1 | #include <Security/SecureObjectSync/SOSTransport.h> |
2 | #include <Security/SecureObjectSync/SOSTransportMessage.h> | |
3 | #include <Security/SecureObjectSync/SOSTransportMessageIDS.h> | |
4 | #include <Security/SecureObjectSync/SOSKVSKeys.h> | |
5 | #include <Security/SecureObjectSync/SOSPeerCoder.h> | |
6 | #include <Security/SecureObjectSync/SOSEngine.h> | |
7 | #include <utilities/SecCFWrappers.h> | |
8 | #include <SOSInternal.h> | |
9 | #include <Security/SecureObjectSync/SOSAccountPriv.h> | |
10 | #include <SOSCloudKeychainClient.h> | |
11 | #include <securityd/SecItemServer.h> // TODO: Remove this layer violation. | |
12 | ||
13 | CFGiblisWithHashFor(SOSTransportMessage); | |
14 | ||
15 | SOSTransportMessageRef SOSTransportMessageCreateForSubclass(size_t size, | |
16 | SOSAccountRef account, CFStringRef circleName, | |
17 | CFErrorRef *error) | |
18 | { | |
19 | SOSTransportMessageRef tpt = CFTypeAllocateWithSpace(SOSTransportMessage, size, kCFAllocatorDefault); | |
20 | ||
21 | SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account->factory, circleName, error); | |
22 | ||
23 | tpt->engine = CFRetainSafe(engine); | |
24 | tpt->account = CFRetainSafe(account); | |
25 | tpt->circleName = CFRetainSafe(circleName); | |
26 | return tpt; | |
27 | } | |
28 | ||
29 | ||
30 | static CFStringRef SOSTransportMessageCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOptions){ | |
31 | SOSTransportMessageRef t = (SOSTransportMessageRef) aObj; | |
32 | ||
33 | return t->copyDescription ? t->copyDescription(t) | |
34 | : CFStringCreateWithFormat(NULL, NULL, CFSTR("<SOSTransportMessage@%p\n>"), t); | |
35 | } | |
36 | ||
37 | static void SOSTransportMessageDestroy(CFTypeRef aObj){ | |
38 | SOSTransportMessageRef transport = (SOSTransportMessageRef) aObj; | |
39 | ||
40 | if (transport->destroy) | |
41 | transport->destroy(transport); | |
42 | ||
43 | CFReleaseSafe(transport->account); | |
44 | } | |
45 | ||
46 | CFStringRef SOSTransportMessageGetCircleName(SOSTransportMessageRef transport){ | |
47 | return transport->circleName; | |
48 | } | |
49 | ||
50 | CFIndex SOSTransportMessageGetTransportType(SOSTransportMessageRef transport, CFErrorRef *error){ | |
51 | return transport->getTransportType ? transport->getTransportType(transport, error) : kUnknown; | |
52 | } | |
53 | ||
54 | ||
55 | SOSAccountRef SOSTransportMessageGetAccount(SOSTransportMessageRef transport){ | |
56 | return transport->account; | |
57 | } | |
58 | ||
59 | static CFHashCode SOSTransportMessageHash(CFTypeRef obj){ | |
60 | return (intptr_t) obj; | |
61 | } | |
62 | ||
63 | static Boolean SOSTransportMessageCompare(CFTypeRef lhs, CFTypeRef rhs){ | |
64 | return SOSTransportMessageHash(lhs) == SOSTransportMessageHash(rhs); | |
65 | } | |
66 | ||
67 | bool SOSTransportMessageSendMessages(SOSTransportMessageRef transport, CFDictionaryRef circle_messages, CFErrorRef *error) { | |
68 | return transport->sendMessages(transport, circle_messages, error); | |
69 | } | |
70 | ||
71 | bool SOSTransportMessageFlushChanges(SOSTransportMessageRef transport, CFErrorRef *error){ | |
72 | return transport->flushChanges(transport, error); | |
73 | } | |
74 | ||
75 | bool SOSTransportMessageSyncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error){ | |
76 | return transport->syncWithPeers(transport, circleToPeerIDs, error); | |
77 | } | |
78 | ||
79 | bool SOSTransportMessageCleanupAfterPeerMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef* error){ | |
80 | return transport->cleanupAfterPeerMessages(transport, circleToPeerIDs, error); | |
81 | } | |
82 | ||
83 | CF_RETURNS_RETAINED | |
84 | CFDictionaryRef SOSTransportMessageHandleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error){ | |
85 | return transport->handleMessages(transport, circle_peer_messages_table, error); | |
86 | } | |
87 | ||
88 | SOSEngineRef SOSTransportMessageGetEngine(SOSTransportMessageRef transport) { | |
89 | return transport->engine; | |
90 | } | |
91 | ||
92 | bool SOSTransportMessageHandlePeerMessage(SOSTransportMessageRef transport, CFStringRef peerID, CFDataRef codedMessage, CFErrorRef *error) { | |
93 | __block bool result = true; | |
94 | __block bool somethingChanged = false; | |
95 | SOSEngineRef engine = SOSTransportMessageGetEngine(transport); | |
fa7225c8 | 96 | result &= SOSEngineWithPeerID(engine, peerID, error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *shouldSave) { |
5c19dc3a | 97 | CFDataRef decodedMessage = NULL; |
fa7225c8 | 98 | enum SOSCoderUnwrapStatus uwstatus = SOSPeerHandleCoderMessage(peer, coder, peerID, codedMessage, &decodedMessage, shouldSave, error); |
5c19dc3a A |
99 | if (uwstatus == SOSCoderUnwrapDecoded) { |
100 | SOSMessageRef message = NULL; | |
101 | if (decodedMessage && CFDataGetLength(decodedMessage)) { | |
102 | // Only hand non empty messages to the engine, empty messages are an artifact | |
103 | // of coder startup. | |
104 | message = SOSMessageCreateWithData(kCFAllocatorDefault, decodedMessage, error); | |
105 | } | |
106 | if (message) { | |
107 | bool engineHandleMessageDoesNotGetToRollbackTransactions = true; | |
108 | result = SOSEngineHandleMessage_locked(engine, peerID, message, txn, &engineHandleMessageDoesNotGetToRollbackTransactions, &somethingChanged, error); | |
109 | CFReleaseSafe(message); | |
110 | } | |
111 | } else { | |
112 | result = uwstatus != SOSCoderUnwrapError; | |
113 | } | |
114 | CFReleaseNull(decodedMessage); | |
115 | }); | |
116 | // TODO: Wish this wasn't here but alas. See the comment for SOSEngineHandleMessage_locked() on why this is needed. | |
117 | if (somethingChanged) | |
118 | SecKeychainChanged(false); | |
119 | ||
120 | return result; | |
121 | } | |
122 | ||
123 | bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) { | |
124 | __block bool ok = true; | |
125 | SOSEngineRef engine = SOSTransportMessageGetEngine(transport); | |
126 | ||
fa7225c8 | 127 | ok &= SOSEngineForPeerID(engine, peer_id, error, ^(SOSTransactionRef txn, SOSPeerRef peer, SOSCoderRef coder) { |
5c19dc3a A |
128 | // Now under engine lock do stuff |
129 | CFDataRef message_to_send = NULL; | |
130 | SOSEnginePeerMessageSentBlock sent = NULL; | |
fa7225c8 | 131 | ok = SOSPeerCoderSendMessageIfNeeded(engine, txn, peer, coder, &message_to_send, circle_id, peer_id, &sent, error); |
5c19dc3a A |
132 | if (message_to_send) { |
133 | CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
134 | peer_id, message_to_send, | |
135 | NULL); | |
136 | CFDictionaryRef circle_peers = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, | |
137 | circle_id, peer_dict, | |
138 | NULL); | |
139 | ok = ok && SOSTransportMessageSendMessages(transport, circle_peers, error); | |
140 | ||
141 | SOSPeerCoderConsume(&sent, ok); | |
142 | ||
143 | CFReleaseSafe(peer_dict); | |
144 | CFReleaseSafe(circle_peers); | |
145 | } | |
146 | ||
147 | Block_release(sent); | |
148 | CFReleaseSafe(message_to_send); | |
149 | }); | |
150 | return ok; | |
151 | } |