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>
11 CFGiblisWithHashFor(SOSTransportMessage
);
13 SOSTransportMessageRef
SOSTransportMessageCreateForSubclass(size_t size
,
14 SOSAccountRef account
, CFStringRef circleName
,
17 SOSTransportMessageRef tpt
= CFTypeAllocateWithSpace(SOSTransportMessage
, size
, kCFAllocatorDefault
);
19 SOSEngineRef engine
= SOSDataSourceFactoryGetEngineForDataSourceName(account
->factory
, circleName
, error
);
21 tpt
->engine
= CFRetainSafe(engine
);
22 tpt
->account
= CFRetainSafe(account
);
27 static CFStringRef
SOSTransportMessageCopyDescription(CFTypeRef aObj
){
28 SOSTransportMessageRef t
= (SOSTransportMessageRef
) aObj
;
30 return t
->copyDescription
? t
->copyDescription(t
)
31 : CFStringCreateWithFormat(NULL
, NULL
, CFSTR("<SOSTransportMessage@%p\n>"), t
);
34 static void SOSTransportMessageDestroy(CFTypeRef aObj
){
35 SOSTransportMessageRef transport
= (SOSTransportMessageRef
) aObj
;
37 if (transport
->destroy
)
38 transport
->destroy(transport
);
40 CFReleaseSafe(transport
->engine
);
43 SOSAccountRef
SOSTransportMessageGetAccount(SOSTransportMessageRef transport
){
44 return transport
->account
;
47 static CFHashCode
SOSTransportMessageHash(CFTypeRef obj
){
48 return (intptr_t) obj
;
51 static Boolean
SOSTransportMessageCompare(CFTypeRef lhs
, CFTypeRef rhs
){
52 return SOSTransportMessageHash(lhs
) == SOSTransportMessageHash(rhs
);
55 bool SOSTransportMessageSendMessages(SOSTransportMessageRef transport
, CFDictionaryRef circle_messages
, CFErrorRef
*error
) {
56 return transport
->sendMessages(transport
, circle_messages
, error
);
59 bool SOSTransportMessageFlushChanges(SOSTransportMessageRef transport
, CFErrorRef
*error
){
60 return transport
->flushChanges(transport
, error
);
63 bool SOSTransportMessageSyncWithPeers(SOSTransportMessageRef transport
, CFDictionaryRef circleToPeerIDs
, CFErrorRef
*error
){
64 return transport
->syncWithPeers(transport
, circleToPeerIDs
, error
);
67 bool SOSTransportMessageCleanupAfterPeerMessages(SOSTransportMessageRef transport
, CFDictionaryRef circleToPeerIDs
, CFErrorRef
* error
){
68 return transport
->cleanupAfterPeerMessages(transport
, circleToPeerIDs
, error
);
72 CFDictionaryRef
SOSTransportMessageHandleMessages(SOSTransportMessageRef transport
, CFMutableDictionaryRef circle_peer_messages_table
, CFErrorRef
*error
){
73 return transport
->handleMessages(transport
, circle_peer_messages_table
, error
);
76 SOSEngineRef
SOSTransportMessageGetEngine(SOSTransportMessageRef transport
){
77 return transport
->engine
;
81 bool SOSTransportMessageHandlePeerMessage(SOSTransportMessageRef transport
, CFStringRef peer_id
, CFDataRef codedMessage
, CFErrorRef
*error
){
83 CFDataRef decodedMessage
= NULL
;
86 SOSPeerRef peer
= SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport
), peer_id
);
88 enum SOSCoderUnwrapStatus uwstatus
= SOSPeerHandleCoderMessage(peer
, peer_id
, codedMessage
, &decodedMessage
, error
);
90 if (uwstatus
== SOSCoderUnwrapDecoded
) {
91 result
= SOSEngineHandleMessage(SOSTransportMessageGetEngine(transport
), peer_id
, decodedMessage
, error
);
93 result
= uwstatus
!= SOSCoderUnwrapError
;
95 CFReleaseNull(decodedMessage
);
100 bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport
, CFStringRef circle_id
, CFStringRef peer_id
, CFErrorRef
*error
) {
102 SOSEnginePeerMessageSentBlock sent
= NULL
;
103 CFDataRef message_to_send
= NULL
;
105 SOSPeerRef peer
= SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport
), peer_id
);
106 CFDataRef coderData
= SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport
), peer_id
);
107 require(coderData
, fail
);
109 SOSCoderRef coder
= SOSCoderCreateFromData(coderData
, error
);
110 require(coder
, fail
);
111 SOSPeerSetCoder(peer
, coder
);
113 ok
= SOSPeerCoderSendMessageIfNeeded(peer
, &message_to_send
, circle_id
, peer_id
, &sent
, error
);
114 coder
= SOSPeerGetCoder(peer
);
116 if (message_to_send
) {
117 CFDictionaryRef peer_dict
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
118 peer_id
, message_to_send
,
120 CFDictionaryRef circle_peers
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
121 circle_id
, peer_dict
,
124 ok
= ok
&& SOSTransportMessageSendMessages(transport
, circle_peers
, error
);
126 SOSPeerCoderConsume(&sent
, ok
);
128 CFReleaseSafe(peer_dict
);
129 CFReleaseSafe(circle_peers
);
136 CFReleaseSafe(message_to_send
);
138 coderData
= SOSCoderCopyDER(coder
, error
);
140 if(!SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport
), peer_id
, coderData
, error
)){
141 secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state");
143 CFReleaseNull(coderData
);
146 SOSCoderDispose(coder
);
153 bool 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
;
159 if (!SOSTransportMessageSendMessageIfNeeded(transport
, circle_id
, peer_id
, &sendError
)) {
160 secerror("Error sending message in circle %@ to peer %@ (%@)", circle_id
, peer_id
, sendError
);
163 CFReleaseNull(sendError
);