+static SOSCoderRef SOSCoderCreate_internal() {
+ SOSCoderRef p = CFTypeAllocate(SOSCoder, struct __OpaqueSOSCoder, kCFAllocatorDefault);
+
+ p->peer_id = NULL;
+ p->sessRef = NULL;
+ p->pendingResponse = NULL;
+ p->waitingForDataPacket = false;
+
+ p->hashOfLastReceived = NULL;
+ p->lastReceivedWasOld = false;
+
+ return p;
+
+}
+
+// 0 - Type not understood
+// 1 - OCTET_STRING, just stored the data for OTR
+// 2 - SEQUENCE with no version value
+// 3 - SEQUENCE with version value we pull out of the CCDER_INTEGER
+
+typedef enum coderExportFormatVersion {
+ kNotUnderstood = 0,
+ kCoderAsOTRDataOnly = 1,
+ kCoderAsSequence = 2,
+ kCoderAsVersionedSequence = 3,
+
+ kCurrentCoderExportVersion = kCoderAsVersionedSequence
+} CoderExportFormatVersion;
+
+static uint64_t SOSCoderGetExportedVersion(const uint8_t *der, const uint8_t *der_end) {
+ ccder_tag tag;
+ uint64_t result = kNotUnderstood;
+ require(ccder_decode_tag(&tag, der, der_end),xit);
+ switch (tag) {
+ case CCDER_OCTET_STRING: // TODO: this code is safe to delete?
+ result = kCoderAsOTRDataOnly;
+ break;
+
+ case CCDER_CONSTRUCTED_SEQUENCE:
+ {
+ const uint8_t *sequence_end = NULL;
+ der = ccder_decode_sequence_tl(&sequence_end, der, der_end);
+ ccder_tag firstSequenceTag;
+ require(ccder_decode_tag(&firstSequenceTag, der, der_end),xit);
+
+ switch (firstSequenceTag) {
+ case CCDER_OCTET_STRING:
+ result = kCoderAsSequence;
+ break;
+ case CCDER_INTEGER:
+ der = ccder_decode_uint64(NULL, der, sequence_end);
+ if (der == NULL) {
+ result = kNotUnderstood;
+ } else {
+ result = kCoderAsVersionedSequence;
+ }
+ break;
+ }
+ }
+ }
+xit:
+ return result;
+
+}
+