mgmt: add config file-based strategy selection

refs: #2053

Change-Id: I76b5945768403578651429ca3170f29d9e66ad54
diff --git a/daemon/mgmt/tables-config-section.cpp b/daemon/mgmt/tables-config-section.cpp
index 7e1ed8f..861ed7f 100644
--- a/daemon/mgmt/tables-config-section.cpp
+++ b/daemon/mgmt/tables-config-section.cpp
@@ -43,7 +43,7 @@
   : m_cs(cs)
   // , m_pit(pit)
   // , m_fib(fib)
-  // , m_strategyChoice(strategyChoice)
+  , m_strategyChoice(strategyChoice)
   // , m_measurements(measurements)
   , m_areTablesConfigured(false)
 {
@@ -80,6 +80,14 @@
   // tables
   // {
   //    cs_max_packets 65536
+  //
+  //    strategy_choice
+  //    {
+  //       /               /localhost/nfd/strategy/best-route
+  //       /localhost      /localhost/nfd/strategy/broadcast
+  //       /localhost/nfd  /localhost/nfd/strategy/best-route
+  //       /ndn/broadcast  /localhost/nfd/strategy/broadcast
+  //    }
   // }
 
   size_t nCsMaxPackets = DEFAULT_CS_MAX_PACKETS;
@@ -101,6 +109,14 @@
       nCsMaxPackets = *valCsMaxPackets;
     }
 
+  boost::optional<const ConfigSection&> strategyChoiceSection =
+    configSection.get_child_optional("strategy_choice");
+
+  if (strategyChoiceSection)
+    {
+      processSectionStrategyChoice(*strategyChoiceSection, isDryRun);
+    }
+
   if (!isDryRun)
     {
       NFD_LOG_INFO("Setting CS max packets to " << nCsMaxPackets);
@@ -110,4 +126,59 @@
     }
 }
 
+void
+TablesConfigSection::processSectionStrategyChoice(const ConfigSection& configSection,
+                                                  bool isDryRun)
+{
+  // strategy_choice
+  // {
+  //   /               /localhost/nfd/strategy/best-route
+  //   /localhost      /localhost/nfd/strategy/broadcast
+  //   /localhost/nfd  /localhost/nfd/strategy/best-route
+  //   /ndn/broadcast  /localhost/nfd/strategy/broadcast
+  // }
+
+  std::map<Name, Name> choices;
+
+  for (const auto& prefixAndStrategy : configSection)
+    {
+      const Name prefix(prefixAndStrategy.first);
+      if (choices.find(prefix) != choices.end())
+        {
+          throw ConfigFile::Error("Duplicate strategy choice for prefix \"" +
+                                  prefix.toUri() + "\" in \"strategy_choice\" section");
+        }
+
+      const std::string strategyString(prefixAndStrategy.second.get_value<std::string>());
+      if (strategyString.empty())
+        {
+          throw ConfigFile::Error("Invalid strategy choice \"\" for prefix \"" +
+                                  prefix.toUri() + "\" in \"strategy_choice\" section");
+        }
+
+      const Name strategyName(strategyString);
+      if (!m_strategyChoice.hasStrategy(strategyName))
+        {
+          throw ConfigFile::Error("Invalid strategy choice \"" +
+                                  strategyName.toUri() + "\" for prefix \"" +
+                                  prefix.toUri() + "\" in \"strategy_choice\" section");
+        }
+
+      choices[prefix] = strategyName;
+    }
+
+
+  for (const auto& prefixAndStrategy : choices)
+    {
+      if (!isDryRun && !m_strategyChoice.insert(prefixAndStrategy.first, prefixAndStrategy.second))
+        {
+          throw ConfigFile::Error("Failed to set strategy \"" +
+                                  prefixAndStrategy.second.toUri() + "\" for prefix \"" +
+                                  prefixAndStrategy.first.toUri() + "\" in \"strategy_choicev\"");
+        }
+    }
+}
+
+
+
 } // namespace nfd