nfd-control: Adding class of ControlResponse
Change-Id: I596bb3f5470e3d3c6671e74bef991e9b047637c9
refs: #1162
diff --git a/src/encoding/tlv-nfd-control.hpp b/src/encoding/tlv-nfd-control.hpp
new file mode 100644
index 0000000..09bfef3
--- /dev/null
+++ b/src/encoding/tlv-nfd-control.hpp
@@ -0,0 +1,38 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_TLV_NFD_CONTROL_HPP
+#define NDN_TLV_NFD_CONTROL_HPP
+
+namespace ndn {
+namespace tlv {
+namespace nfd_control {
+
+enum {
+ // ControlResponse
+ ControlResponse = 101,
+ StatusCode = 102,
+ StatusText = 103,
+
+ // FIB Management Protocol
+ FibManagementOptions = 104,
+ FaceId = 105,
+ Cost = 106,
+ Strategy = 107,
+
+ // Face Management Protocol
+ FaceManagementOptions = 108
+};
+
+
+} // namespace nfd_control
+} // namespace tlv
+} // namespace ndn
+
+#endif // NDN_TLV_NFD_CONTROL_HPP
diff --git a/src/management/control-response.hpp b/src/management/control-response.hpp
new file mode 100644
index 0000000..b14409c
--- /dev/null
+++ b/src/management/control-response.hpp
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
+#define NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
+
+#include "encoding/block.hpp"
+#include "encoding/tlv-nfd-control.hpp"
+
+namespace ndn {
+
+/**
+ * @brief Class defining abstraction of ControlResponse for NFD Control Protocol
+ *
+ * @see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ */
+class ControlResponse {
+public:
+ struct Error : public Tlv::Error { Error(const std::string &what) : Tlv::Error(what) {} };
+
+ ControlResponse()
+ : m_code(200)
+ {
+ }
+
+ ControlResponse(uint32_t code, const std::string &text)
+ : m_code(code)
+ , m_text(text)
+ {
+ }
+
+ inline uint32_t
+ getCode() const;
+
+ inline void
+ setCode(uint32_t code);
+
+ inline const std::string &
+ getText() const;
+
+ inline void
+ setText(const std::string &text);
+
+ inline const Block&
+ getBody() const;
+
+ inline void
+ setBody(const Block& body);
+
+ inline const Block&
+ wireEncode() const;
+
+ inline void
+ wireDecode(const Block &block);
+
+protected:
+ uint32_t m_code;
+ std::string m_text;
+ Block m_body;
+
+ mutable Block m_wire;
+};
+
+inline uint32_t
+ControlResponse::getCode() const
+{
+ return m_code;
+}
+
+inline void
+ControlResponse::setCode(uint32_t code)
+{
+ m_code = code;
+ m_wire.reset();
+}
+
+inline const std::string &
+ControlResponse::getText() const
+{
+ return m_text;
+}
+
+inline void
+ControlResponse::setText(const std::string &text)
+{
+ m_text = text;
+ m_wire.reset();
+}
+
+inline const Block&
+ControlResponse::getBody() const
+{
+ return m_body;
+}
+
+inline void
+ControlResponse::setBody(const Block& body)
+{
+ m_body = body;
+ m_body.encode(); // will do nothing if already encoded
+ m_wire.reset();
+}
+
+
+inline const Block&
+ControlResponse::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ m_wire = Block(tlv::nfd_control::ControlResponse);
+ m_wire.push_back
+ (nonNegativeIntegerBlock(tlv::nfd_control::StatusCode, m_code));
+
+ m_wire.push_back
+ (dataBlock(tlv::nfd_control::StatusText, m_text.c_str(), m_text.size()));
+
+ if (m_body.hasWire())
+ {
+ m_wire.push_back(m_body);
+ }
+
+ m_wire.encode();
+ return m_wire;
+}
+
+inline void
+ControlResponse::wireDecode(const Block &wire)
+{
+ m_wire = wire;
+ m_wire.parse();
+
+ Block::element_iterator val = m_wire.getAll().begin();
+ if (val == m_wire.getAll().end() ||
+ val->type() != tlv::nfd_control::StatusCode)
+ {
+ throw Error("Incorrect ControlResponse format (StatusCode missing or not the first item)");
+ }
+
+ m_code = readNonNegativeInteger(*val);
+ ++val;
+
+ if (val == m_wire.getAll().end() ||
+ val->type() != tlv::nfd_control::StatusText)
+ {
+ throw Error("Incorrect ControlResponse format (StatusText missing or not the second item)");
+ }
+ m_text.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ ++val;
+
+ if (val != m_wire.getAll().end())
+ m_body = *val;
+ else
+ m_body = Block();
+}
+
+inline std::ostream&
+operator << (std::ostream &os, const ControlResponse &status)
+{
+ os << status.getCode() << " " << status.getText();
+ return os;
+}
+
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
diff --git a/tests/test-nfd-control.cpp b/tests/test-nfd-control.cpp
new file mode 100644
index 0000000..8e282a0
--- /dev/null
+++ b/tests/test-nfd-control.cpp
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <boost/test/unit_test.hpp>
+
+#include "management/control-response.hpp"
+
+#include <boost/test/output_test_stream.hpp>
+
+using namespace std;
+
+namespace ndn {
+
+BOOST_AUTO_TEST_SUITE(TestNfdControl)
+
+const uint8_t TestControlResponse[] = {0x65, 0x17, 0x66, 0x02, 0x01, 0x94, 0x67, 0x11, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64};
+
+BOOST_AUTO_TEST_CASE (ControlResponseEncode)
+{
+ ndn::ControlResponse controlResponse(404, "Nothing not found");
+ const Block &wire = controlResponse.wireEncode();
+
+ BOOST_REQUIRE_EQUAL_COLLECTIONS(TestControlResponse, TestControlResponse+sizeof(TestControlResponse),
+ wire.begin(), wire.end());
+}
+
+BOOST_AUTO_TEST_CASE (ControlResponseDecode)
+{
+ ndn::ControlResponse controlResponse;
+
+ BOOST_REQUIRE_NO_THROW(controlResponse.wireDecode(Block(TestControlResponse, sizeof(TestControlResponse))));
+
+ BOOST_REQUIRE_EQUAL(controlResponse.getCode(), 404);
+ BOOST_REQUIRE_EQUAL(controlResponse.getText(), "Nothing not found");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn