Пример #1
0
        /// <summary>
        /// Continue scanning input starting from offset_ to find the element end.
        /// If the end of the element which started at offset 0 is found, this returns
        /// true and getOffset() is the length of the element.  Otherwise, this returns
        /// false which means you should read more into input and call again.
        /// </summary>
        ///
        /// <param name="input">You have to pass in input each time because the buffer could be reallocated.</param>
        /// <returns>true if found the element end, false if not.</returns>
        public bool findElementEnd(ByteBuffer input)
        {
            if (gotElementEnd_)
            {
                // Someone is calling when we already got the end.
                return(true);
            }

            TlvDecoder decoder = new TlvDecoder(input);

            while (true)
            {
                if (offset_ >= input.limit())
                {
                    // All the cases assume we have some input. Return and wait for more.
                    return(false);
                }

                if (state_ == TlvStructureDecoder.READ_TYPE)
                {
                    int firstOctet = (int)input.get(offset_) & 0xff;
                    offset_ += 1;
                    if (firstOctet < 253)
                    {
                        // The value is simple, so we can skip straight to reading the length.
                        state_ = TlvStructureDecoder.READ_LENGTH;
                    }
                    else
                    {
                        // Set up to skip the type bytes.
                        if (firstOctet == 253)
                        {
                            nBytesToRead_ = 2;
                        }
                        else if (firstOctet == 254)
                        {
                            nBytesToRead_ = 4;
                        }
                        else
                        {
                            // value == 255.
                            nBytesToRead_ = 8;
                        }

                        state_ = TlvStructureDecoder.READ_TYPE_BYTES;
                    }
                }
                else if (state_ == TlvStructureDecoder.READ_TYPE_BYTES)
                {
                    int nRemainingBytes = input.limit() - offset_;
                    if (nRemainingBytes < nBytesToRead_)
                    {
                        // Need more.
                        offset_       += nRemainingBytes;
                        nBytesToRead_ -= nRemainingBytes;
                        return(false);
                    }

                    // Got the type bytes. Move on to read the length.
                    offset_ += nBytesToRead_;
                    state_   = TlvStructureDecoder.READ_LENGTH;
                }
                else if (state_ == TlvStructureDecoder.READ_LENGTH)
                {
                    int firstOctet_0 = (int)input.get(offset_) & 0xff;
                    offset_ += 1;
                    if (firstOctet_0 < 253)
                    {
                        // The value is simple, so we can skip straight to reading
                        //  the value bytes.
                        nBytesToRead_ = firstOctet_0;
                        if (nBytesToRead_ == 0)
                        {
                            // No value bytes to read. We're finished.
                            gotElementEnd_ = true;
                            return(true);
                        }

                        state_ = TlvStructureDecoder.READ_VALUE_BYTES;
                    }
                    else
                    {
                        // We need to read the bytes in the extended encoding of
                        //  the length.
                        if (firstOctet_0 == 253)
                        {
                            nBytesToRead_ = 2;
                        }
                        else if (firstOctet_0 == 254)
                        {
                            nBytesToRead_ = 4;
                        }
                        else
                        {
                            // value == 255.
                            nBytesToRead_ = 8;
                        }

                        // We need to use firstOctet in the next state.
                        firstOctet_ = firstOctet_0;
                        state_      = TlvStructureDecoder.READ_LENGTH_BYTES;
                    }
                }
                else if (state_ == TlvStructureDecoder.READ_LENGTH_BYTES)
                {
                    int nRemainingBytes_1 = input.limit() - offset_;
                    if (!useHeaderBuffer_ && nRemainingBytes_1 >= nBytesToRead_)
                    {
                        // We don't have to use the headerBuffer. Set nBytesToRead.
                        decoder.seek(offset_);

                        nBytesToRead_ = decoder.readExtendedVarNumber(firstOctet_);
                        // Update offset_ to the decoder's offset after reading.
                        offset_ = decoder.getOffset();
                    }
                    else
                    {
                        useHeaderBuffer_ = true;

                        int nNeededBytes = nBytesToRead_ - headerBuffer_.position();
                        if (nNeededBytes > nRemainingBytes_1)
                        {
                            // We can't get all of the header bytes from this input.
                            // Save in headerBuffer.
                            if (headerBuffer_.position() + nRemainingBytes_1 > headerBuffer_
                                .limit())
                            {
                                // We don't expect this to happen.
                                throw new Exception(
                                          "Cannot store more header bytes than the size of headerBuffer");
                            }
                            ByteBuffer remainingInput = input.duplicate();
                            remainingInput.position(offset_);
                            headerBuffer_.put(remainingInput);
                            offset_ += nRemainingBytes_1;

                            return(false);
                        }

                        // Copy the remaining bytes into headerBuffer, read the
                        //   length and set nBytesToRead.
                        if (headerBuffer_.position() + nNeededBytes > headerBuffer_
                            .limit())
                        {
                            // We don't expect this to happen.
                            throw new Exception(
                                      "Cannot store more header bytes than the size of headerBuffer");
                        }
                        ByteBuffer remainingLengthBytes = input.duplicate();
                        remainingLengthBytes.position(offset_);
                        remainingLengthBytes.limit(offset_ + nNeededBytes);
                        headerBuffer_.put(remainingLengthBytes);
                        offset_ += nNeededBytes;

                        // Use a local decoder just for the headerBuffer.
                        headerBuffer_.flip();
                        TlvDecoder bufferDecoder = new TlvDecoder(headerBuffer_);
                        // Replace nBytesToRead with the length of the value.
                        nBytesToRead_ = bufferDecoder
                                        .readExtendedVarNumber(firstOctet_);
                    }

                    if (nBytesToRead_ == 0)
                    {
                        // No value bytes to read. We're finished.
                        gotElementEnd_ = true;
                        return(true);
                    }

                    // Get ready to read the value bytes.
                    state_ = TlvStructureDecoder.READ_VALUE_BYTES;
                }
                else if (state_ == TlvStructureDecoder.READ_VALUE_BYTES)
                {
                    int nRemainingBytes_2 = input.limit() - offset_;
                    if (nRemainingBytes_2 < nBytesToRead_)
                    {
                        // Need more.
                        offset_       += nRemainingBytes_2;
                        nBytesToRead_ -= nRemainingBytes_2;
                        return(false);
                    }

                    // Got the bytes. We're finished.
                    offset_       += nBytesToRead_;
                    gotElementEnd_ = true;
                    return(true);
                }
                else
                {
                    // We don't expect this to happen.
                    throw new Exception("findElementEnd: unrecognized state");
                }
            }
        }
