face: implement close-on-idle and persistency change for Ethernet unicast

Change-Id: I255024990a72b8cea5a44fa89f515ad91aadba66
Refs: #4011
diff --git a/daemon/face/unicast-ethernet-transport.cpp b/daemon/face/unicast-ethernet-transport.cpp
index eb34648..05bab28 100644
--- a/daemon/face/unicast-ethernet-transport.cpp
+++ b/daemon/face/unicast-ethernet-transport.cpp
@@ -59,7 +59,45 @@
            m_srcAddress.toString().data());
   m_pcap.setPacketFilter(filter);
 
-  // TODO: implement close on idle and persistency change
+  if (getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND &&
+      m_idleTimeout > time::nanoseconds::zero()) {
+    scheduleClosureWhenIdle();
+  }
+}
+
+bool
+UnicastEthernetTransport::canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const
+{
+  return true;
+}
+
+void
+UnicastEthernetTransport::afterChangePersistency(ndn::nfd::FacePersistency oldPersistency)
+{
+  if (getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND &&
+      m_idleTimeout > time::nanoseconds::zero()) {
+    scheduleClosureWhenIdle();
+  }
+  else {
+    m_closeIfIdleEvent.cancel();
+    setExpirationTime(time::steady_clock::TimePoint::max());
+  }
+}
+
+void
+UnicastEthernetTransport::scheduleClosureWhenIdle()
+{
+  m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, [this] {
+    if (!hasBeenUsedRecently()) {
+      NFD_LOG_FACE_INFO("Closing due to inactivity");
+      this->close();
+    }
+    else {
+      resetRecentUsage();
+      scheduleClosureWhenIdle();
+    }
+  });
+  setExpirationTime(time::steady_clock::now() + m_idleTimeout);
 }
 
 } // namespace face