add logger response
Change-Id: I2a2888eaf27671374ba8ed7f36ca2d1ffb736ea4
diff --git a/core/logger-response.cpp b/core/logger-response.cpp
new file mode 100644
index 0000000..cef7e64
--- /dev/null
+++ b/core/logger-response.cpp
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NSL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "logger-response.hpp"
+#include "tlv.hpp"
+
+namespace nsl {
+
+LoggerResponse::LoggerResponse()
+ : m_code(-1)
+{
+}
+
+LoggerResponse::LoggerResponse(int32_t code, const std::string& msg)
+ : m_code(code)
+ , m_msg(msg)
+ , m_dataSeqNo(0)
+{
+}
+
+LoggerResponse::LoggerResponse(const NonNegativeInteger& seqNo)
+ : m_code(0)
+ , m_dataSeqNo(seqNo)
+{
+}
+
+template<ndn::encoding::Tag TAG>
+size_t
+LoggerResponse::wireEncode(ndn::EncodingImpl<TAG>& block) const
+{
+ size_t totalLength = 0;
+
+ if (m_code != 0) {
+ totalLength += block.prependByteArrayBlock(tlv::ResultMsg,
+ reinterpret_cast<const uint8_t*>(m_msg.c_str()),
+ m_msg.size());
+ }
+ else {
+ totalLength += ndn::prependNonNegativeIntegerBlock(block, tlv::DataSeqNo, m_dataSeqNo);
+ }
+ totalLength += ndn::prependNonNegativeIntegerBlock(block, tlv::ResultCode, m_code);
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::LogResponse);
+
+ return totalLength;
+}
+
+template size_t
+LoggerResponse::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>&) const;
+
+template size_t
+LoggerResponse::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>&) const;
+
+
+const Block&
+LoggerResponse::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ ndn::EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ ndn::EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+LoggerResponse::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw Error("The supplied block does not contain wire format");
+ }
+
+ m_wire = wire;
+ m_wire.parse();
+
+ if (m_wire.type() != tlv::LogResponse)
+ throw tlv::Error("Unexpected TLV type when decoding log response");
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+
+ // the first block must be result code
+ if (it != m_wire.elements_end() && it->type() == tlv::ResultCode) {
+ m_code = readNonNegativeInteger(*it);
+ it++;
+ }
+ else
+ throw Error("The first sub-TLV is not ResultCode");
+
+ // the second block could be result msg
+ if (it == m_wire.elements_end())
+ return;
+ else if (it->type() == tlv::ResultMsg) {
+ m_msg = std::string(reinterpret_cast<const char*>(it->value()), it->value_size());
+ it++;
+ }
+ else if (it->type() == tlv::DataSeqNo) {
+ m_dataSeqNo = readNonNegativeInteger(*it);
+ it++;
+ }
+ else
+ throw Error("The second sub-TLV is not ResultMsg");
+
+ if (it != m_wire.elements_end())
+ throw Error("No more sub-TLV in log response");
+}
+
+} // namespace nsl
diff --git a/core/logger-response.hpp b/core/logger-response.hpp
new file mode 100644
index 0000000..8a393e4
--- /dev/null
+++ b/core/logger-response.hpp
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NSL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#ifndef NSL_CORE_LOGGER_RESPONSE_HPP
+#define NSL_CORE_LOGGER_RESPONSE_HPP
+
+#include "common.hpp"
+#include "util/non-negative-integer.hpp"
+#include <ndn-cxx/encoding/buffer.hpp>
+
+namespace nsl {
+
+class LoggerResponse
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+public:
+ LoggerResponse();
+
+ LoggerResponse(int32_t resultCode, const std::string& resultMsg);
+
+ LoggerResponse(const NonNegativeInteger& seqNo);
+
+ int32_t
+ getCode() const
+ {
+ return m_code;
+ }
+
+ const std::string&
+ getMsg() const
+ {
+ if (m_code == 0)
+ throw Error("Error msg is not available");
+
+ return m_msg;
+ }
+
+ const NonNegativeInteger&
+ getDataSeqNo() const
+ {
+ if (m_code != 0)
+ throw Error("Data seqNo is not available");
+
+ return m_dataSeqNo;
+ }
+
+ /// @brief Encode to a wire format or estimate wire format
+ template<ndn::encoding::Tag TAG>
+ size_t
+ wireEncode(ndn::EncodingImpl<TAG>& block) const;
+
+ /// @brief Encode to a wire format
+ const Block&
+ wireEncode() const;
+
+ /// @brief Decode from a wire format
+ void
+ wireDecode(const Block& wire);
+
+private:
+ int32_t m_code;
+ std::string m_msg; // optional
+ NonNegativeInteger m_dataSeqNo; // optional
+
+ mutable Block m_wire;
+};
+
+} // namespace nsl
+
+#endif // NSL_CORE_LOGGER_RESPONSE_HPP
diff --git a/core/tlv.hpp b/core/tlv.hpp
index 6dd7cac..56de322 100644
--- a/core/tlv.hpp
+++ b/core/tlv.hpp
@@ -33,7 +33,18 @@
LoggerLeaf = 128, // 0x80
Timestamp = 129, // 0x81
DataSeqNo = 130, // 0x82
- SignerSeqNo = 131 // 0x83
+ SignerSeqNo = 131, // 0x83
+
+ LogResponse = 144, // 0x90
+ ResultCode = 145, // 0x91
+ ResultMsg = 146 // 0x92
+};
+
+enum {
+ LogResponse_Accept = 0,
+ LogResponse_Error_Tree = 1,
+ LogResponse_Error_Policy = 2,
+ LogResponse_Error_Signer = 3
};
} // namespace tlv
diff --git a/tests/core/logger-response.t.cpp b/tests/core/logger-response.t.cpp
new file mode 100644
index 0000000..37ea13a
--- /dev/null
+++ b/tests/core/logger-response.t.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NSL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "logger-response.hpp"
+#include "cryptopp.hpp"
+
+#include "boost-test.hpp"
+
+namespace nsl {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(TestLoggerResponse)
+
+void
+printByte(const uint8_t* buf, size_t size)
+{
+ std::stringstream ss;
+ using namespace CryptoPP;
+ StringSource is(buf, size, true, new HexEncoder(new FileSink(ss), false));
+
+ std::string output = ss.str();
+ for (size_t i = 0; i < output.size(); i++) {
+ std::cerr << "0x" << output.at(i);
+ std::cerr << output.at(++i) << ", ";
+ if ((i + 1) % 32 == 0)
+ std::cerr << std::endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ LoggerResponse response1(5);
+ BOOST_CHECK_EQUAL(response1.getCode(), 0);
+ BOOST_CHECK_EQUAL(response1.getDataSeqNo(), 5);
+
+ LoggerResponse response2(1, "error");
+ BOOST_CHECK_EQUAL(response2.getCode(), 1);
+ BOOST_CHECK_EQUAL(response2.getMsg(), "error");
+}
+
+uint8_t RESPONSE1[] = {
+ 0x90, 0x06,
+ 0x91, 0x01, 0x00,
+ 0x82, 0x01, 0x05
+};
+
+uint8_t RESPONSE2[] = {
+ 0x90, 0x0a,
+ 0x91, 0x01, 0x01,
+ 0x92, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72
+};
+
+BOOST_AUTO_TEST_CASE(Encoding)
+{
+ LoggerResponse response1(5);
+ BOOST_CHECK_EQUAL_COLLECTIONS(response1.wireEncode().wire(),
+ response1.wireEncode().wire() + response1.wireEncode().size(),
+ RESPONSE1, RESPONSE1 + sizeof(RESPONSE1));
+
+ LoggerResponse response2(1, "error");
+ BOOST_CHECK_EQUAL_COLLECTIONS(response2.wireEncode().wire(),
+ response2.wireEncode().wire() + response2.wireEncode().size(),
+ RESPONSE2, RESPONSE2 + sizeof(RESPONSE2));
+}
+
+BOOST_AUTO_TEST_CASE(Decoding)
+{
+ LoggerResponse response1;
+ Block block1(RESPONSE1, sizeof(RESPONSE1));
+ BOOST_REQUIRE_NO_THROW(response1.wireDecode(block1));
+ BOOST_CHECK_EQUAL(response1.getCode(), 0);
+ BOOST_CHECK_EQUAL(response1.getDataSeqNo(), 5);
+
+ LoggerResponse response2;
+ Block block2(RESPONSE2, sizeof(RESPONSE2));
+ BOOST_REQUIRE_NO_THROW(response2.wireDecode(block2));
+ BOOST_CHECK_EQUAL(response2.getCode(), 1);
+ BOOST_CHECK_EQUAL(response2.getMsg(), "error");
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nsl