LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeType)
{
    uint8_t rawManifest[40] = { 0x00, 0x07, 0x00, 0x24,
                                0x00, 0x02, 0x00, 0x20,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46 };
    PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawManifest, 40));

    CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
    CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateManifest();

    uint16_t type = ccnxCodecTlvDecoder_GetType(decoder);
    uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);

    bool result = _decodeType(decoder, dict, type, length);
    assertTrue(result, "Expected the manifest type to be correctly decoded at the top level");

    ccnxManifest_Release(&dict);
    ccnxCodecTlvDecoder_Destroy(&decoder);
    parcBuffer_Release(&wireFormat);
}
bool
ccnxCodecSchemaV1PacketDecoder_BufferDecode(PARCBuffer *packetBuffer, CCNxTlvDictionary *packetDictionary)
{
    CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
    bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, packetDictionary);
    ccnxCodecTlvDecoder_Destroy(&decoder);
    return success;
}
/**
 * Decodes the per-hop optional headers
 *
 * @param [in] data The packet decoder state
 *
 * @return true successful decode
 * @return false A decoding error
 *
 * Example:
 * @code
 * <#example#>
 * @endcode
 */
static bool
_decodeOptionalHeaders(_CCNxCodecSchemaV1Data *data)
{
    size_t optionalHeaderLength = ccnxCodecSchemaV1FixedHeaderDecoder_GetOptionalHeaderLength(data->packetDictionary);
    CCNxCodecTlvDecoder *optionalHeaderDecoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, optionalHeaderLength);

    bool success = ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(optionalHeaderDecoder, data->packetDictionary);

    ccnxCodecTlvDecoder_Destroy(&optionalHeaderDecoder);
    return success;
}
Пример #4
0
bool
ccnxCodecTlvUtilities_DecodeSubcontainer(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t key, uint16_t length,
                                   bool (*subcontainerDecoder)(CCNxCodecTlvDecoder *, CCNxTlvDictionary *))
{
    bool success = false;
    CCNxCodecTlvDecoder *innerDecoder = ccnxCodecTlvDecoder_GetContainer(decoder, length);
    if (innerDecoder) {
        success = subcontainerDecoder(innerDecoder, packetDictionary);
        ccnxCodecTlvDecoder_Destroy(&innerDecoder);
    }
    return success;
}
LONGBOW_TEST_CASE(Global, ccnxTlvCodecName_Decode_WrongType)
{
    uint8_t decodeBytes[] = { 0x10, 0x20, 0x00, 0x0E, 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
    PARCBuffer *decodeBuffer = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
    CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(decodeBuffer);
    CCNxName *test = ccnxCodecSchemaV1NameCodec_Decode(decoder, 0xFFFF);

    assertNull(test, "Name should have returned NULL because the name type does not match");
    assertTrue(ccnxCodecTlvDecoder_Position(decoder) == 0, "Position should not have moved, expected 0, got %zu", ccnxCodecTlvDecoder_Position(decoder));

    ccnxCodecTlvDecoder_Destroy(&decoder);
    parcBuffer_Release(&decodeBuffer);
}
/**
 * Decodes the CCNx message inside a TLV packet
 *
 * Creates an inner decoder that slices the decode buffer then passes that and our
 * message dictionary to the appropriate inner decoder.
 *
 * @param [in] data The packet decoder state
 *
 * @return true successful decode
 * @return false A decoding error
 *
 * Example:
 * @code
 * <#example#>
 * @endcode
 */
static bool
_decodeMessage(_CCNxCodecSchemaV1Data *data)
{
    bool success = false;

    if (ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, 4)) {
        // what kind of message are we looking at?
        // Note that this is based on the TLV container, not the fixed head PacketType
        uint16_t tlv_type = ccnxCodecTlvDecoder_GetType(data->decoder);
        uint16_t tlv_length = ccnxCodecTlvDecoder_GetLength(data->decoder);

        // ensure its a proper tlv type
        switch (tlv_type) {
            case CCNxCodecSchemaV1Types_MessageType_Interest: // fallthrough
            case CCNxCodecSchemaV1Types_MessageType_ContentObject: // fallthrough
            case CCNxCodecSchemaV1Types_MessageType_Control: // fallthrough
                break;

            default:
                return false;
        }

        // cross check with the fixed header value
        // ccnxCodecSchemaV1FixedHeaderDecoder_Decode ensures that PacketLength is not less than HeaderLength
        size_t messageLength = ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength(data->packetDictionary) - ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(data->packetDictionary);

        if (tlv_length <= messageLength && ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
            // This decode is for the "value" of the message, it does not include the wrapper
            CCNxCodecTlvDecoder *messageDecoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, tlv_length);

            if (tlv_type == CCNxCodecSchemaV1Types_MessageType_Control) {
                // the CPI messages are not a proper "message" in that there's no inner TLV, its just data
                success = _decodeCPI(messageDecoder, data->packetDictionary);
            } else {
                success = ccnxCodecSchemaV1MessageDecoder_Decode(messageDecoder, data->packetDictionary);
            }

            ccnxCodecTlvDecoder_Destroy(&messageDecoder);
        } else {
            // raise an error
            CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_TOO_LONG, __func__, __LINE__, ccnxCodecTlvDecoder_Position(data->decoder));
            ccnxCodecTlvDecoder_SetError(data->decoder, error);
            ccnxCodecError_Release(&error);
        }
    }

    return success;
}
LONGBOW_TEST_CASE(Global, ccnxTlvCodecName_Decode_RightType)
{
    PARCBuffer *buffer = parcBuffer_WrapCString("brandywine");
    CCNxNameSegment *segment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, buffer);
    CCNxName *truth = ccnxName_Append(ccnxName_Create(), segment);
    ccnxNameSegment_Release(&segment);
    parcBuffer_Release(&buffer);

    uint8_t decodeBytes[] = { 0x10, 0x20, 0x00, 0x0E, 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
    PARCBuffer *decodeBuffer = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
    CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(decodeBuffer);
    CCNxName *test = ccnxCodecSchemaV1NameCodec_Decode(decoder, 0x1020);

    assertTrue(ccnxName_Equals(truth, test), "Name segments do not match");

    ccnxName_Release(&test);
    ccnxCodecTlvDecoder_Destroy(&decoder);
    parcBuffer_Release(&decodeBuffer);
    ccnxName_Release(&truth);
}
static bool
_decodeValidationPayload(_CCNxCodecSchemaV1Data *data)
{
    bool success = false;

    if (ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, 4)) {
        // what kind of message are we looking at?
        // Note that this is based on the TLV container, not the fixed head PacketType
        uint16_t tlv_type = ccnxCodecTlvDecoder_GetType(data->decoder);
        uint16_t tlv_length = ccnxCodecTlvDecoder_GetLength(data->decoder);

        if (tlv_type == CCNxCodecSchemaV1Types_MessageType_ValidationPayload &&
            ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
            CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, tlv_length);

            success = ccnxCodecSchemaV1ValidationDecoder_DecodePayload(decoder, data->packetDictionary);

            ccnxCodecTlvDecoder_Destroy(&decoder);
        }
    }

    return success;
}
LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroup)
{
    uint8_t rawManifest[40] = { 0x00, 0x07, 0x00, 0x24,
                                0x00, 0x02, 0x00, 0x20,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46 };
    PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawManifest, 40));

    CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
    CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateManifest();

    ccnxCodecTlvDecoder_GetType(decoder); // swallow type
    uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);

    CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
    bool result = _decodeHashGroup(decoder, dict, group, length);
    assertTrue(result, "Expected hash group to be decoded correctly.");

    PARCBuffer *expectedPointer = parcBuffer_AllocateCString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
    CCNxManifestHashGroupPointer *pointer = ccnxManifestHashGroup_GetPointerAtIndex(group, 0);
    const PARCBuffer *actualPointer = ccnxManifestHashGroupPointer_GetDigest(pointer);
    assertTrue(parcBuffer_Equals(expectedPointer, actualPointer), "Expected decoded pointer to equal %s, got %s", parcBuffer_ToHexString(expectedPointer), parcBuffer_ToHexString(actualPointer));

    parcBuffer_Release(&expectedPointer);

    ccnxManifestHashGroup_Release(&group);
    ccnxManifest_Release(&dict);
    ccnxCodecTlvDecoder_Destroy(&decoder);
    parcBuffer_Release(&wireFormat);
}
LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_Decode)
{
    uint8_t rawManifest[40] = { 0x00, 0x07, 0x00, 0x24,
                                0x00, 0x02, 0x00, 0x20,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46,
                                0x46, 0x46, 0x46, 0x46 };
    PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawManifest, 40));

    CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
    CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateManifest();

    bool result = ccnxCodecSchemaV1ManifestDecoder_Decode(decoder, dict);
    assertTrue(result, "Expected the manifest to be decoded correctly");

    ccnxTlvDictionary_Release(&dict);
    ccnxCodecTlvDecoder_Destroy(&decoder);
    parcBuffer_Release(&wireFormat);
}
static bool
_decodeValidationAlg(_CCNxCodecSchemaV1Data *data)
{
    bool success = false;

    if (ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, 4)) {
        // what kind of message are we looking at?
        // Note that this is based on the TLV container, not the fixed head PacketType
        uint16_t tlv_type = ccnxCodecTlvDecoder_GetType(data->decoder);
        uint16_t tlv_length = ccnxCodecTlvDecoder_GetLength(data->decoder);

        if (tlv_type == CCNxCodecSchemaV1Types_MessageType_ValidationAlg &&
            ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
            CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, tlv_length);

            success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, data->packetDictionary);

            ccnxCodecTlvDecoder_Destroy(&decoder);
        } else {
            // raise and error
            if (!ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
                // tlv_length goes beyond the decoder
                CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_TOO_LONG, __func__, __LINE__, ccnxCodecTlvDecoder_Position(data->decoder));
                ccnxCodecTlvDecoder_SetError(data->decoder, error);
                ccnxCodecError_Release(&error);
            } else {
                // not CCNxCodecSchemaV1Types_MessageType_ValidationAlg
                CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(data->decoder));
                ccnxCodecTlvDecoder_SetError(data->decoder, error);
                ccnxCodecError_Release(&error);
            }
        }
    }

    return success;
}
LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroupMetadata)
{
    // Re-build the expected metadata from the manifest
    CCNxName *groupLocator = ccnxName_CreateFromCString("ccnx:/locator");
    PARCBuffer *digest = parcBuffer_Allocate(16);
    for (size_t i = 0; i < parcBuffer_Limit(digest); i++) {
        parcBuffer_PutUint8(digest, 0);
    }
    parcBuffer_Flip(digest);
    size_t entrySize = 1;
    size_t dataSize = 2;
    size_t blockSize = 3;
    size_t treeHeight = 4;

    // Compute the expected size of this metadata group.
    size_t metadataSize = 4 * (4 + 8) + 4 + parcBuffer_Limit(digest) + 4 + strlen("ccnx:/locator");

    // See test_ccnxCodecSchemaV1_ManifestEncoder.c for the packet construction details.
    uint8_t rawMetadata[89] = { 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata,
                                0x00, metadataSize,
                                0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator,
                                0x00, strlen("ccnx:/locator"),
                                'c',  'c',
                                'n',  'x',
                                ':',  '/',
                                'l',  'o',
                                'c',  'a',
                                't',  'o',
                                'r',
                                0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize,
                                0x00, 0x08,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, dataSize,
                                0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize,
                                0x00, 0x08,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, blockSize,
                                0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize,
                                0x00, 0x08,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, entrySize,
                                0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight,
                                0x00, 0x08,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, treeHeight,
                                0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256,
                                0x00, parcBuffer_Remaining(digest),
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00,
                                0x00, 0x00 };
    PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawMetadata, sizeof(rawMetadata)));

    // Create the encoder and swallow the top level container
    CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
    ccnxCodecTlvDecoder_GetType(decoder); // swallow type
    uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);

    // Decode the metadata
    CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
    bool result = _decodeHashGroupMetadata(decoder, group, length);
    assertTrue(result, "Expected hash group metadata to be decoded correctly.");

    const CCNxName *actualLocator = ccnxManifestHashGroup_GetLocator(group);
    size_t actualEntrySize = ccnxManifestHashGroup_GetEntrySize(group);
    size_t actualDataSize = ccnxManifestHashGroup_GetDataSize(group);
    size_t actualBlockSize = ccnxManifestHashGroup_GetBlockSize(group);
    size_t actualTreeHeight = ccnxManifestHashGroup_GetTreeHeight(group);
    const PARCBuffer *actualDigest = ccnxManifestHashGroup_GetOverallDataDigest(group);

    assertTrue(ccnxName_Equals(groupLocator, actualLocator), "Expected decoded locator to equal %s, got %s", ccnxName_ToString(groupLocator), ccnxName_ToString(actualLocator));
    assertTrue(entrySize == actualEntrySize, "Expected %zu entry size, got %zu", entrySize, actualEntrySize);
    assertTrue(dataSize == actualDataSize, "Expected %zu data size, got %zu", dataSize, actualDataSize);
    assertTrue(blockSize == actualBlockSize, "Expected %zu block size, got %zu", blockSize, actualBlockSize);
    assertTrue(treeHeight == actualTreeHeight, "Expected %zu tree height, got %zu", treeHeight, actualTreeHeight);
    assertTrue(parcBuffer_Equals(digest, actualDigest), "Expected %s digest, got %s", parcBuffer_ToHexString(digest), parcBuffer_ToHexString(actualDigest));

    parcBuffer_Release(&digest);
    ccnxName_Release(&groupLocator);

    ccnxManifestHashGroup_Release(&group);
    ccnxCodecTlvDecoder_Destroy(&decoder);
    parcBuffer_Release(&wireFormat);
}