face: Moving idle UdpFace closing logic to UdpFace class
Change-Id: Ia7310fa18681f17d93c8214ce744da909fea7022
Refs: #1686
diff --git a/daemon/face/face-flags.hpp b/daemon/face/face-flags.hpp
new file mode 100644
index 0000000..1451a27
--- /dev/null
+++ b/daemon/face/face-flags.hpp
@@ -0,0 +1,48 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014 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
+ *
+ * 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_MGMT_FACE_FLAGS_HPP
+#define NFD_DAEMON_MGMT_FACE_FLAGS_HPP
+
+#include "face/face.hpp"
+#include <ndn-cxx/management/nfd-face-flags.hpp>
+
+namespace nfd {
+
+inline uint64_t
+getFaceFlags(const Face& face)
+{
+ uint64_t flags = 0;
+ if (face.isLocal()) {
+ flags |= ndn::nfd::FACE_IS_LOCAL;
+ }
+ if (face.isOnDemand()) {
+ flags |= ndn::nfd::FACE_IS_ON_DEMAND;
+ }
+ return flags;
+}
+
+} // namespace nfd
+
+#endif // NFD_DAEMON_MGMT_FACE_FLAGS_HPP
diff --git a/daemon/face/face.cpp b/daemon/face/face.cpp
index 9d2368b..ea08f5b 100644
--- a/daemon/face/face.cpp
+++ b/daemon/face/face.cpp
@@ -24,6 +24,7 @@
**/
#include "face.hpp"
+#include "face-flags.hpp"
#include "core/logger.hpp"
namespace nfd {
@@ -128,4 +129,23 @@
this->onFail(reason);
}
+ndn::nfd::FaceStatus
+Face::getFaceStatus() const
+{
+ const FaceCounters& counters = getCounters();
+
+ ndn::nfd::FaceStatus status;
+ status.setFaceId(getId())
+ .setRemoteUri(getRemoteUri().toString())
+ .setLocalUri(getLocalUri().toString())
+ .setFlags(getFaceFlags(*this))
+ .setNInInterests(counters.getNInInterests())
+ .setNInDatas(counters.getNInDatas())
+ .setNOutInterests(counters.getNOutInterests())
+ .setNOutDatas(counters.getNOutDatas());
+
+ return status;
+}
+
+
} //namespace nfd
diff --git a/daemon/face/face.hpp b/daemon/face/face.hpp
index 987853e..2660045 100644
--- a/daemon/face/face.hpp
+++ b/daemon/face/face.hpp
@@ -31,6 +31,8 @@
#include "core/face-uri.hpp"
#include "face-counter.hpp"
+#include <ndn-cxx/management/nfd-face-status.hpp>
+
namespace nfd {
/** \class FaceId
@@ -149,6 +151,11 @@
const FaceUri&
getLocalUri() const;
+ /** \return FaceStatus data structure filled with the current Face status
+ */
+ virtual ndn::nfd::FaceStatus
+ getFaceStatus() const;
+
protected:
// this is a non-virtual method
bool
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 684879a..b01d699 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -61,15 +61,6 @@
}
this->setUri(FaceUri(localEndpoint));
-
- //setting the timeout to close the idle faces
- m_closeIdleFaceEvent = scheduler::schedule(m_idleFaceTimeout,
- bind(&UdpChannel::closeIdleFaces, this));
-}
-
-UdpChannel::~UdpChannel()
-{
- scheduler::cancel(m_closeIdleFaceEvent);
}
void
@@ -185,7 +176,7 @@
ChannelFaceMap::iterator faceMapPos = m_channelFaces.find(remoteEndpoint);
if (faceMapPos == m_channelFaces.end())
{
- face = make_shared<UdpFace>(socket, isOnDemand);
+ face = make_shared<UdpFace>(socket, isOnDemand, m_idleFaceTimeout);
face->onFail += bind(&UdpChannel::afterFaceFailed, this, remoteEndpoint);
m_channelFaces[remoteEndpoint] = face;
@@ -263,26 +254,4 @@
m_channelFaces.erase(endpoint);
}
-void
-UdpChannel::closeIdleFaces()
-{
- ChannelFaceMap::iterator next = m_channelFaces.begin();
-
- while (next != m_channelFaces.end()) {
- ChannelFaceMap::iterator it = next;
- next++;
- if (it->second->isOnDemand() &&
- !it->second->hasBeenUsedRecently()) {
- //face has been idle since the last time closeIdleFaces
- //has been called. Going to close it
- NFD_LOG_DEBUG("Found idle face id: " << it->second->getId());
- it->second->close();
- } else {
- it->second->resetRecentUsage();
- }
- }
- m_closeIdleFaceEvent = scheduler::schedule(m_idleFaceTimeout,
- bind(&UdpChannel::closeIdleFaces, this));
-}
-
} // namespace nfd
diff --git a/daemon/face/udp-channel.hpp b/daemon/face/udp-channel.hpp
index 4db6e43..fed232a 100644
--- a/daemon/face/udp-channel.hpp
+++ b/daemon/face/udp-channel.hpp
@@ -27,7 +27,6 @@
#include "channel.hpp"
#include "core/global-io.hpp"
-#include "core/scheduler.hpp"
#include "udp-face.hpp"
namespace nfd {
@@ -65,9 +64,6 @@
UdpChannel(const udp::Endpoint& localEndpoint,
const time::seconds& timeout);
- virtual
- ~UdpChannel();
-
/**
* \brief Enable listening on the local endpoint, accept connections,
* and create faces when remote host makes a connection
@@ -137,9 +133,6 @@
const ConnectFailedCallback& onConnectFailed,
const shared_ptr<boost::asio::ip::udp::resolver>& resolver);
- void
- closeIdleFaces();
-
private:
udp::Endpoint m_localEndpoint;
@@ -178,9 +171,6 @@
* faces will be removed
*/
time::seconds m_idleFaceTimeout;
-
- EventId m_closeIdleFaceEvent;
-
};
} // namespace nfd
diff --git a/daemon/face/udp-face.cpp b/daemon/face/udp-face.cpp
index d2d7823..d4fe8cf 100644
--- a/daemon/face/udp-face.cpp
+++ b/daemon/face/udp-face.cpp
@@ -33,10 +33,14 @@
NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(DatagramFace, UdpFace::protocol, "UdpFace");
-UdpFace::UdpFace(const shared_ptr<UdpFace::protocol::socket>& socket, bool isOnDemand)
+UdpFace::UdpFace(const shared_ptr<UdpFace::protocol::socket>& socket,
+ bool isOnDemand,
+ const time::seconds& idleTimeout)
: DatagramFace<protocol>(FaceUri(socket->remote_endpoint()),
FaceUri(socket->local_endpoint()),
socket, isOnDemand)
+ , m_idleTimeout(idleTimeout)
+ , m_lastIdleCheck(time::steady_clock::now())
{
#ifdef __linux__
//
@@ -60,6 +64,16 @@
<< "] Failed to disable path MTU discovery");
}
#endif
+
+ if (isOnDemand && m_idleTimeout > time::seconds::zero()) {
+ m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout,
+ bind(&UdpFace::closeIfIdle, this));
+ }
+}
+
+UdpFace::~UdpFace()
+{
+ scheduler::cancel(m_closeIfIdleEvent);
}
void
@@ -84,4 +98,49 @@
receiveDatagram(buffer, nBytesReceived, error);
}
+ndn::nfd::FaceStatus
+UdpFace::getFaceStatus() const
+{
+ ndn::nfd::FaceStatus status = Face::getFaceStatus();
+ if (isOnDemand()) {
+ time::milliseconds left = time::duration_cast<time::milliseconds>(
+ time::steady_clock::now() - m_lastIdleCheck);
+
+ if (hasBeenUsedRecently()) {
+ status.setExpirationPeriod(left + m_idleTimeout);
+ }
+ else {
+ status.setExpirationPeriod(left);
+ }
+ }
+ return status;
+}
+
+void
+UdpFace::closeIfIdle()
+{
+ // Face can be switched from on-demand to non-on-demand mode
+ // (non-on-demand -> on-demand transition is not allowed)
+ if (isOnDemand()) {
+ if (!hasBeenUsedRecently()) {
+ // face has been idle since the last time closeIfIdle
+ // has been called. Going to close it
+ NFD_LOG_DEBUG("Found idle face id: " << getId());
+
+ NFD_LOG_INFO("[id:" << this->getId()
+ << ",endpoint:" << m_socket->local_endpoint()
+ << "] Idle for more than " << m_idleTimeout << ", closing");
+ close();
+ }
+ else {
+ resetRecentUsage();
+
+ m_lastIdleCheck = time::steady_clock::now();
+ m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout,
+ bind(&UdpFace::closeIfIdle, this));
+ }
+ }
+ // else do nothing and do not reschedule the event
+}
+
} // namespace nfd
diff --git a/daemon/face/udp-face.hpp b/daemon/face/udp-face.hpp
index ec11682..2751517 100644
--- a/daemon/face/udp-face.hpp
+++ b/daemon/face/udp-face.hpp
@@ -26,6 +26,7 @@
#define NFD_DAEMON_FACE_UDP_FACE_HPP
#include "datagram-face.hpp"
+#include "core/scheduler.hpp"
namespace nfd {
@@ -37,7 +38,11 @@
{
public:
UdpFace(const shared_ptr<protocol::socket>& socket,
- bool isOnDemand);
+ bool isOnDemand,
+ const time::seconds& idleTimeout);
+
+ virtual
+ ~UdpFace();
/**
* \brief Manages the first datagram received by the UdpChannel socket set on listening
@@ -46,6 +51,18 @@
handleFirstReceive(const uint8_t* buffer,
std::size_t nBytesReceived,
const boost::system::error_code& error);
+
+ virtual ndn::nfd::FaceStatus
+ getFaceStatus() const;
+
+private:
+ void
+ closeIfIdle();
+
+private:
+ EventId m_closeIfIdleEvent;
+ time::seconds m_idleTimeout;
+ time::steady_clock::TimePoint m_lastIdleCheck;
};
} // namespace nfd