ndn_Error ndn_TlvDecoder_skipRemainingNestedTlvs (struct ndn_TlvDecoder *self, size_t endOffset, int skipCritical) { while(self->offset < endOffset) { ndn_Error error; uint64_t type; int critical; uint64_t lengthVarNumber; if ((error = ndn_TlvDecoder_readVarNumber(self, &type))) return error; if ((error = ndn_TlvDecoder_readVarNumber(self, &lengthVarNumber))) return error; critical = (type <= 31 || (type & 1) == 1); if (critical && !skipCritical) return NDN_ERROR_Unrecognized_critical_TLV_type_code; // Silently ignore if the length is larger than size_t. self->offset += (size_t)lengthVarNumber; if (self->offset > self->inputLength) return NDN_ERROR_TLV_length_exceeds_buffer_length; } if (self->offset != endOffset) return NDN_ERROR_TLV_length_does_not_equal_total_length_of_nested_TLVs; return NDN_ERROR_success; }
ndn_Error ndn_decodeTlvNameComponent (struct ndn_NameComponent *component, struct ndn_TlvDecoder *decoder) { ndn_Error error; uint64_t type; size_t saveOffset; saveOffset = decoder->offset; if ((error = ndn_TlvDecoder_readVarNumber(decoder, &type))) return error; // Restore the position. ndn_TlvDecoder_seek(decoder, saveOffset); if ((error = ndn_TlvDecoder_readBlobTlv(decoder, type, &component->value))) return error; if (type == ndn_Tlv_ImplicitSha256DigestComponent) component->type = ndn_NameComponentType_IMPLICIT_SHA256_DIGEST; else if (type == ndn_Tlv_ParametersSha256DigestComponent) component->type = ndn_NameComponentType_PARAMETERS_SHA256_DIGEST; else if (type == ndn_Tlv_NameComponent) component->type = ndn_NameComponentType_GENERIC; else { // Unrecognized type code. component->type = ndn_NameComponentType_OTHER_CODE; component->otherTypeCode = (int)type; } return NDN_ERROR_success; }
ndn_Error ndn_decodeTlvNameComponent (struct ndn_NameComponent *component, struct ndn_TlvDecoder *decoder) { ndn_Error error; uint64_t type; size_t saveOffset; saveOffset = decoder->offset; if ((error = ndn_TlvDecoder_readVarNumber(decoder, &type))) return error; // Restore the position. ndn_TlvDecoder_seek(decoder, saveOffset); if ((error = ndn_TlvDecoder_readBlobTlv(decoder, type, &component->value))) return error; if (type == ndn_Tlv_ImplicitSha256DigestComponent) component->type = ndn_NameComponentType_IMPLICIT_SHA256_DIGEST; else component->type = ndn_NameComponentType_GENERIC; return NDN_ERROR_success; }
ndn_Error ndn_decodeTlvLpPacket (struct ndn_LpPacket *lpPacket, struct ndn_TlvDecoder *decoder) { ndn_Error error; size_t endOffset; ndn_LpPacket_clear(lpPacket); if ((error = ndn_TlvDecoder_readNestedTlvsStart (decoder, ndn_Tlv_LpPacket_LpPacket, &endOffset))) return error; while (decoder->offset < endOffset) { // Imitate ndn_TlvDecoder_readTypeAndLength. uint64_t fieldTypeVarNumber; int fieldType; uint64_t fieldLength; size_t fieldEndOffset; if ((error = ndn_TlvDecoder_readVarNumber(decoder, &fieldTypeVarNumber))) return error; fieldType = (int)fieldTypeVarNumber; if ((error = ndn_TlvDecoder_readVarNumber(decoder, &fieldLength))) return error; fieldEndOffset = decoder->offset + (size_t)fieldLength; if (fieldEndOffset > decoder->inputLength) return NDN_ERROR_TLV_length_exceeds_buffer_length; if (fieldType == ndn_Tlv_LpPacket_Fragment) { // Set the fragment to the bytes of the TLV value. if ((error = ndn_TlvDecoder_getSlice (decoder, decoder->offset, fieldEndOffset, &lpPacket->fragmentWireEncoding))) return error; ndn_TlvDecoder_seek(decoder, fieldEndOffset); // The fragment is supposed to be the last field. break; } else if (fieldType == ndn_Tlv_LpPacket_Nack) { struct ndn_NetworkNack *networkNack; int code; if ((error = ndn_NetworkNack_add(lpPacket, &networkNack))) return error; if ((error = ndn_TlvDecoder_readOptionalNonNegativeIntegerTlv (decoder, ndn_Tlv_LpPacket_NackReason, fieldEndOffset, &code))) return error; // The enum numeric values are the same as this wire format, so use as is. if (code < 0 || code == ndn_NetworkNackReason_NONE) // This includes an omitted NackReason. networkNack->reason = ndn_NetworkNackReason_NONE; else if (code == ndn_NetworkNackReason_CONGESTION || code == ndn_NetworkNackReason_DUPLICATE || code == ndn_NetworkNackReason_NO_ROUTE) networkNack->reason = code; else { // Unrecognized reason. networkNack->reason = ndn_NetworkNackReason_OTHER_CODE; networkNack->otherReasonCode = code; } } else if (fieldType == ndn_Tlv_LpPacket_IncomingFaceId) { struct ndn_IncomingFaceId *incomingFaceId; if ((error = ndn_IncomingFaceId_add(lpPacket, &incomingFaceId))) return error; if ((error = ndn_TlvDecoder_readNonNegativeInteger (decoder, fieldLength, &incomingFaceId->faceId))) return error; } else { // Unrecognized field type. The conditions for ignoring are here: // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2 int canIgnore = (fieldType >= ndn_Tlv_LpPacket_IGNORE_MIN && fieldType <= ndn_Tlv_LpPacket_IGNORE_MAX && (fieldType & 0x01) == 1); if (!canIgnore) return NDN_ERROR_did_not_get_the_expected_TLV_type; // Ignore. ndn_TlvDecoder_seek(decoder, fieldEndOffset); } if ((error = ndn_TlvDecoder_finishNestedTlvs(decoder, fieldEndOffset))) return error; } if ((error = ndn_TlvDecoder_finishNestedTlvs(decoder, endOffset))) return error; return NDN_ERROR_success; }