Block::Block(const EncodingBuffer& buffer) : m_buffer(buffer.m_buffer) , m_begin(buffer.begin()) , m_end(buffer.end()) , m_size(m_end - m_begin) { m_value_begin = m_begin; m_value_end = m_end; m_type = Tlv::readType(m_value_begin, m_value_end); uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end); if (length != static_cast<uint64_t>(m_value_end - m_value_begin)) { throw Tlv::Error("TLV length doesn't match buffer length"); } }
shared_ptr<IdentityCertificate> Pib::prepareCertificate(const Name& keyName, const KeyParams& keyParams, const time::system_clock::TimePoint& notBefore, const time::system_clock::TimePoint& notAfter, const Name& signerName) { // Generate mgmt key m_tpm->generateKeyPairInTpm(keyName, keyParams); shared_ptr<PublicKey> publicKey = m_tpm->getPublicKeyFromTpm(keyName); // Set mgmt cert auto certificate = make_shared<IdentityCertificate>(); Name certName = keyName.getPrefix(-1); certName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion(); certificate->setName(certName); certificate->setNotBefore(notBefore); certificate->setNotAfter(notAfter); certificate->setPublicKeyInfo(*publicKey); CertificateSubjectDescription subjectName(oid::ATTRIBUTE_NAME, keyName.getPrefix(-1).toUri()); certificate->addSubjectDescription(subjectName); certificate->encode(); Name signingKeyName; KeyLocator keyLocator; if (signerName == EMPTY_SIGNER_NAME) { // Self-sign mgmt cert keyLocator = KeyLocator(certificate->getName().getPrefix(-1)); signingKeyName = keyName; } else { keyLocator = KeyLocator(signerName.getPrefix(-1)); signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(signerName); } SignatureSha256WithRsa signature(keyLocator); certificate->setSignature(signature); EncodingBuffer encoder; certificate->wireEncode(encoder, true); Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(), signingKeyName, DIGEST_ALGORITHM_SHA256); certificate->wireEncode(encoder, signatureValue); return certificate; }
BOOST_FIXTURE_TEST_CASE(StatusDataset, DispatcherFixture) { static Block smallBlock("\x81\x01\0x01", 3); static Block largeBlock = [] () -> Block { EncodingBuffer encoder; for (size_t i = 0; i < 2500; ++i) { encoder.prependByte(1); } encoder.prependVarNumber(2500); encoder.prependVarNumber(129); return encoder.block(); }(); dispatcher.addStatusDataset("test/small", makeTestAuthorization(), [] (const Name& prefix, const Interest& interest, StatusDatasetContext context) { context.append(smallBlock); context.append(smallBlock); context.append(smallBlock); context.end(); }); dispatcher.addStatusDataset("test/large", makeTestAuthorization(), [] (const Name& prefix, const Interest& interest, StatusDatasetContext context) { context.append(largeBlock); context.append(largeBlock); context.append(largeBlock); context.end(); }); dispatcher.addStatusDataset("test/reject", makeTestAuthorization(), [] (const Name& prefix, const Interest& interest, StatusDatasetContext context) { context.reject(); }); dispatcher.addTopPrefix("/root"); advanceClocks(time::milliseconds(1)); face->sentDatas.clear(); face->receive(*util::makeInterest("/root/test/small/%80%00")); // returns 403 face->receive(*util::makeInterest("/root/test/small/%80%00/invalid")); // returns 403 face->receive(*util::makeInterest("/root/test/small/%80%00/silent")); // silently ignored advanceClocks(time::milliseconds(1), 20); BOOST_CHECK_EQUAL(face->sentDatas.size(), 2); BOOST_CHECK(face->sentDatas[0].getContentType() == tlv::ContentType_Blob); BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[0].getContent().blockFromValue()).getCode(), 403); BOOST_CHECK(face->sentDatas[1].getContentType() == tlv::ContentType_Blob); BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[1].getContent().blockFromValue()).getCode(), 403); face->sentDatas.clear(); face->receive(*util::makeInterest("/root/test/small/valid")); advanceClocks(time::milliseconds(1), 10); BOOST_CHECK_EQUAL(face->sentDatas.size(), 1); face->receive(*util::makeInterest(Name("/root/test/small/valid").appendVersion(10))); // should be ignored face->receive(*util::makeInterest(Name("/root/test/small/valid").appendSegment(20))); // should be ignored advanceClocks(time::milliseconds(1), 10); BOOST_CHECK_EQUAL(face->sentDatas.size(), 1); Block content = face->sentDatas[0].getContent(); BOOST_CHECK_NO_THROW(content.parse()); BOOST_CHECK_EQUAL(content.elements().size(), 3); BOOST_CHECK(content.elements()[0] == smallBlock); BOOST_CHECK(content.elements()[1] == smallBlock); BOOST_CHECK(content.elements()[2] == smallBlock); face->sentDatas.clear(); face->receive(*util::makeInterest("/root/test/large/valid")); advanceClocks(time::milliseconds(1), 10); BOOST_CHECK_EQUAL(face->sentDatas.size(), 2); const auto& datas = face->sentDatas; content = [&datas] () -> Block { EncodingBuffer encoder; size_t valueLength = encoder.prependByteArray(datas[1].getContent().value(), datas[1].getContent().value_size()); valueLength += encoder.prependByteArray(datas[0].getContent().value(), datas[0].getContent().value_size()); encoder.prependVarNumber(valueLength); encoder.prependVarNumber(tlv::Content); return encoder.block(); }(); BOOST_CHECK_NO_THROW(content.parse()); BOOST_CHECK_EQUAL(content.elements().size(), 3); BOOST_CHECK(content.elements()[0] == largeBlock); BOOST_CHECK(content.elements()[1] == largeBlock); BOOST_CHECK(content.elements()[2] == largeBlock); face->sentDatas.clear(); face->receive(*util::makeInterest("/root/test/reject/%80%00/valid")); // returns nack advanceClocks(time::milliseconds(1)); BOOST_CHECK_EQUAL(face->sentDatas.size(), 1); BOOST_CHECK(face->sentDatas[0].getContentType() == tlv::ContentType_Nack); BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[0].getContent().blockFromValue()).getCode(), 400); }
BOOST_FIXTURE_TEST_CASE(StatusDataset, DispatcherFixture) { static Block smallBlock("\x81\x01\0x01", 3); static Block largeBlock = [] () -> Block { EncodingBuffer encoder; for (size_t i = 0; i < 2500; ++i) { encoder.prependByte(1); } encoder.prependVarNumber(2500); encoder.prependVarNumber(129); return encoder.block(); }(); dispatcher.addStatusDataset("test/small", makeTestAuthorization(), [] (const Name& prefix, const Interest& interest, StatusDatasetContext& context) { context.append(smallBlock); context.append(smallBlock); context.append(smallBlock); context.end(); }); dispatcher.addStatusDataset("test/large", makeTestAuthorization(), [] (const Name& prefix, const Interest& interest, StatusDatasetContext& context) { context.append(largeBlock); context.append(largeBlock); context.append(largeBlock); context.end(); }); dispatcher.addStatusDataset("test/reject", makeTestAuthorization(), [] (const Name& prefix, const Interest& interest, StatusDatasetContext& context) { context.reject(); }); dispatcher.addTopPrefix("/root"); advanceClocks(time::milliseconds(1)); face.sentData.clear(); face.receive(*util::makeInterest("/root/test/small/%80%00")); // returns 403 face.receive(*util::makeInterest("/root/test/small/%80%00/invalid")); // returns 403 face.receive(*util::makeInterest("/root/test/small/%80%00/silent")); // silently ignored advanceClocks(time::milliseconds(1), 20); BOOST_CHECK_EQUAL(face.sentData.size(), 2); BOOST_CHECK(face.sentData[0].getContentType() == tlv::ContentType_Blob); BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 403); BOOST_CHECK(face.sentData[1].getContentType() == tlv::ContentType_Blob); BOOST_CHECK_EQUAL(ControlResponse(face.sentData[1].getContent().blockFromValue()).getCode(), 403); face.sentData.clear(); auto interestSmall = *util::makeInterest("/root/test/small/valid"); face.receive(interestSmall); advanceClocks(time::milliseconds(1), 10); // one data packet is generated and sent to both places BOOST_CHECK_EQUAL(face.sentData.size(), 1); BOOST_CHECK_EQUAL(storage.size(), 1); auto fetchedData = storage.find(interestSmall); BOOST_REQUIRE(fetchedData != nullptr); BOOST_CHECK(face.sentData[0].wireEncode() == fetchedData->wireEncode()); face.receive(*util::makeInterest(Name("/root/test/small/valid").appendVersion(10))); // should be ignored face.receive(*util::makeInterest(Name("/root/test/small/valid").appendSegment(20))); // should be ignored advanceClocks(time::milliseconds(1), 10); BOOST_CHECK_EQUAL(face.sentData.size(), 1); BOOST_CHECK_EQUAL(storage.size(), 1); Block content = face.sentData[0].getContent(); BOOST_CHECK_NO_THROW(content.parse()); BOOST_CHECK_EQUAL(content.elements().size(), 3); BOOST_CHECK(content.elements()[0] == smallBlock); BOOST_CHECK(content.elements()[1] == smallBlock); BOOST_CHECK(content.elements()[2] == smallBlock); storage.erase("/", true); // clear the storage face.sentData.clear(); face.receive(*util::makeInterest("/root/test/large/valid")); advanceClocks(time::milliseconds(1), 10); // two data packets are generated, the first one will be sent to both places // while the second one will only be inserted into the in-memory storage BOOST_CHECK_EQUAL(face.sentData.size(), 1); BOOST_CHECK_EQUAL(storage.size(), 2); // segment0 should be sent through the face const auto& component = face.sentData[0].getName().at(-1); BOOST_CHECK(component.isSegment()); BOOST_CHECK_EQUAL(component.toSegment(), 0); std::vector<Data> dataInStorage; std::copy(storage.begin(), storage.end(), std::back_inserter(dataInStorage)); // the Data sent through the face should be the same as the first Data in the storage BOOST_CHECK_EQUAL(face.sentData[0].getName(), dataInStorage[0].getName()); BOOST_CHECK(face.sentData[0].getContent() == dataInStorage[0].getContent()); content = [&dataInStorage] () -> Block { EncodingBuffer encoder; size_t valueLength = encoder.prependByteArray(dataInStorage[1].getContent().value(), dataInStorage[1].getContent().value_size()); valueLength += encoder.prependByteArray(dataInStorage[0].getContent().value(), dataInStorage[0].getContent().value_size()); encoder.prependVarNumber(valueLength); encoder.prependVarNumber(tlv::Content); return encoder.block(); }(); BOOST_CHECK_NO_THROW(content.parse()); BOOST_CHECK_EQUAL(content.elements().size(), 3); BOOST_CHECK(content.elements()[0] == largeBlock); BOOST_CHECK(content.elements()[1] == largeBlock); BOOST_CHECK(content.elements()[2] == largeBlock); storage.erase("/", true);// clear the storage face.sentData.clear(); face.receive(*util::makeInterest("/root/test/reject/%80%00/valid")); // returns nack advanceClocks(time::milliseconds(1)); BOOST_CHECK_EQUAL(face.sentData.size(), 1); BOOST_CHECK(face.sentData[0].getContentType() == tlv::ContentType_Nack); BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 400); BOOST_CHECK_EQUAL(storage.size(), 0); // the nack packet will not be inserted into the in-memory storage }