Пример #2
0
        private static void decodeSignatureInfo(SignatureHolder signatureHolder,
				TlvDecoder decoder, bool copy)
        {
            int beginOffset = decoder.getOffset();
            int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.SignatureInfo);

            int signatureType = (int) decoder
                    .readNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureType);
            if (signatureType == net.named_data.jndn.encoding.tlv.Tlv.SignatureType_SignatureSha256WithRsa) {
                signatureHolder.setSignature(new Sha256WithRsaSignature());
                // Modify the holder's signature object because if we create an object
                //   and set it, then the holder will have to copy all the fields.
                Sha256WithRsaSignature signatureInfo = (Sha256WithRsaSignature) signatureHolder
                        .getSignature();
                decodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.KeyLocator, signatureInfo.getKeyLocator(),
                        decoder, copy);
                if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.ValidityPeriod_ValidityPeriod, endOffset))
                    decodeValidityPeriod(signatureInfo.getValidityPeriod(), decoder);
            } else if (signatureType == net.named_data.jndn.encoding.tlv.Tlv.SignatureType_SignatureSha256WithEcdsa) {
                signatureHolder.setSignature(new Sha256WithEcdsaSignature());
                Sha256WithEcdsaSignature signatureInfo_0 = (Sha256WithEcdsaSignature) signatureHolder
                        .getSignature();
                decodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.KeyLocator, signatureInfo_0.getKeyLocator(),
                        decoder, copy);
                if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.ValidityPeriod_ValidityPeriod, endOffset))
                    decodeValidityPeriod(signatureInfo_0.getValidityPeriod(), decoder);
            } else if (signatureType == net.named_data.jndn.encoding.tlv.Tlv.SignatureType_SignatureHmacWithSha256) {
                signatureHolder.setSignature(new HmacWithSha256Signature());
                HmacWithSha256Signature signatureInfo_1 = (HmacWithSha256Signature) signatureHolder
                        .getSignature();
                decodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.KeyLocator, signatureInfo_1.getKeyLocator(),
                        decoder, copy);
            } else if (signatureType == net.named_data.jndn.encoding.tlv.Tlv.SignatureType_DigestSha256)
                signatureHolder.setSignature(new DigestSha256Signature());
            else {
                signatureHolder.setSignature(new GenericSignature());
                GenericSignature signatureInfo_2 = (GenericSignature) signatureHolder
                        .getSignature();

                // Get the bytes of the SignatureInfo TLV.
                signatureInfo_2.setSignatureInfoEncoding(
                        new Blob(decoder.getSlice(beginOffset, endOffset), copy),
                        signatureType);
            }

            decoder.finishNestedTlvs(endOffset);
        }
Пример #3
0
        /// <summary>
        /// Decode the input and update this Schedule object.
        /// </summary>
        ///
        /// <param name="input"></param>
        /// <exception cref="EncodingException">For invalid encoding.</exception>
        public void wireDecode(ByteBuffer input)
        {
            // For now, don't use WireFormat and hardcode to use TLV since the encoding
            // doesn't go out over the wire, only into the local SQL database.
            TlvDecoder decoder = new TlvDecoder(input);

            int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_Schedule);

            // Decode the whiteIntervalList.
              		ILOG.J2CsMapping.Collections.Collections.Clear(whiteIntervalList_);
            int listEndOffset = decoder
                    .readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_WhiteIntervalList);
            while (decoder.getOffset() < listEndOffset)
                ILOG.J2CsMapping.Collections.Collections.Add(whiteIntervalList_,decodeRepetitiveInterval(decoder));
            decoder.finishNestedTlvs(listEndOffset);

            // Decode the blackIntervalList.
            ILOG.J2CsMapping.Collections.Collections.Clear(blackIntervalList_);
            listEndOffset = decoder
                    .readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_BlackIntervalList);
            while (decoder.getOffset() < listEndOffset)
                ILOG.J2CsMapping.Collections.Collections.Add(blackIntervalList_,decodeRepetitiveInterval(decoder));
            decoder.finishNestedTlvs(listEndOffset);

            decoder.finishNestedTlvs(endOffset);
        }
Пример #4
0
        /// <summary>
        /// Decode the name as NDN-TLV and set the fields in name.
        /// </summary>
        ///
        /// <param name="name">The name object whose fields are set.</param>
        /// <param name="signedPortionBeginOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest). If you are not decoding in order to verify, you can ignore this returned value.</param>
        /// <param name="signedPortionEndOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest). If you are not decoding in order to verify, you can ignore this returned value.</param>
        /// <param name="decoder">The decoder with the input to decode.</param>
        /// <param name="copy">unchanged while the Blob values are used.</param>
        /// <exception cref="EncodingException"></exception>
        private static void decodeName(Name name, int[] signedPortionBeginOffset,
				int[] signedPortionEndOffset, TlvDecoder decoder, bool copy)
        {
            name.clear();

            int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Name);

            signedPortionBeginOffset[0] = decoder.getOffset();
            // In case there are no components, set signedPortionEndOffset arbitrarily.
            signedPortionEndOffset[0] = signedPortionBeginOffset[0];

            while (decoder.getOffset() < endOffset) {
                signedPortionEndOffset[0] = decoder.getOffset();
                name.append(decodeNameComponent(decoder, copy));
            }

            decoder.finishNestedTlvs(endOffset);
        }
Пример #5
0
        /// <summary>
        /// Decode the name component as NDN-TLV and return the component. This handles
        /// different component types such as ImplicitSha256DigestComponent.
        /// </summary>
        ///
        /// <param name="decoder">The decoder with the input to decode.</param>
        /// <param name="copy">unchanged while the Blob values are used.</param>
        /// <returns>A new Name.Component.</returns>
        /// <exception cref="EncodingException"></exception>
        private static Name.Component decodeNameComponent(TlvDecoder decoder,
				bool copy)
        {
            int savePosition = decoder.getOffset();
            int type = decoder.readVarNumber();
            // Restore the position.
            decoder.seek(savePosition);

            Blob value_ren = new Blob(decoder.readBlobTlv(type), copy);
            if (type == net.named_data.jndn.encoding.tlv.Tlv.ImplicitSha256DigestComponent)
                return net.named_data.jndn.Name.Component.fromImplicitSha256Digest(value_ren);
            else
                return new Name.Component(value_ren);
        }
