/// <summary> /// Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object. /// </summary> /// /// <param name="lpPacket">The LpPacket object whose fields are updated.</param> /// <param name="input"></param> /// <param name="copy">unchanged while the Blob values are used.</param> /// <exception cref="EncodingException">For invalid encoding.</exception> public override void decodeLpPacket(LpPacket lpPacket, ByteBuffer input, bool copy) { lpPacket.clear(); TlvDecoder decoder = new TlvDecoder(input); int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.LpPacket_LpPacket); while (decoder.getOffset() < endOffset) { // Imitate TlvDecoder.readTypeAndLength. int fieldType = decoder.readVarNumber(); int fieldLength = decoder.readVarNumber(); int fieldEndOffset = decoder.getOffset() + fieldLength; if (fieldEndOffset > input.limit()) throw new EncodingException( "TLV length exceeds the buffer length"); if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_Fragment) { // Set the fragment to the bytes of the TLV value. lpPacket.setFragmentWireEncoding(new Blob(decoder.getSlice( decoder.getOffset(), fieldEndOffset), copy)); decoder.seek(fieldEndOffset); // The fragment is supposed to be the last field. break; } else if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_Nack) { NetworkNack networkNack = new NetworkNack(); int code = (int) decoder.readOptionalNonNegativeIntegerTlv( net.named_data.jndn.encoding.tlv.Tlv.LpPacket_NackReason, fieldEndOffset); // The enum numeric values are the same as this wire format, so use as is. if (code < 0 || code == net.named_data.jndn.NetworkNack.Reason.NONE.getNumericType()) // This includes an omitted NackReason. networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.NONE); else if (code == net.named_data.jndn.NetworkNack.Reason.CONGESTION.getNumericType()) networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.CONGESTION); else if (code == net.named_data.jndn.NetworkNack.Reason.DUPLICATE.getNumericType()) networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.DUPLICATE); else if (code == net.named_data.jndn.NetworkNack.Reason.NO_ROUTE.getNumericType()) networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.NO_ROUTE); else { // Unrecognized reason. networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.OTHER_CODE); networkNack.setOtherReasonCode(code); } lpPacket.addHeaderField(networkNack); } else if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IncomingFaceId) { IncomingFaceId incomingFaceId = new IncomingFaceId(); incomingFaceId.setFaceId(decoder .readNonNegativeInteger(fieldLength)); lpPacket.addHeaderField(incomingFaceId); } else { // Unrecognized field type. The conditions for ignoring are here: // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2 bool canIgnore = (fieldType >= net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IGNORE_MIN && fieldType <= net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IGNORE_MAX && (fieldType & 0x01) == 1); if (!canIgnore) throw new EncodingException( "Did not get the expected TLV type"); // Ignore. decoder.seek(fieldEndOffset); } decoder.finishNestedTlvs(fieldEndOffset); } decoder.finishNestedTlvs(endOffset); }