management: add FaceQueryFilter type
refs #2085
Change-Id: I3d2628f5738dad763baa9cd199599372aed4e23d
diff --git a/src/encoding/tlv-nfd.hpp b/src/encoding/tlv-nfd.hpp
index 9f7d5f8..91d7c11 100644
--- a/src/encoding/tlv-nfd.hpp
+++ b/src/encoding/tlv-nfd.hpp
@@ -61,9 +61,11 @@
FaceStatus = 128,
LocalUri = 129,
ChannelStatus = 130,
+ UriScheme = 131,
FaceScope = 132,
FacePersistency = 133,
LinkType = 134,
+ FaceQueryFilter = 150,
FaceEventNotification = 192,
FaceEventKind = 193,
diff --git a/src/management/nfd-face-query-filter.cpp b/src/management/nfd-face-query-filter.cpp
new file mode 100644
index 0000000..39c5240
--- /dev/null
+++ b/src/management/nfd-face-query-filter.cpp
@@ -0,0 +1,344 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "nfd-face-query-filter.hpp"
+
+namespace ndn {
+namespace nfd {
+
+FaceQueryFilter::FaceQueryFilter()
+ : m_hasFaceId(false)
+ , m_hasUriScheme(false)
+ , m_hasRemoteUri(false)
+ , m_hasLocalUri(false)
+ , m_hasFaceScope(false)
+ , m_hasFacePersistency(false)
+ , m_hasLinkType(false)
+{
+}
+
+FaceQueryFilter::FaceQueryFilter(const Block& block)
+{
+ this->wireDecode(block);
+}
+
+template<bool T>
+size_t
+FaceQueryFilter::wireEncode(EncodingImpl<T>& encoder) const
+{
+ size_t totalLength = 0;
+
+ if (m_hasLinkType) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::LinkType, m_linkType);
+ }
+
+ if (m_hasFacePersistency) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FacePersistency, m_facePersistency);
+ }
+
+ if (m_hasFaceScope) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceScope, m_faceScope);
+ }
+
+ if (m_hasLocalUri) {
+ totalLength += prependByteArrayBlock(encoder, tlv::nfd::LocalUri,
+ reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+ }
+
+ if (m_hasRemoteUri) {
+ totalLength += prependByteArrayBlock(encoder, tlv::nfd::Uri,
+ reinterpret_cast<const uint8_t*>(m_remoteUri.c_str()), m_remoteUri.size());
+ }
+
+ if (m_hasUriScheme) {
+ totalLength += prependByteArrayBlock(encoder, tlv::nfd::UriScheme,
+ reinterpret_cast<const uint8_t*>(m_uriScheme.c_str()), m_uriScheme.size());
+ }
+
+ if (m_hasFaceId) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceId, m_faceId);
+ }
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::FaceQueryFilter);
+ return totalLength;
+}
+
+template size_t
+FaceQueryFilter::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+FaceQueryFilter::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+FaceQueryFilter::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+FaceQueryFilter::wireDecode(const Block& block)
+{
+ //all fields are optional
+ if (block.type() != tlv::nfd::FaceQueryFilter) {
+ throw Error("expecting FaceQueryFilter block");
+ }
+
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
+ m_faceId = readNonNegativeInteger(*val);
+ m_hasFaceId = true;
+ ++val;
+ }
+ else {
+ m_hasFaceId = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::UriScheme) {
+ m_uriScheme.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ m_hasUriScheme = true;
+ ++val;
+ }
+ else {
+ m_hasUriScheme = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Uri) {
+ m_remoteUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ m_hasRemoteUri = true;
+ ++val;
+ }
+ else {
+ m_hasRemoteUri = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
+ m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ m_hasLocalUri = true;
+ ++val;
+ }
+ else {
+ m_hasLocalUri = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceScope) {
+ m_faceScope = static_cast<FaceScope>(readNonNegativeInteger(*val));
+ m_hasFaceScope = true;
+ ++val;
+ }
+ else {
+ m_hasFaceScope = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FacePersistency) {
+ m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
+ m_hasFacePersistency = true;
+ ++val;
+ }
+ else {
+ m_hasFacePersistency = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LinkType) {
+ m_linkType = static_cast<LinkType>(readNonNegativeInteger(*val));
+ m_hasLinkType = true;
+ ++val;
+ }
+ else {
+ m_hasLinkType = false;
+ }
+
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setFaceId(uint64_t faceId)
+{
+ m_wire.reset();
+ m_faceId = faceId;
+ m_hasFaceId = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetFaceId()
+{
+ m_wire.reset();
+ m_hasFaceId = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setUriScheme(const std::string& uriScheme)
+{
+ m_wire.reset();
+ m_uriScheme = uriScheme;
+ m_hasUriScheme = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetUriScheme()
+{
+ m_wire.reset();
+ m_hasUriScheme = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setRemoteUri(const std::string& remoteUri)
+{
+ m_wire.reset();
+ m_remoteUri = remoteUri;
+ m_hasRemoteUri = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetRemoteUri()
+{
+ m_wire.reset();
+ m_hasRemoteUri = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setLocalUri(const std::string& localUri)
+{
+ m_wire.reset();
+ m_localUri = localUri;
+ m_hasLocalUri = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetLocalUri()
+{
+ m_wire.reset();
+ m_hasLocalUri = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setFaceScope(FaceScope faceScope)
+{
+ m_wire.reset();
+ m_faceScope = faceScope;
+ m_hasFaceScope = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetFaceScope()
+{
+ m_wire.reset();
+ m_hasFaceScope = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setFacePersistency(FacePersistency facePersistency)
+{
+ m_wire.reset();
+ m_facePersistency = facePersistency;
+ m_hasFacePersistency = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetFacePersistency()
+{
+ m_wire.reset();
+ m_hasFacePersistency = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setLinkType(LinkType linkType)
+{
+ m_wire.reset();
+ m_linkType = linkType;
+ m_hasLinkType = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetLinkType()
+{
+ m_wire.reset();
+ m_hasLinkType = false;
+ return *this;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const FaceQueryFilter& filter)
+{
+ os << "FaceQueryFilter(";
+ if (filter.hasFaceId()) {
+ os << "FaceID: " << filter.getFaceId() << ",\n";
+ }
+
+ if (filter.hasUriScheme()) {
+ os << "UriScheme: " << filter.getUriScheme() << ",\n";
+ }
+
+ if (filter.hasRemoteUri()) {
+ os << "RemoteUri: " << filter.getRemoteUri() << ",\n";
+ }
+
+ if (filter.hasLocalUri()) {
+ os << "LocalUri: " << filter.getLocalUri() << ",\n";
+ }
+
+ if (filter.hasFaceScope()) {
+ os << "FaceScope: " << filter.getFaceScope() << ",\n";
+ }
+
+ if (filter.hasFacePersistency()) {
+ os << "FacePersistency: " << filter.getFacePersistency() << ",\n";
+ }
+
+ if (filter.hasLinkType()) {
+ os << "LinkType: " << filter.getLinkType() << ",\n";
+ }
+ os << ")";
+ return os;
+}
+
+} // namespace nfd
+} // namespace ndn
+
diff --git a/src/management/nfd-face-query-filter.hpp b/src/management/nfd-face-query-filter.hpp
new file mode 100644
index 0000000..5de02fe
--- /dev/null
+++ b/src/management/nfd-face-query-filter.hpp
@@ -0,0 +1,230 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MANAGEMENT_NFD_FACE_QUERY_FILTER_HPP
+#define NDN_MANAGEMENT_NFD_FACE_QUERY_FILTER_HPP
+
+#include "nfd-face-traits.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \brief represents Face Query Filter
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Query-Operation
+ */
+class FaceQueryFilter
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ FaceQueryFilter();
+
+ explicit
+ FaceQueryFilter(const Block& block);
+
+ /** \brief prepend FaceQueryFilter to the encoder
+ */
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& encoder) const;
+
+ /** \brief encode FaceQueryFilter
+ */
+ const Block&
+ wireEncode() const;
+
+ /** \brief decode FaceQueryFilter
+ */
+ void
+ wireDecode(const Block& wire);
+
+public: // getters & setters
+
+ bool
+ hasFaceId() const
+ {
+ return m_hasFaceId;
+ }
+
+ uint64_t
+ getFaceId() const
+ {
+ BOOST_ASSERT(this->hasFaceId());
+ return m_faceId;
+ }
+
+ FaceQueryFilter&
+ setFaceId(uint64_t faceId);
+
+ FaceQueryFilter&
+ unsetFaceId();
+
+ bool
+ hasUriScheme() const
+ {
+ return m_hasUriScheme;
+ }
+
+ const std::string&
+ getUriScheme() const
+ {
+ BOOST_ASSERT(this->hasUriScheme());
+ return m_uriScheme;
+ }
+
+ FaceQueryFilter&
+ setUriScheme(const std::string& uriScheme);
+
+ FaceQueryFilter&
+ unsetUriScheme();
+
+ bool
+ hasRemoteUri() const
+ {
+ return m_hasRemoteUri;
+ }
+
+ const std::string&
+ getRemoteUri() const
+ {
+ BOOST_ASSERT(this->hasRemoteUri());
+ return m_remoteUri;
+ }
+
+ FaceQueryFilter&
+ setRemoteUri(const std::string& remoteUri);
+
+ FaceQueryFilter&
+ unsetRemoteUri();
+
+ bool
+ hasLocalUri() const
+ {
+ return m_hasLocalUri;
+ }
+
+ const std::string&
+ getLocalUri() const
+ {
+ BOOST_ASSERT(this->hasLocalUri());
+ return m_localUri;
+ }
+
+ FaceQueryFilter&
+ setLocalUri(const std::string& localUri);
+
+ FaceQueryFilter&
+ unsetLocalUri();
+
+ bool
+ hasFaceScope() const
+ {
+ return m_hasFaceScope;
+ }
+
+ FaceScope
+ getFaceScope() const
+ {
+ BOOST_ASSERT(this->hasFaceScope());
+ return m_faceScope;
+ }
+
+ FaceQueryFilter&
+ setFaceScope(FaceScope faceScope);
+
+ FaceQueryFilter&
+ unsetFaceScope();
+
+ bool
+ hasFacePersistency() const
+ {
+ return m_hasFacePersistency;
+ }
+
+ FacePersistency
+ getFacePersistency() const
+ {
+ BOOST_ASSERT(this->hasFacePersistency());
+ return m_facePersistency;
+ }
+
+ FaceQueryFilter&
+ setFacePersistency(FacePersistency facePersistency);
+
+ FaceQueryFilter&
+ unsetFacePersistency();
+
+ bool
+ hasLinkType() const
+ {
+ return m_hasLinkType;
+ }
+
+ LinkType
+ getLinkType() const
+ {
+ BOOST_ASSERT(this->hasLinkType());
+ return m_linkType;
+ }
+
+ FaceQueryFilter&
+ setLinkType(LinkType linkType);
+
+ FaceQueryFilter&
+ unsetLinkType();
+
+private:
+ uint64_t m_faceId;
+ std::string m_uriScheme;
+ std::string m_remoteUri;
+ std::string m_localUri;
+ FaceScope m_faceScope;
+ FacePersistency m_facePersistency;
+ LinkType m_linkType;
+
+ bool m_hasFaceId;
+ bool m_hasUriScheme;
+ bool m_hasRemoteUri;
+ bool m_hasLocalUri;
+ bool m_hasFaceScope;
+ bool m_hasFacePersistency;
+ bool m_hasLinkType;
+
+ mutable Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const FaceQueryFilter& filter);
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NFD_FACE_QUERY_FILTER_HPP
diff --git a/tests/unit-tests/management/test-nfd-face-query-filter.cpp b/tests/unit-tests/management/test-nfd-face-query-filter.cpp
new file mode 100644
index 0000000..575c475
--- /dev/null
+++ b/tests/unit-tests/management/test-nfd-face-query-filter.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "management/nfd-face-query-filter.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace nfd {
+
+BOOST_AUTO_TEST_SUITE(ManagementTestNfdFaceQueryFilter)
+
+BOOST_AUTO_TEST_CASE(Encode)
+{
+ FaceQueryFilter filter1;
+ BOOST_CHECK_EQUAL(filter1.hasFaceId(), false);
+ BOOST_CHECK_EQUAL(filter1.hasUriScheme(), false);
+ BOOST_CHECK_EQUAL(filter1.hasRemoteUri(), false);
+ BOOST_CHECK_EQUAL(filter1.hasLocalUri(), false);
+ BOOST_CHECK_EQUAL(filter1.hasFaceScope(), false);
+ BOOST_CHECK_EQUAL(filter1.hasFacePersistency(), false);
+ BOOST_CHECK_EQUAL(filter1.hasLinkType(), false);
+
+ filter1.setFaceId(100)
+ .setUriScheme("tcp4")
+ .setRemoteUri("tcp4://192.0.2.1:6363")
+ .setLocalUri("tcp4://192.0.2.2:55555")
+ .setFaceScope(FACE_SCOPE_LOCAL)
+ .setFacePersistency(FACE_PERSISTENCY_ON_DEMAND)
+ .setLinkType(LINK_TYPE_MULTI_ACCESS);
+
+ Block wire;
+ BOOST_REQUIRE_NO_THROW(wire = filter1.wireEncode());
+
+ // These octets are obtained by the snippet below.
+ // This check is intended to detect unexpected encoding change in the future.
+ // for (Buffer::const_iterator it = wire.begin(); it != wire.end(); ++it) {
+ // printf("0x%02x, ", *it);
+ // }
+ static const uint8_t expected[] = {
+ 0x96, 0x41, 0x69, 0x01, 0x64, 0x83, 0x04, 0x74, 0x63, 0x70,
+ 0x34, 0x72, 0x15, 0x74, 0x63, 0x70, 0x34, 0x3a, 0x2f, 0x2f,
+ 0x31, 0x39, 0x32, 0x2e, 0x30, 0x2e, 0x32, 0x2e, 0x31, 0x3a,
+ 0x36, 0x33, 0x36, 0x33, 0x81, 0x16, 0x74, 0x63, 0x70, 0x34,
+ 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32, 0x2e, 0x30, 0x2e, 0x32,
+ 0x2e, 0x32, 0x3a, 0x35, 0x35, 0x35, 0x35, 0x35, 0x84, 0x01,
+ 0x01, 0x85, 0x01, 0x01, 0x86, 0x01, 0x01,
+ };
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
+ wire.begin(), wire.end());
+
+ BOOST_REQUIRE_NO_THROW(FaceQueryFilter(wire));
+
+ FaceQueryFilter filter2(wire);
+ BOOST_CHECK_EQUAL(filter1.getFaceId(), filter2.getFaceId());
+ BOOST_CHECK_EQUAL(filter1.getUriScheme(), filter2.getUriScheme());
+ BOOST_CHECK_EQUAL(filter1.getRemoteUri(), filter2.getRemoteUri());
+ BOOST_CHECK_EQUAL(filter1.getLocalUri(), filter2.getLocalUri());
+ BOOST_CHECK_EQUAL(filter1.getFaceScope(), filter2.getFaceScope());
+ BOOST_CHECK_EQUAL(filter1.getFacePersistency(), filter2.getFacePersistency());
+ BOOST_CHECK_EQUAL(filter1.getLinkType(), filter2.getLinkType());
+
+ std::ostringstream os;
+ os << filter2;
+ BOOST_CHECK_EQUAL(os.str(), "FaceQueryFilter(FaceID: 100,\n"
+ "UriScheme: tcp4,\n"
+ "RemoteUri: tcp4://192.0.2.1:6363,\n"
+ "LocalUri: tcp4://192.0.2.2:55555,\n"
+ "FaceScope: local,\n"
+ "FacePersistency: on-demand,\n"
+ "LinkType: multi-access,\n"
+ ")");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace nfd
+} // namespace ndn