Пример #6
0
        private static void decodeExclude(Exclude exclude, TlvDecoder decoder,
				bool copy)
        {
            int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Exclude);

            exclude.clear();
            while (decoder.getOffset() < endOffset) {
                if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Any, endOffset)) {
                    // Read past the Any TLV.
                    decoder.readBooleanTlv(net.named_data.jndn.encoding.tlv.Tlv.Any, endOffset);
                    exclude.appendAny();
                } else
                    exclude.appendComponent(decodeNameComponent(decoder, copy));
            }

            decoder.finishNestedTlvs(endOffset);
        }
Пример #7
0
        private static void decodeKeyLocator(int expectedType,
				KeyLocator keyLocator, TlvDecoder decoder, bool copy)
        {
            int endOffset = decoder.readNestedTlvsStart(expectedType);

            keyLocator.clear();

            if (decoder.getOffset() == endOffset)
                // The KeyLocator is omitted, so leave the fields as none.
                return;

            if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Name, endOffset)) {
                // KeyLocator is a Name.
                keyLocator.setType(net.named_data.jndn.KeyLocatorType.KEYNAME);
                decodeName(keyLocator.getKeyName(), new int[1], new int[1],
                        decoder, copy);
            } else if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.KeyLocatorDigest, endOffset)) {
                // KeyLocator is a KeyLocatorDigest.
                keyLocator.setType(net.named_data.jndn.KeyLocatorType.KEY_LOCATOR_DIGEST);
                keyLocator.setKeyData(new Blob(decoder
                        .readBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.KeyLocatorDigest), copy));
            } else
                throw new EncodingException(
                        "decodeKeyLocator: Unrecognized key locator type");

            decoder.finishNestedTlvs(endOffset);
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <summary>
        /// Decode input as an interest in  NDN-TLV and set the fields of the interest
        /// object.
        /// </summary>
        ///
        /// <param name="interest">The Interest object whose fields are updated.</param>
        /// <param name="input"></param>
        /// <param name="signedPortionBeginOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest).</param>
        /// <param name="signedPortionEndOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest).</param>
        /// <param name="copy">unchanged while the Blob values are used.</param>
        /// <exception cref="EncodingException">For invalid encoding.</exception>
        public override void decodeInterest(Interest interest, ByteBuffer input,
				int[] signedPortionBeginOffset, int[] signedPortionEndOffset,
				bool copy)
        {
            TlvDecoder decoder = new TlvDecoder(input);

            int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Interest);
            decodeName(interest.getName(), signedPortionBeginOffset,
                    signedPortionEndOffset, decoder, copy);
            if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Selectors, endOffset))
                decodeSelectors(interest, decoder, copy);
            // Require a Nonce, but don't force it to be 4 bytes.
            ByteBuffer nonce = decoder.readBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Nonce);
            interest.setInterestLifetimeMilliseconds(decoder
                    .readOptionalNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.InterestLifetime,
                            endOffset));

            if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Data, endOffset)) {
                // Get the bytes of the Link TLV.
                int linkBeginOffset = decoder.getOffset();
                int linkEndOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Data);
                decoder.seek(linkEndOffset);

                interest.setLinkWireEncoding(
                        new Blob(decoder.getSlice(linkBeginOffset, linkEndOffset),
                                copy), this);
            } else
                interest.unsetLink();
            interest.setSelectedDelegationIndex((int) decoder
                    .readOptionalNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SelectedDelegation,
                            endOffset));
            if (interest.getSelectedDelegationIndex() >= 0 && !interest.hasLink())
                throw new EncodingException(
                        "Interest has a selected delegation, but no link object");

            // Set the nonce last because setting other interest fields clears it.
            interest.setNonce(new Blob(nonce, copy));

            decoder.finishNestedTlvs(endOffset);
        }
