face: Implementation of encode/decode of LocalControlHeader
LocalControlHeader can only be used on faces that are derived from
LocalFace. UnixStreamFace is directly inherited from LocalFace,
TCP face has two specializations: generic TcpFace (strictly not local),
and LocalTcpFace.
refs #1213
Change-Id: I8a158c3bc4bb929eedd15757cfddecc0d1049f9f
diff --git a/daemon/face/local-face.hpp b/daemon/face/local-face.hpp
new file mode 100644
index 0000000..6175b5d
--- /dev/null
+++ b/daemon/face/local-face.hpp
@@ -0,0 +1,179 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NFD_FACE_LOCAL_FACE_HPP
+#define NFD_FACE_LOCAL_FACE_HPP
+
+#include "face.hpp"
+
+namespace nfd {
+
+/* \brief indicates a feature in LocalControlHeader
+ */
+enum LocalControlHeaderFeature
+{
+ /// any feature
+ LOCAL_CONTROL_HEADER_FEATURE_ANY,
+ /// in-faceid
+ LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID,
+ /// out-faceid
+ LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID,
+ /// upper bound of enum
+ LOCAL_CONTROL_HEADER_FEATURE_MAX
+};
+
+
+/** \brief represents a face
+ */
+class LocalFace : public Face
+{
+public:
+ LocalFace();
+
+ /** \brief get whether a LocalControlHeader feature is enabled
+ *
+ * \param feature The feature. Cannot be LOCAL_CONTROL_HEADER_FEATURE_MAX
+ * LOCAL_CONTROL_HEADER_FEATURE_ANY returns true if any feature is enabled.
+ */
+ bool
+ isLocalControlHeaderEnabled(LocalControlHeaderFeature feature =
+ LOCAL_CONTROL_HEADER_FEATURE_ANY) const;
+
+ /** \brief enable or disable a LocalControlHeader feature
+ *
+ * \param feature The feature. Cannot be LOCAL_CONTROL_HEADER_FEATURE_ANY
+ * or LOCAL_CONTROL_HEADER_FEATURE_MAX
+ */
+ void
+ setLocalControlHeaderFeature(LocalControlHeaderFeature feature, bool enabled = true);
+
+protected:
+ // statically overridden from Face
+
+ /** \brief Decode block into Interest/Data, considering potential LocalControlHeader
+ *
+ * If LocalControlHeader is present, the encoded data is filtered out, based
+ * on enabled features on the face.
+ */
+ bool
+ decodeAndDispatchInput(const Block& element);
+
+ // LocalFace-specific methods
+
+ /** \brief Check if LocalControlHeader needs to be included, taking into account
+ * both set parameters in supplied LocalControlHeader and features
+ * enabled on the local face.
+ */
+ bool
+ isEmptyFilteredLocalControlHeader(const ndn::nfd::LocalControlHeader& header) const;
+
+ /** \brief Create LocalControlHeader, considering enabled features
+ */
+ template<class Packet>
+ Block
+ filterAndEncodeLocalControlHeader(const Packet& packet);
+
+private:
+ std::vector<bool> m_localControlHeaderFeatures;
+};
+
+inline
+LocalFace::LocalFace()
+ : m_localControlHeaderFeatures(LOCAL_CONTROL_HEADER_FEATURE_MAX)
+{
+ setLocal(true);
+}
+
+inline bool
+LocalFace::isLocalControlHeaderEnabled(LocalControlHeaderFeature feature) const
+{
+ BOOST_ASSERT(feature < m_localControlHeaderFeatures.size());
+ return m_localControlHeaderFeatures[feature];
+}
+
+inline void
+LocalFace::setLocalControlHeaderFeature(LocalControlHeaderFeature feature, bool enabled/* = true*/)
+{
+ BOOST_ASSERT(feature > LOCAL_CONTROL_HEADER_FEATURE_ANY &&
+ feature < m_localControlHeaderFeatures.size());
+ m_localControlHeaderFeatures[feature] = enabled;
+
+ BOOST_STATIC_ASSERT(LOCAL_CONTROL_HEADER_FEATURE_ANY == 0);
+ m_localControlHeaderFeatures[LOCAL_CONTROL_HEADER_FEATURE_ANY] =
+ std::find(m_localControlHeaderFeatures.begin() + 1,
+ m_localControlHeaderFeatures.end(), true) <
+ m_localControlHeaderFeatures.end();
+ // 'find(..) < .end()' instead of 'find(..) != .end()' due to LLVM Bug 16816
+}
+
+inline bool
+LocalFace::decodeAndDispatchInput(const Block& element)
+{
+ const Block& payload = ndn::nfd::LocalControlHeader::getPayload(element);
+
+ // If received LocalControlHeader, but it is not enabled on the face
+ if ((&payload != &element) && !this->isLocalControlHeaderEnabled())
+ return false;
+
+ if (payload.type() == tlv::Interest)
+ {
+ shared_ptr<Interest> i = make_shared<Interest>();
+ i->wireDecode(payload);
+ if (&payload != &element)
+ {
+ i->getLocalControlHeader().wireDecode(element,
+ false,
+ this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
+ }
+
+ this->onReceiveInterest(*i);
+ }
+ else if (payload.type() == tlv::Data)
+ {
+ shared_ptr<Data> d = make_shared<Data>();
+ d->wireDecode(payload);
+
+ /// \todo Uncomment and correct the following when we have more
+ /// options in LocalControlHeader that apply for incoming
+ /// Data packets (if ever)
+ // if (&payload != &element)
+ // {
+ //
+ // d->getLocalControlHeader().wireDecode(element,
+ // false,
+ // false);
+ // }
+
+ this->onReceiveData(*d);
+ }
+ else
+ return false;
+
+ return true;
+}
+
+inline bool
+LocalFace::isEmptyFilteredLocalControlHeader(const ndn::nfd::LocalControlHeader& header) const
+{
+ if (!this->isLocalControlHeaderEnabled())
+ return true;
+
+ return header.empty(this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID),
+ false);
+}
+
+template<class Packet>
+inline Block
+LocalFace::filterAndEncodeLocalControlHeader(const Packet& packet)
+{
+ return packet.getLocalControlHeader().wireEncode(packet,
+ this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID),
+ false);
+}
+
+} // namespace nfd
+
+#endif // NFD_FACE_LOCAL_FACE_HPP