SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { SOSCoderRef p = calloc(1, sizeof(struct __OpaqueSOSCoder)); const uint8_t *der = CFDataGetBytePtr(exportedData); const uint8_t *der_end = der + CFDataGetLength(exportedData); CFDataRef otr_data = NULL; ccder_tag tag; require(ccder_decode_tag(&tag, der, der_end),fail); switch (tag) { case CCDER_OCTET_STRING: // TODO: this code is safe to delete? { der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end); p->waitingForDataPacket = false; } break; case CCDER_CONSTRUCTED_SEQUENCE: { const uint8_t *sequence_end = NULL; der = ccder_decode_sequence_tl(&sequence_end, der, der_end); require_action_quiet(sequence_end == der_end, fail, SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Extra data in SOS coder"), NULL, error)); der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end); der = der_decode_bool(&p->waitingForDataPacket, der, sequence_end); if (der != sequence_end) { // optionally a pending response der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end); } } break; default: SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Unsupported SOS Coder DER"), NULL, error); goto fail; } require(der, fail); p->sessRef = SecOTRSessionCreateFromData(NULL, otr_data); require(p->sessRef, fail); CFReleaseSafe(otr_data); return p; fail: SOSCoderDispose(p); CFReleaseSafe(otr_data); return NULL; }
bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) { SOSEnginePeerMessageSentBlock sent = NULL; CFDataRef message_to_send = NULL; bool ok = false; SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peer_id); CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peer_id); require(coderData, fail); SOSCoderRef coder = SOSCoderCreateFromData(coderData, error); require(coder, fail); SOSPeerSetCoder(peer, coder); ok = SOSPeerCoderSendMessageIfNeeded(peer, &message_to_send, circle_id, peer_id, &sent, error); coder = SOSPeerGetCoder(peer); if (message_to_send) { CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, peer_id, message_to_send, NULL); CFDictionaryRef circle_peers = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, circle_id, peer_dict, NULL); ok = ok && SOSTransportMessageSendMessages(transport, circle_peers, error); SOSPeerCoderConsume(&sent, ok); CFReleaseSafe(peer_dict); CFReleaseSafe(circle_peers); } Block_release(sent); CFReleaseSafe(message_to_send); coderData = SOSCoderCopyDER(coder, error); if(!SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error)){ secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state"); } CFReleaseNull(coderData); if (coder) SOSCoderDispose(coder); fail: CFReleaseNull(peer); return ok; }