ssize_t _appendMetadata(CCNxCodecTlvEncoder *encoder, CCNxManifestHashGroup *group) { ssize_t length = 0; // Pre-populate this field -- we'll come back and fill in the length after we're done size_t startPosition = ccnxCodecTlvEncoder_Position(encoder); ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata, length); // Now append all metadata that exists in the hash group. const CCNxName *locator = ccnxManifestHashGroup_GetLocator(group); if (locator != NULL) { char *nameString = ccnxName_ToString(locator); PARCBuffer *nameBuffer = parcBuffer_AllocateCString(nameString); length += ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator, nameBuffer); parcBuffer_Release(&nameBuffer); parcMemory_Deallocate(&nameString); } size_t dataSize = ccnxManifestHashGroup_GetDataSize(group); if (dataSize > 0) { length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize, dataSize); } size_t blockSize = ccnxManifestHashGroup_GetBlockSize(group); if (blockSize > 0) { length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize, blockSize); } size_t entrySize = ccnxManifestHashGroup_GetEntrySize(group); if (entrySize > 0) { length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize, entrySize); } size_t treeSize = ccnxManifestHashGroup_GetTreeHeight(group); if (treeSize > 0) { length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight, treeSize); } const PARCBuffer *dataDigest = ccnxManifestHashGroup_GetOverallDataDigest(group); if (dataDigest != NULL) { length += ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256, (PARCBuffer *) dataDigest); } // Rewind back to the container opening and fill in the length size_t endPosition = ccnxCodecTlvEncoder_Position(encoder); ccnxCodecTlvEncoder_PutUint16(encoder, startPosition, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata); ccnxCodecTlvEncoder_PutUint16(encoder, startPosition + 2, length); ccnxCodecTlvEncoder_SetPosition(encoder, endPosition); return endPosition - startPosition; }
ssize_t ccnxCodecSchemaV1ManifestEncoder_Encode(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) { ssize_t length = 0; ssize_t numHashGroups = ccnxTlvDictionary_ListSize(packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_HASH_GROUP_LIST); for (size_t i = 0; i < numHashGroups; i++) { // Skip past the TL of the hash group to append the pointers inside ssize_t groupLength = 0; ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_HashGroup, groupLength); CCNxManifestInterface *interface = ccnxManifestInterface_GetInterface(packetDictionary); CCNxManifestHashGroup *group = interface->getHashGroup(packetDictionary, i); // Encode any metadata, if present. if (ccnxManifestHashGroup_HasMetadata(group)) { groupLength += _appendMetadata(encoder, group); } // Append the HashGroup pointers size_t numPointers = ccnxManifestHashGroup_GetNumberOfPointers(group); for (size_t p = 0; p < numPointers; p++) { CCNxManifestHashGroupPointer *ptr = ccnxManifestHashGroup_GetPointerAtIndex(group, p); ssize_t ptrLength = _appendPointer(encoder, ptr); if (ptrLength < 0) { return ptrLength; } groupLength += ptrLength; } // Now that we know the overall length, rewind back to the start and append the TL // part of the container. size_t endPosition = ccnxCodecTlvEncoder_Position(encoder); ssize_t offset = endPosition - groupLength - 4; ccnxCodecTlvEncoder_PutUint16(encoder, offset, CCNxCodecSchemaV1Types_CCNxMessage_HashGroup); ccnxCodecTlvEncoder_PutUint16(encoder, offset + 2, groupLength); ccnxCodecTlvEncoder_SetPosition(encoder, endPosition); length += groupLength + 4; ccnxManifestHashGroup_Release(&group); } return length; }
ssize_t ccnxCodecTlvUtilities_NestedEncode(CCNxCodecTlvEncoder *outerEncoder, CCNxTlvDictionary *packetDictionary, uint32_t nestedType, ssize_t (*nestedEncoderFunction)(CCNxCodecTlvEncoder *protoInfoEncoder, CCNxTlvDictionary *packetDictionary)) { size_t startPosition = ccnxCodecTlvEncoder_Position(outerEncoder); ccnxCodecTlvEncoder_AppendContainer(outerEncoder, nestedType, 0); ssize_t nestedLength = nestedEncoderFunction(outerEncoder, packetDictionary); if (nestedLength > 0) { ccnxCodecTlvEncoder_SetContainerLength(outerEncoder, startPosition, nestedLength); } else { // rewind the container ccnxCodecTlvEncoder_SetPosition(outerEncoder, startPosition); return nestedLength; } size_t endPosition = ccnxCodecTlvEncoder_Position(outerEncoder); return endPosition - startPosition; }