face: Refactor Face as LinkService+Transport
LpFace: new Face implementation
LpFaceWrapper: allows new Face system to work with old Face system
Eventually, LpFace will be renamed to Face and LpFaceWrapper will be removed.
refs #3088 #3179
Change-Id: Ia4ad7c84631e65b444d4f24e1d7593392927c8db
diff --git a/daemon/face/transport.hpp b/daemon/face/transport.hpp
new file mode 100644
index 0000000..144e0dc
--- /dev/null
+++ b/daemon/face/transport.hpp
@@ -0,0 +1,340 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD 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.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_DAEMON_FACE_TRANSPORT_HPP
+#define NFD_DAEMON_FACE_TRANSPORT_HPP
+
+#include "common.hpp"
+
+#include "face-counters.hpp"
+#include "face-log.hpp"
+
+namespace nfd {
+namespace face {
+
+class LpFace;
+class LinkService;
+
+/** \brief indicates the state of a transport
+ */
+enum class TransportState {
+ NONE,
+ UP, ///< the transport is up
+ DOWN, ///< the transport is down temporarily, and is being recovered
+ CLOSING, ///< the transport is requested to be closed
+ FAILED, ///< the transport is being closed due to a failure
+ CLOSED ///< the transport is closed, and can be safely deallocated
+};
+
+std::ostream&
+operator<<(std::ostream& os, TransportState state);
+
+/** \brief the lower part of an LpFace
+ * \sa LpFace
+ */
+class Transport : noncopyable
+{
+public:
+ /** \brief identifies an endpoint on the link
+ */
+ typedef uint64_t EndpointId;
+
+ /** \brief stores a packet along with the remote endpoint
+ */
+ class Packet
+ {
+ public:
+ Packet() = default;
+
+ explicit
+ Packet(Block&& packet);
+
+ public:
+ /** \brief the packet as a TLV block
+ */
+ Block packet;
+
+ /** \brief identifies the remote endpoint
+ *
+ * This ID is only meaningful in the context of the same Transport.
+ * Incoming packets from the same remote endpoint have the same EndpointId,
+ * and incoming packets from different remote endpoints have different EndpointIds.
+ */
+ EndpointId remoteEndpoint;
+ };
+
+ Transport();
+
+ virtual
+ ~Transport();
+
+public:
+ /** \brief set Face and LinkService for Transport
+ * \pre setFaceAndLinkService has not been called
+ */
+ void
+ setFaceAndLinkService(LpFace& face, LinkService& service);
+
+ /** \return Face to which this Transport is attached
+ */
+ const LpFace*
+ getFace() const;
+
+ /** \return LinkService to which this Transport is attached
+ */
+ const LinkService*
+ getLinkService() const;
+
+ /** \return LinkService to which this Transport is attached
+ */
+ LinkService*
+ getLinkService();
+
+public: // upper interface
+ /** \brief request the transport to be closed
+ *
+ * This operation is effective only if transport is in UP or DOWN state,
+ * otherwise it has no effect.
+ * The transport changes state to CLOSING, and performs cleanup procedure.
+ * The state will be changed to CLOSED when cleanup is complete, which may
+ * happen synchronously or asynchronously.
+ */
+ void
+ close();
+
+ /** \brief send a link-layer packet
+ */
+ void
+ send(Packet&& packet);
+
+protected: // upper interface to be invoked by subclass
+ /** \brief receive a link-layer packet
+ */
+ void
+ receive(Packet&& packet);
+
+public: // static properties
+ /** \return a FaceUri representing local endpoint
+ */
+ FaceUri
+ getLocalUri() const;
+
+ /** \return a FaceUri representing remote endpoint
+ */
+ FaceUri
+ getRemoteUri() const;
+
+ /** \return whether face is local or non-local for scope control purpose
+ */
+ ndn::nfd::FaceScope
+ getScope() const;
+
+ /** \return face persistency setting
+ */
+ ndn::nfd::FacePersistency
+ getPersistency() const;
+
+ /** \brief changes face persistency setting
+ */
+ void
+ setPersistency(ndn::nfd::FacePersistency persistency);
+
+ /** \return whether face is point-to-point or multi-access
+ */
+ ndn::nfd::LinkType
+ getLinkType() const;
+
+public: // dynamic properties
+ /** \return transport state
+ */
+ TransportState
+ getState() const;
+
+ /** \brief signals when transport state changes
+ */
+ signal::Signal<Transport, TransportState/*old*/, TransportState/*new*/> afterStateChange;
+
+protected: // properties to be set by subclass
+ void
+ setLocalUri(const FaceUri& uri);
+
+ void
+ setRemoteUri(const FaceUri& uri);
+
+ void
+ setScope(ndn::nfd::FaceScope scope);
+
+ void
+ setLinkType(ndn::nfd::LinkType linkType);
+
+ /** \brief set transport state
+ *
+ * Only the following transitions are valid:
+ * UP->DOWN, DOWN->UP, UP/DOWN->CLOSING/FAILED, CLOSING/FAILED->CLOSED
+ *
+ * \throw std::runtime_error transition is invalid.
+ */
+ void
+ setState(TransportState newState);
+
+protected: // to be overridden by subclass
+ /** \brief invoked before persistency is changed
+ * \throw std::invalid_argument new persistency is not supported
+ * \throw std::runtime_error transition is disallowed
+ *
+ * Base class implementation does nothing.
+ */
+ virtual void
+ beforeChangePersistency(ndn::nfd::FacePersistency newPersistency)
+ {
+ }
+
+ /** \brief performs Transport specific operations to close the transport
+ *
+ * When the cleanup procedure is complete, this method should change state to CLOSED.
+ * This can happen synchronously or asynchronously.
+ */
+ virtual void
+ doClose() = 0;
+
+private: // to be overridden by subclass
+ /** \brief performs Transport specific operations to send a packet
+ * \param packet the packet, which must be a well-formed TLV block
+ */
+ virtual void
+ doSend(Packet&& packet) = 0;
+
+private:
+ LpFace* m_face;
+ LinkService* m_service;
+ FaceUri m_localUri;
+ FaceUri m_remoteUri;
+ ndn::nfd::FaceScope m_scope;
+ ndn::nfd::FacePersistency m_persistency;
+ ndn::nfd::LinkType m_linkType;
+ TransportState m_state;
+ LinkLayerCounters* m_counters; // TODO#3177 change into LinkCounters
+};
+
+inline const LpFace*
+Transport::getFace() const
+{
+ return m_face;
+}
+
+inline const LinkService*
+Transport::getLinkService() const
+{
+ return m_service;
+}
+
+inline LinkService*
+Transport::getLinkService()
+{
+ return m_service;
+}
+
+inline FaceUri
+Transport::getLocalUri() const
+{
+ return m_localUri;
+}
+
+inline FaceUri
+Transport::getRemoteUri() const
+{
+ return m_remoteUri;
+}
+
+inline ndn::nfd::FaceScope
+Transport::getScope() const
+{
+ return m_scope;
+}
+
+inline ndn::nfd::FacePersistency
+Transport::getPersistency() const
+{
+ return m_persistency;
+}
+
+inline void
+Transport::setPersistency(ndn::nfd::FacePersistency persistency)
+{
+ this->beforeChangePersistency(persistency);
+ m_persistency = persistency;
+}
+
+inline ndn::nfd::LinkType
+Transport::getLinkType() const
+{
+ return m_linkType;
+}
+
+inline TransportState
+Transport::getState() const
+{
+ return m_state;
+}
+
+inline void
+Transport::setLocalUri(const FaceUri& uri)
+{
+ m_localUri = uri;
+}
+
+inline void
+Transport::setRemoteUri(const FaceUri& uri)
+{
+ m_remoteUri = uri;
+}
+
+inline void
+Transport::setScope(ndn::nfd::FaceScope scope)
+{
+ m_scope = scope;
+}
+
+inline void
+Transport::setLinkType(ndn::nfd::LinkType linkType)
+{
+ m_linkType = linkType;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh);
+
+template<typename T>
+typename std::enable_if<std::is_base_of<Transport, T>::value &&
+ !std::is_same<Transport, T>::value, std::ostream&>::type
+operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
+{
+ return os << FaceLogHelper<Transport>(flh.obj);
+}
+
+} // namespace face
+} // namespace nfd
+
+#endif // NFD_DAEMON_FACE_TRANSPORT_HPP