Пример #10
0
        /// <summary>
        /// Decode input as a sequence of NDN-TLV Delegation and set the fields of the
        /// delegationSet object. Note that the sequence of Delegation does not have an
        /// outer TLV type and length because it is intended to use the type and length
        /// of a Data packet's Content. This ignores any elements after the sequence
        /// of Delegation and before input.limit().
        /// </summary>
        ///
        /// <param name="delegationSet">The DelegationSet 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 decodeDelegationSet(DelegationSet delegationSet,
				ByteBuffer input, bool copy)
        {
            TlvDecoder decoder = new TlvDecoder(input);
            int endOffset = input.limit();

            delegationSet.clear();
            while (decoder.getOffset() < endOffset) {
                decoder.readTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Link_Delegation);
                int preference = (int) decoder
                        .readNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Link_Preference);
                Name name = new Name();
                decodeName(name, new int[1], new int[1], decoder, copy);

                // Add unsorted to preserve the order so that Interest selected delegation
                // index will work.
                delegationSet.addUnsorted(preference, name);
            }
        }
Пример #11
0
        /// <summary>
        /// Decode input as a data packet in NDN-TLV and set the fields in the data
        /// object.
        /// </summary>
        ///
        /// <param name="data">The Data object whose fields are updated.</param>
        /// <param name="input"></param>
        /// <param name="signedPortionBeginOffset">If you are not decoding in order to verify, you can call decodeData(data, input) to ignore this returned value.</param>
        /// <param name="signedPortionEndOffset">not decoding in order to verify, you can call decodeData(data, input) to ignore this returned value.</param>
        /// <param name="copy">unchanged while the Blob values are used.</param>
        /// <exception cref="EncodingException">For invalid encoding.</exception>
        public override void decodeData(Data data, ByteBuffer input,
				int[] signedPortionBeginOffset, int[] signedPortionEndOffset,
				bool copy)
        {
            TlvDecoder decoder = new TlvDecoder(input);

            int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Data);
            signedPortionBeginOffset[0] = decoder.getOffset();

            decodeName(data.getName(), new int[1], new int[1], decoder, copy);
            decodeMetaInfo(data.getMetaInfo(), decoder, copy);
            data.setContent(new Blob(decoder.readBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Content), copy));
            decodeSignatureInfo(data, decoder, copy);

            signedPortionEndOffset[0] = decoder.getOffset();
            data.getSignature().setSignature(
                    new Blob(decoder.readBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureValue), copy));

            decoder.finishNestedTlvs(endOffset);
        }
