route: use ndn::FaceUri type for faceUri

refs #4227

Change-Id: I1b0d7ed97e43e4d0c50770ed306cbe85382dfc9a
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index 0975c20..d47d880 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -242,10 +242,10 @@
 }
 
 void
-Fib::unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri)
+Fib::unregisterPrefix(const ndn::Name& namePrefix, const ndn::FaceUri& faceUri)
 {
   uint64_t faceId = 0;
-  auto adjacent = m_adjacencyList.findAdjacent(ndn::FaceUri(faceUri));
+  auto adjacent = m_adjacencyList.findAdjacent(faceUri);
   if (adjacent != m_adjacencyList.end()) {
     faceId = adjacent->getFaceId();
   }
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index 1a9b75f..8c53125 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -165,7 +165,7 @@
    *
    */
   void
-  unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri);
+  unregisterPrefix(const ndn::Name& namePrefix, const ndn::FaceUri& faceUri);
 
   /*! \brief Log registration success, and update the Face ID associated with a URI.
    */
diff --git a/src/route/nexthop-list.hpp b/src/route/nexthop-list.hpp
index 98e5760..1ed1a5a 100644
--- a/src/route/nexthop-list.hpp
+++ b/src/route/nexthop-list.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -31,42 +31,16 @@
 
 namespace nlsr {
 
-struct NextHopComparator {
+struct NextHopUriSortedComparator
+{
   bool
-  operator() (const NextHop& nh1, const NextHop& nh2) const {
-    if (nh1.getRouteCostAsAdjustedInteger() < nh2.getRouteCostAsAdjustedInteger()) {
-      return true;
-    }
-    else if (nh1.getRouteCostAsAdjustedInteger() == nh2.getRouteCostAsAdjustedInteger()) {
-      return nh1.getConnectingFaceUri() < nh2.getConnectingFaceUri();
-    }
-    else {
-      return false;
-    }
+  operator()(const NextHop& lhs, const NextHop& rhs) const
+  {
+    return lhs.getConnectingFaceUri() < rhs.getConnectingFaceUri();
   }
 };
 
-struct NextHopUriSortedComparator {
-  bool
-  operator() (const NextHop& nh1, const NextHop& nh2) const {
-    return nh1.getConnectingFaceUri() < nh2.getConnectingFaceUri();
-  }
-};
-
-static inline bool
-nexthopAddCompare(const NextHop& nh1, const NextHop& nh2)
-{
-  return nh1.getConnectingFaceUri() == nh2.getConnectingFaceUri();
-}
-
-static inline bool
-nexthopRemoveCompare(const NextHop& nh1, const NextHop& nh2)
-{
-  return (nh1.getConnectingFaceUri() == nh2.getConnectingFaceUri() &&
-          nh1.getRouteCostAsAdjustedInteger() == nh2.getRouteCostAsAdjustedInteger()) ;
-}
-
-template<typename T = NextHopComparator>
+template<typename T = std::less<NextHop>>
 class NexthopListT
 {
 public:
@@ -76,19 +50,21 @@
     \param nh The next hop.
 
     Adds a next hop to this object. If the next hop is new it is
-    added. If the next hop already exists in the list then that next
-    hop's route cost is updated.
+    added. If the next hop already exists but has a higher cost then
+    its route cost is updated.
   */
   void
   addNextHop(const NextHop& nh)
   {
     auto it = std::find_if(m_nexthopList.begin(), m_nexthopList.end(),
-                           std::bind(&nexthopAddCompare, _1, nh));
+      [&nh] (const auto& item) {
+        return item.getConnectingFaceUri() == nh.getConnectingFaceUri();
+      });
     if (it == m_nexthopList.end()) {
       m_nexthopList.insert(nh);
     }
     else if (it->getRouteCost() > nh.getRouteCost()) {
-      removeNextHop(*it);
+      m_nexthopList.erase(it);
       m_nexthopList.insert(nh);
     }
   }
@@ -101,8 +77,7 @@
   void
   removeNextHop(const NextHop& nh)
   {
-    auto it = std::find_if(m_nexthopList.begin(), m_nexthopList.end(),
-                           std::bind(&nexthopRemoveCompare, _1, nh));
+    auto it = std::find(m_nexthopList.begin(), m_nexthopList.end(), nh);
     if (it != m_nexthopList.end()) {
       m_nexthopList.erase(it);
     }
diff --git a/src/route/nexthop.cpp b/src/route/nexthop.cpp
index a5f10ba..aeeb641 100644
--- a/src/route/nexthop.cpp
+++ b/src/route/nexthop.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -32,7 +32,7 @@
   size_t totalLength = 0;
 
   totalLength += ndn::encoding::prependDoubleBlock(block, nlsr::tlv::CostDouble, m_routeCost);
-  totalLength += ndn::encoding::prependStringBlock(block, nlsr::tlv::Uri, m_connectingFaceUri);
+  totalLength += ndn::encoding::prependStringBlock(block, nlsr::tlv::Uri, m_connectingFaceUri.toString());
 
   totalLength += block.prependVarNumber(totalLength);
   totalLength += block.prependVarNumber(nlsr::tlv::NextHop);
@@ -63,7 +63,7 @@
 void
 NextHop::wireDecode(const ndn::Block& wire)
 {
-  m_connectingFaceUri = "";
+  m_connectingFaceUri = {};
   m_routeCost = 0;
 
   m_wire = wire;
@@ -77,7 +77,12 @@
   auto val = m_wire.elements_begin();
 
   if (val != m_wire.elements_end() && val->type() == nlsr::tlv::Uri) {
-    m_connectingFaceUri = ndn::encoding::readString(*val);
+    try {
+      m_connectingFaceUri = ndn::FaceUri(ndn::encoding::readString(*val));
+    }
+    catch (const ndn::FaceUri::Error& e) {
+      NDN_THROW_NESTED(Error("Invalid Uri"));
+    }
     ++val;
   }
   else {
@@ -93,13 +98,6 @@
   }
 }
 
-bool
-operator==(const NextHop& lhs, const NextHop& rhs)
-{
-  return (lhs.getRouteCostAsAdjustedInteger() == rhs.getRouteCostAsAdjustedInteger()) &&
-         (lhs.getConnectingFaceUri() == rhs.getConnectingFaceUri());
-}
-
 std::ostream&
 operator<<(std::ostream& os, const NextHop& hop)
 {
diff --git a/src/route/nexthop.hpp b/src/route/nexthop.hpp
index 77bc8b1..6629d89 100644
--- a/src/route/nexthop.hpp
+++ b/src/route/nexthop.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -26,6 +26,9 @@
 #include <ndn-cxx/encoding/block.hpp>
 #include <ndn-cxx/encoding/encoding-buffer.hpp>
 #include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/net/face-uri.hpp>
+
+#include <boost/operators.hpp>
 
 #include <cmath>
 #include <ostream>
@@ -40,38 +43,33 @@
  *
  * \sa https://redmine.named-data.net/projects/nlsr/wiki/Routing_Table_Dataset
  */
-class NextHop
+class NextHop : private boost::totally_ordered<NextHop>
 {
 public:
   using Error = ndn::tlv::Error;
 
-  NextHop()
-    : m_connectingFaceUri()
-    , m_routeCost(0)
-    , m_isHyperbolic(false)
-  {
-  }
+  NextHop() = default;
 
-  NextHop(const std::string& cfu, double rc)
+  NextHop(const ndn::FaceUri& cfu, double rc)
     : m_connectingFaceUri(cfu)
     , m_routeCost(rc)
-    , m_isHyperbolic(false)
   {
   }
 
+  explicit
   NextHop(const ndn::Block& block)
   {
     wireDecode(block);
   }
 
-  const std::string&
+  const ndn::FaceUri&
   getConnectingFaceUri() const
   {
     return m_connectingFaceUri;
   }
 
   void
-  setConnectingFaceUri(const std::string& cfu)
+  setConnectingFaceUri(const ndn::FaceUri& cfu)
   {
     m_connectingFaceUri = cfu;
   }
@@ -124,10 +122,29 @@
   void
   wireDecode(const ndn::Block& wire);
 
+private: // non-member operators
+  // NOTE: the following "hidden friend" operators are available via
+  //       argument-dependent lookup only and must be defined inline.
+  // boost::totally_ordered provides !=, <=, >=, and > operators.
+
+  friend bool
+  operator==(const NextHop& lhs, const NextHop& rhs)
+  {
+    return lhs.getRouteCostAsAdjustedInteger() == rhs.getRouteCostAsAdjustedInteger() &&
+           lhs.getConnectingFaceUri() == rhs.getConnectingFaceUri();
+  }
+
+  friend bool
+  operator<(const NextHop& lhs, const NextHop& rhs)
+  {
+    return std::forward_as_tuple(lhs.getRouteCostAsAdjustedInteger(), lhs.getConnectingFaceUri()) <
+           std::forward_as_tuple(rhs.getRouteCostAsAdjustedInteger(), rhs.getConnectingFaceUri());
+  }
+
 private:
-  std::string m_connectingFaceUri;
-  double m_routeCost;
-  bool m_isHyperbolic;
+  ndn::FaceUri m_connectingFaceUri;
+  double m_routeCost = 0.0;
+  bool m_isHyperbolic = false;
 
   mutable ndn::Block m_wire;
 
@@ -147,9 +164,6 @@
 
 NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(NextHop);
 
-bool
-operator==(const NextHop& lhs, const NextHop& rhs);
-
 std::ostream&
 operator<<(std::ostream& os, const NextHop& hop);
 
diff --git a/src/route/routing-table-calculator.cpp b/src/route/routing-table-calculator.cpp
index a7419ce..54c8a47 100644
--- a/src/route/routing-table-calculator.cpp
+++ b/src/route/routing-table-calculator.cpp
@@ -348,8 +348,7 @@
         // Fetch its actual name
         auto nextHopRouterName = pMap.getRouterNameByMappingNo(nextHopRouter);
         if (nextHopRouterName) {
-          std::string nextHopFace =
-            adjacencies.getAdjacent(*nextHopRouterName).getFaceUri().toString();
+          auto nextHopFace = adjacencies.getAdjacent(*nextHopRouterName).getFaceUri();
           // Add next hop to routing table
           NextHop nh(nextHopFace, routeCost);
           rt.addNextHop(*(pMap.getRouterNameByMappingNo(i)), nh);
@@ -451,10 +450,8 @@
       continue;
     }
 
-    std::string srcFaceUri = adj->getFaceUri().toString();
-
     // Install nexthops for this router to the neighbor; direct neighbors have a 0 cost link
-    addNextHop(srcRouterName, srcFaceUri, 0, rt);
+    addNextHop(srcRouterName, adj->getFaceUri(), 0, rt);
 
     auto src = map.getMappingNoByRouterName(srcRouterName);
     if (!src) {
@@ -477,7 +474,7 @@
                            << " to " << *destRouterName);
             continue;
           }
-          addNextHop(*destRouterName, srcFaceUri, distance, rt);
+          addNextHop(*destRouterName, adj->getFaceUri(), distance, rt);
         }
       }
     }
@@ -618,7 +615,7 @@
 }
 
 void
-HyperbolicRoutingCalculator::addNextHop(ndn::Name dest, std::string faceUri,
+HyperbolicRoutingCalculator::addNextHop(const ndn::Name& dest, const ndn::FaceUri& faceUri,
                                         double cost, RoutingTable& rt)
 {
   NextHop hop(faceUri, cost);
diff --git a/src/route/routing-table-calculator.hpp b/src/route/routing-table-calculator.hpp
index 749c5b8..45af713 100644
--- a/src/route/routing-table-calculator.hpp
+++ b/src/route/routing-table-calculator.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -214,7 +214,7 @@
   getHyperbolicDistance(Lsdb& lsdb, ndn::Name src, ndn::Name dest);
 
   void
-  addNextHop(ndn::Name destinationRouter, std::string faceUri, double cost, RoutingTable& rt);
+  addNextHop(const ndn::Name& destinationRouter, const ndn::FaceUri& faceUri, double cost, RoutingTable& rt);
 
   double
   calculateHyperbolicDistance(double rI, double rJ, double deltaTheta);