mgmt: add LocalUri to ControlParameters

refs #4014

Change-Id: I474dc3f41021687b99804fc2d71dd6e72c5175c5
diff --git a/src/mgmt/nfd/control-parameters.cpp b/src/mgmt/nfd/control-parameters.cpp
index 4958749..a414567 100644
--- a/src/mgmt/nfd/control-parameters.cpp
+++ b/src/mgmt/nfd/control-parameters.cpp
@@ -78,6 +78,13 @@
     totalLength += prependNonNegativeIntegerBlock(encoder,
                    tlv::nfd::LocalControlFeature, m_localControlFeature);
   }
+  if (this->hasLocalUri()) {
+    size_t valLength = encoder.prependByteArray(
+                       reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+    totalLength += valLength;
+    totalLength += encoder.prependVarNumber(valLength);
+    totalLength += encoder.prependVarNumber(tlv::nfd::LocalUri);
+  }
   if (this->hasUri()) {
     size_t valLength = encoder.prependByteArray(
                        reinterpret_cast<const uint8_t*>(m_uri.c_str()), m_uri.size());
@@ -147,6 +154,12 @@
     m_uri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
   }
 
+  val = m_wire.find(tlv::nfd::LocalUri);
+  m_hasFields[CONTROL_PARAMETER_LOCAL_URI] = val != m_wire.elements_end();
+  if (this->hasLocalUri()) {
+    m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+  }
+
   val = m_wire.find(tlv::nfd::LocalControlFeature);
   m_hasFields[CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE] = val != m_wire.elements_end();
   if (this->hasLocalControlFeature()) {
@@ -292,6 +305,10 @@
     os << "Uri: " << parameters.getUri() << ", ";
   }
 
+  if (parameters.hasLocalUri()) {
+    os << "LocalUri: " << parameters.getLocalUri() << ", ";
+  }
+
   if (parameters.hasLocalControlFeature()) {
     os << "LocalControlFeature: " << parameters.getLocalControlFeature() << ", ";
   }
diff --git a/src/mgmt/nfd/control-parameters.hpp b/src/mgmt/nfd/control-parameters.hpp
index 6c0c599..cd432ca 100644
--- a/src/mgmt/nfd/control-parameters.hpp
+++ b/src/mgmt/nfd/control-parameters.hpp
@@ -37,6 +37,7 @@
   CONTROL_PARAMETER_NAME,
   CONTROL_PARAMETER_FACE_ID,
   CONTROL_PARAMETER_URI,
+  CONTROL_PARAMETER_LOCAL_URI,
   CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE,
   CONTROL_PARAMETER_ORIGIN,
   CONTROL_PARAMETER_COST,
@@ -52,6 +53,7 @@
   "Name",
   "FaceId",
   "Uri",
+  "LocalUri",
   "LocalControlFeature",
   "Origin",
   "Cost",
@@ -74,7 +76,7 @@
 /**
  * \ingroup management
  * \brief represents parameters in a ControlCommand request or response
- * \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand#ControlParameters
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/ControlCommand#ControlParameters
  * \details This type is copyable because it's an abstraction of a TLV type.
  */
 class ControlParameters : public mgmt::ControlParameters
@@ -196,6 +198,36 @@
     return *this;
   }
 
+  bool
+  hasLocalUri() const
+  {
+    return m_hasFields[CONTROL_PARAMETER_LOCAL_URI];
+  }
+
+  const std::string&
+  getLocalUri() const
+  {
+    BOOST_ASSERT(this->hasLocalUri());
+    return m_localUri;
+  }
+
+  ControlParameters&
+  setLocalUri(const std::string& localUri)
+  {
+    m_wire.reset();
+    m_localUri = localUri;
+    m_hasFields[CONTROL_PARAMETER_LOCAL_URI] = true;
+    return *this;
+  }
+
+  ControlParameters&
+  unsetLocalUri()
+  {
+    m_wire.reset();
+    m_hasFields[CONTROL_PARAMETER_LOCAL_URI] = false;
+    return *this;
+  }
+
   /**
    * \deprecated use Flags+Mask fields instead
    */