Пример #12
0
        /// <summary>
        /// Continue scanning input starting from offset_ to find the element end.
        /// If the end of the element which started at offset 0 is found, this returns
        /// true and getOffset() is the length of the element.  Otherwise, this returns
        /// false which means you should read more into input and call again.
        /// </summary>
        ///
        /// <param name="input">You have to pass in input each time because the buffer could be reallocated.</param>
        /// <returns>true if found the element end, false if not.</returns>
        public bool findElementEnd(ByteBuffer input)
        {
            if (gotElementEnd_)
                // Someone is calling when we already got the end.
                return true;

            TlvDecoder decoder = new TlvDecoder(input);

            while (true) {
                if (offset_ >= input.limit())
                    // All the cases assume we have some input. Return and wait for more.
                    return false;

                if (state_ == TlvStructureDecoder.READ_TYPE) {
                    int firstOctet = (int) input.get(offset_) & 0xff;
                    offset_ += 1;
                    if (firstOctet < 253)
                        // The value is simple, so we can skip straight to reading the length.
                        state_ = TlvStructureDecoder.READ_LENGTH;
                    else {
                        // Set up to skip the type bytes.
                        if (firstOctet == 253)
                            nBytesToRead_ = 2;
                        else if (firstOctet == 254)
                            nBytesToRead_ = 4;
                        else
                            // value == 255.
                            nBytesToRead_ = 8;

                        state_ = TlvStructureDecoder.READ_TYPE_BYTES;
                    }
                } else if (state_ == TlvStructureDecoder.READ_TYPE_BYTES) {
                    int nRemainingBytes = input.limit() - offset_;
                    if (nRemainingBytes < nBytesToRead_) {
                        // Need more.
                        offset_ += nRemainingBytes;
                        nBytesToRead_ -= nRemainingBytes;
                        return false;
                    }

                    // Got the type bytes. Move on to read the length.
                    offset_ += nBytesToRead_;
                    state_ = TlvStructureDecoder.READ_LENGTH;
                } else if (state_ == TlvStructureDecoder.READ_LENGTH) {
                    int firstOctet_0 = (int) input.get(offset_) & 0xff;
                    offset_ += 1;
                    if (firstOctet_0 < 253) {
                        // The value is simple, so we can skip straight to reading
                        //  the value bytes.
                        nBytesToRead_ = firstOctet_0;
                        if (nBytesToRead_ == 0) {
                            // No value bytes to read. We're finished.
                            gotElementEnd_ = true;
                            return true;
                        }

                        state_ = TlvStructureDecoder.READ_VALUE_BYTES;
                    } else {
                        // We need to read the bytes in the extended encoding of
                        //  the length.
                        if (firstOctet_0 == 253)
                            nBytesToRead_ = 2;
                        else if (firstOctet_0 == 254)
                            nBytesToRead_ = 4;
                        else
                            // value == 255.
                            nBytesToRead_ = 8;

                        // We need to use firstOctet in the next state.
                        firstOctet_ = firstOctet_0;
                        state_ = TlvStructureDecoder.READ_LENGTH_BYTES;
                    }
                } else if (state_ == TlvStructureDecoder.READ_LENGTH_BYTES) {
                    int nRemainingBytes_1 = input.limit() - offset_;
                    if (!useHeaderBuffer_ && nRemainingBytes_1 >= nBytesToRead_) {
                        // We don't have to use the headerBuffer. Set nBytesToRead.
                        decoder.seek(offset_);

                        nBytesToRead_ = decoder.readExtendedVarNumber(firstOctet_);
                        // Update offset_ to the decoder's offset after reading.
                        offset_ = decoder.getOffset();
                    } else {
                        useHeaderBuffer_ = true;

                        int nNeededBytes = nBytesToRead_ - headerBuffer_.position();
                        if (nNeededBytes > nRemainingBytes_1) {
                            // We can't get all of the header bytes from this input.
                            // Save in headerBuffer.
                            if (headerBuffer_.position() + nRemainingBytes_1 > headerBuffer_
                                    .limit())
                                // We don't expect this to happen.
                                throw new Exception(
                                        "Cannot store more header bytes than the size of headerBuffer");
                            ByteBuffer remainingInput = input.duplicate();
                            remainingInput.position(offset_);
                            headerBuffer_.put(remainingInput);
                            offset_ += nRemainingBytes_1;

                            return false;
                        }

                        // Copy the remaining bytes into headerBuffer, read the
                        //   length and set nBytesToRead.
                        if (headerBuffer_.position() + nNeededBytes > headerBuffer_
                                .limit())
                            // We don't expect this to happen.
                            throw new Exception(
                                    "Cannot store more header bytes than the size of headerBuffer");
                        ByteBuffer remainingLengthBytes = input.duplicate();
                        remainingLengthBytes.position(offset_);
                        remainingLengthBytes.limit(offset_ + nNeededBytes);
                        headerBuffer_.put(remainingLengthBytes);
                        offset_ += nNeededBytes;

                        // Use a local decoder just for the headerBuffer.
                        headerBuffer_.flip();
                        TlvDecoder bufferDecoder = new TlvDecoder(headerBuffer_);
                        // Replace nBytesToRead with the length of the value.
                        nBytesToRead_ = bufferDecoder
                                .readExtendedVarNumber(firstOctet_);
                    }

                    if (nBytesToRead_ == 0) {
                        // No value bytes to read. We're finished.
                        gotElementEnd_ = true;
                        return true;
                    }

                    // Get ready to read the value bytes.
                    state_ = TlvStructureDecoder.READ_VALUE_BYTES;
                } else if (state_ == TlvStructureDecoder.READ_VALUE_BYTES) {
                    int nRemainingBytes_2 = input.limit() - offset_;
                    if (nRemainingBytes_2 < nBytesToRead_) {
                        // Need more.
                        offset_ += nRemainingBytes_2;
                        nBytesToRead_ -= nRemainingBytes_2;
                        return false;
                    }

                    // Got the bytes. We're finished.
                    offset_ += nBytesToRead_;
                    gotElementEnd_ = true;
                    return true;
                } else
                    // We don't expect this to happen.
                    throw new Exception("findElementEnd: unrecognized state");
            }
        }