bool ccnxCodecSchemaV1FixedHeaderDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary) { if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, _fixedHeaderBytes)) { PARCBuffer *buffer = ccnxCodecTlvDecoder_GetValue(decoder, _fixedHeaderBytes); bool success = ccnxTlvDictionary_PutBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader, buffer); // validation parcBuffer_SetPosition(buffer, _fixedHeader_VersionOffset); uint8_t version = parcBuffer_GetUint8(buffer); parcBuffer_SetPosition(buffer, _fixedHeader_PacketLengthOffset); uint16_t packetLength = parcBuffer_GetUint16(buffer); parcBuffer_SetPosition(buffer, _fixedHeader_HopLimitOffset); uint8_t hopLimit = parcBuffer_GetUint8(buffer); parcBuffer_SetPosition(buffer, _fixedHeader_HeaderLengthOffset); uint8_t headerLength = parcBuffer_GetUint8(buffer); if (version != 1) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_VERSION, __func__, __LINE__, _fixedHeader_VersionOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } else if (packetLength < _fixedHeaderBytes) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETLENGTH_TOO_SHORT, __func__, __LINE__, _fixedHeader_PacketTypeOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } else if (headerLength < _fixedHeaderBytes) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_HEADERLENGTH_TOO_SHORT, __func__, __LINE__, _fixedHeader_HeaderLengthOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } else if (packetLength < headerLength) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETLENGTHSHORTER, __func__, __LINE__, _fixedHeader_PacketTypeOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } // decoder now points to just past the fixed header parcBuffer_Release(&buffer); // Set the hoplimit in the dictionary. ccnxTlvDictionary_PutInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT, hopLimit); return success; } else { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder)); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); return false; } }
static size_t _appendPointer(CCNxCodecTlvEncoder *encoder, CCNxManifestHashGroupPointer *ptr) { const PARCBuffer *digest = ccnxManifestHashGroupPointer_GetDigest(ptr); CCNxManifestHashGroupPointerType type = ccnxManifestHashGroupPointer_GetType(ptr); ssize_t length = -1; switch (type) { case CCNxManifestHashGroupPointerType_Data: length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_DataPointer, (PARCBuffer *) digest); break; case CCNxManifestHashGroupPointerType_Manifest: length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_ManifestPointer, (PARCBuffer *) digest); break; default: assertTrue(false, "Invalid pointer type %d", type); } if (length < 0) { CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder)); ccnxCodecTlvEncoder_SetError(encoder, error); ccnxCodecError_Release(&error); } return length; }
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; }
/** * 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; }
static bool _decodeType(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length) { bool success = false; switch (type) { case CCNxCodecSchemaV1Types_OptionalHeaders_InterestFragment: success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG); break; case CCNxCodecSchemaV1Types_OptionalHeaders_ContentObjectFragment: success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG); break; case CCNxCodecSchemaV1Types_OptionalHeaders_InterestLifetime: // its a time, so use an Integer success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime); break; case CCNxCodecSchemaV1Types_OptionalHeaders_RecommendedCacheTime: // its a time, so use an Integer success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime); break; default: { // if we do not know the TLV type, put it in this container's unknown list success = ccnxCodecTlvUtilities_PutAsListBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_Lists_HEADERS); } break; } if (!success) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder)); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); } return success; }