@@ -492,6 +524,7 @@
   Name                m_name;
   uint64_t            m_faceId;
   std::string         m_uri;
+  std::string         m_localUri;
   LocalControlFeature m_localControlFeature;
   uint64_t            m_origin;
   uint64_t            m_cost;
diff --git a/tests/unit-tests/mgmt/nfd/control-parameters.t.cpp b/tests/unit-tests/mgmt/nfd/control-parameters.t.cpp
index 7ef364e..96d8519 100644
--- a/tests/unit-tests/mgmt/nfd/control-parameters.t.cpp
+++ b/tests/unit-tests/mgmt/nfd/control-parameters.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2016 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -35,6 +35,7 @@
 {
   ControlParameters parameters;
   parameters.setUri("tcp4://192.0.2.1:6363");
+  parameters.setLocalUri("dev://eth0");
   parameters.setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
   parameters.setFlags(1);
   parameters.setMask(1);
@@ -42,6 +43,7 @@
 
   ControlParameters decoded(wire);
   BOOST_CHECK_EQUAL(decoded.getUri(), "tcp4://192.0.2.1:6363");
+  BOOST_CHECK_EQUAL(decoded.getLocalUri(), "dev://eth0");
   BOOST_CHECK_EQUAL(decoded.getFacePersistency(), ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
   BOOST_CHECK_EQUAL(decoded.getFlags(), 1);
   BOOST_CHECK_EQUAL(decoded.getMask(), 1);
@@ -68,6 +70,7 @@
   BOOST_CHECK_EQUAL(decoded.hasName(), false);
   BOOST_CHECK_EQUAL(decoded.hasFaceId(), false);
   BOOST_CHECK_EQUAL(decoded.hasUri(), false);
+  BOOST_CHECK_EQUAL(decoded.hasLocalUri(), false);
   BOOST_CHECK_EQUAL(decoded.hasOrigin(), false);
   BOOST_CHECK_EQUAL(decoded.hasCost(), false);
   BOOST_CHECK_EQUAL(decoded.hasFlags(), false);
@@ -91,6 +94,7 @@
   BOOST_CHECK_EQUAL(decoded.getCost(), 555);
 
   BOOST_CHECK_EQUAL(decoded.hasUri(), false);
+  BOOST_CHECK_EQUAL(decoded.hasLocalUri(), false);
   BOOST_CHECK_EQUAL(decoded.hasLocalControlFeature(), false);
   BOOST_CHECK_EQUAL(decoded.hasOrigin(), false);
   BOOST_CHECK_EQUAL(decoded.hasFlags(), false);
@@ -114,6 +118,7 @@
 
   BOOST_CHECK_EQUAL(decoded.hasFaceId(), false);
   BOOST_CHECK_EQUAL(decoded.hasUri(), false);
+  BOOST_CHECK_EQUAL(decoded.hasLocalUri(), false);
   BOOST_CHECK_EQUAL(decoded.hasLocalControlFeature(), false);
   BOOST_CHECK_EQUAL(decoded.hasOrigin(), false);
   BOOST_CHECK_EQUAL(decoded.hasCost(), false);
@@ -144,6 +149,7 @@
   BOOST_CHECK_EQUAL(decoded.getExpirationPeriod(), time::milliseconds(1800000));
 
   BOOST_CHECK_EQUAL(decoded.hasUri(), false);
+  BOOST_CHECK_EQUAL(decoded.hasLocalUri(), false);
   BOOST_CHECK_EQUAL(decoded.hasLocalControlFeature(), false);
   BOOST_CHECK_EQUAL(decoded.hasMask(), false);
   BOOST_CHECK_EQUAL(decoded.hasStrategy(), false);