tools: nfdc accepts FaceUri in all commands
refs #1995
Change-Id: Ifd05eb835bdf86d6e44bca4f8fe1c973ddb7a6ee
diff --git a/tools/nfdc.cpp b/tools/nfdc.cpp
index 2ecba4d..dcb228c 100644
--- a/tools/nfdc.cpp
+++ b/tools/nfdc.cpp
@@ -31,6 +31,10 @@
#include <boost/algorithm/string/regex_find_format.hpp>
#include <boost/regex.hpp>
+#include <ndn-cxx/management/nfd-face-query-filter.hpp>
+#include <ndn-cxx/management/nfd-face-status.hpp>
+#include <ndn-cxx/util/segment-fetcher.hpp>
+
void
usage(const char* programName)
{
@@ -48,7 +52,7 @@
" (by default the entry remains in FIB for the lifetime of the associated face)\n"
" -o: specify origin\n"
" 0 for Local producer applications, 128 for NLSR, 255(default) for static routes\n"
- " unregister [-o origin] name <faceId>\n"
+ " unregister [-o origin] name <faceId | faceUri>\n"
" unregister name from the given faceId\n"
" create <faceUri> \n"
" Create a face in one of the following formats:\n"
@@ -63,7 +67,7 @@
" add-nexthop [-c <cost>] <name> <faceId | faceUri>\n"
" Add a nexthop to a FIB entry\n"
" -c: specify cost (default 0)\n"
- " remove-nexthop <name> <faceId> \n"
+ " remove-nexthop <name> <faceId | faceUri> \n"
" Remove a nexthop from a FIB entry\n"
<< std::endl;
}
@@ -75,11 +79,181 @@
const ndn::time::milliseconds Nfdc::DEFAULT_EXPIRATION_PERIOD = ndn::time::milliseconds::max();
const uint64_t Nfdc::DEFAULT_COST = 0;
+Nfdc::FaceIdFetcher::FaceIdFetcher(ndn::Face& face,
+ Controller& controller,
+ bool allowCreate,
+ const SuccessCallback& onSucceed,
+ const FailureCallback& onFail)
+ : m_face(face)
+ , m_controller(controller)
+ , m_allowCreate(allowCreate)
+ , m_onSucceed(onSucceed)
+ , m_onFail(onFail)
+{
+}
+
+void
+Nfdc::FaceIdFetcher::start(ndn::Face& face,
+ Controller& controller,
+ const std::string& input,
+ bool allowCreate,
+ const SuccessCallback& onSucceed,
+ const FailureCallback& onFail)
+{
+ // 1. Try parse input as FaceId, if input is FaceId, succeed with parsed FaceId
+ // 2. Try parse input as FaceUri, if input is not FaceUri, fail
+ // 3. Canonize faceUri
+ // 4. If canonization fails, fail
+ // 5. Query for face
+ // 6. If query succeeds and finds a face, succeed with found FaceId
+ // 7. Create face
+ // 8. If face creation succeeds, succeed with created FaceId
+ // 9. Fail
+
+ boost::regex e("^[a-z0-9]+\\:.*");
+ if (!boost::regex_match(input, e)) {
+ try
+ {
+ u_int32_t faceId = boost::lexical_cast<uint32_t>(input);
+ onSucceed(faceId);
+ return;
+ }
+ catch (boost::bad_lexical_cast&)
+ {
+ onFail("No valid faceId or faceUri is provided");
+ return;
+ }
+ }
+ else {
+ ndn::util::FaceUri faceUri;
+ if (!faceUri.parse(input)) {
+ onFail("FaceUri parse failed");
+ return;
+ }
+
+ auto fetcher = new FaceIdFetcher(std::ref(face), std::ref(controller),
+ allowCreate, onSucceed, onFail);
+
+ fetcher->startGetFaceId(faceUri);
+ }
+}
+
+void
+Nfdc::FaceIdFetcher::startGetFaceId(const ndn::util::FaceUri& faceUri)
+{
+ faceUri.canonize(bind(&FaceIdFetcher::onCanonizeSuccess, this, _1),
+ bind(&FaceIdFetcher::onCanonizeFailure, this, _1),
+ m_face.getIoService(), ndn::time::seconds(4));
+}
+
+void
+Nfdc::FaceIdFetcher::onCanonizeSuccess(const ndn::util::FaceUri& canonicalUri)
+{
+ ndn::Name queryName("/localhost/nfd/faces/query");
+ ndn::nfd::FaceQueryFilter queryFilter;
+ queryFilter.setRemoteUri(canonicalUri.toString());
+ queryName.append(queryFilter.wireEncode());
+
+ ndn::Interest interestPacket(queryName);
+ interestPacket.setMustBeFresh(true);
+ interestPacket.setInterestLifetime(ndn::time::milliseconds(4000));
+ auto interest = std::make_shared<ndn::Interest>(interestPacket);
+
+ ndn::util::SegmentFetcher::fetch(m_face, *interest,
+ ndn::util::DontVerifySegment(),
+ bind(&FaceIdFetcher::onQuerySuccess,
+ this, _1, canonicalUri),
+ bind(&FaceIdFetcher::onQueryFailure,
+ this, _1, canonicalUri));
+}
+
+void
+Nfdc::FaceIdFetcher::onCanonizeFailure(const std::string& reason)
+{
+ fail("Canonize faceUri failed : " + reason);
+}
+
+void
+Nfdc::FaceIdFetcher::onQuerySuccess(const ndn::ConstBufferPtr& data,
+ const ndn::util::FaceUri& canonicalUri)
+{
+ size_t offset = 0;
+ ndn::Block block;
+ bool ok = ndn::Block::fromBuffer(data, offset, block);
+
+ if (!ok) {
+ if (m_allowCreate) {
+ startFaceCreate(canonicalUri);
+ }
+ else {
+ fail("Fail to find faceId");
+ }
+ }
+ else {
+ try {
+ FaceStatus status(block);
+ succeed(status.getFaceId());
+ }
+ catch (const ndn::tlv::Error& e) {
+ std::string errorMessage(e.what());
+ fail("ERROR: " + errorMessage);
+ }
+ }
+}
+
+void
+Nfdc::FaceIdFetcher::onQueryFailure(uint32_t errorCode,
+ const ndn::util::FaceUri& canonicalUri)
+{
+ std::stringstream ss;
+ ss << "Cannot fetch data (code " << errorCode << ")";
+ fail(ss.str());
+}
+
+void
+Nfdc::FaceIdFetcher::onFaceCreateError(uint32_t code,
+ const std::string& error,
+ const std::string& message)
+{
+ std::stringstream ss;
+ ss << message << " : " << error << " (code " << code << ")";
+ fail(ss.str());
+}
+
+void
+Nfdc::FaceIdFetcher::startFaceCreate(const ndn::util::FaceUri& canonicalUri)
+{
+ ControlParameters parameters;
+ parameters.setUri(canonicalUri.toString());
+
+ m_controller.start<FaceCreateCommand>(parameters,
+ [this] (const ControlParameters& result) {
+ succeed(result.getFaceId());
+ },
+ bind(&FaceIdFetcher::onFaceCreateError, this, _1, _2,
+ "Face creation failed"));
+}
+
+void
+Nfdc::FaceIdFetcher::succeed(uint32_t faceId)
+{
+ m_onSucceed(faceId);
+ delete this;
+}
+
+void
+Nfdc::FaceIdFetcher::fail(const std::string& reason)
+{
+ m_onFail(reason);
+ delete this;
+}
+
Nfdc::Nfdc(ndn::Face& face)
: m_flags(ROUTE_FLAG_CHILD_INHERIT)
, m_cost(DEFAULT_COST)
, m_origin(ROUTE_ORIGIN_STATIC)
, m_expires(DEFAULT_EXPIRATION_PERIOD)
+ , m_face(face)
, m_controller(face, m_keyChain)
, m_ioService(face.getIoService())
{
@@ -138,196 +312,104 @@
return true;
}
-namespace {
-
-inline bool
-isValidUri(const std::string& input)
-{
- // an extended regex to support the validation of uri structure
- // boost::regex e("^[a-z0-9]+-?+[a-z0-9]+\\:\\/\\/.*");
- boost::regex e("^[a-z0-9]+\\:.*");
- return boost::regex_match(input, e);
-}
-
-} // anonymous namespace
-
void
Nfdc::fibAddNextHop()
{
m_name = m_commandLineArguments[0];
- ControlParameters parameters;
- parameters
- .setName(m_name)
- .setCost(m_cost);
+ const std::string& faceName = m_commandLineArguments[1];
- if (!isValidUri(m_commandLineArguments[1])) {
- try { //So the uri is not valid, may be a faceId is provided.
- m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
- }
- catch (const std::exception& e) {
- std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
- return;
- }
- parameters.setFaceId(m_faceId);
- fibAddNextHop(parameters);
- }
- else {
- ndn::util::FaceUri faceUri;
- faceUri.parse(m_commandLineArguments[1]);
+ FaceIdFetcher::start(m_face, m_controller, faceName, true,
+ [this] (const uint32_t faceId) {
+ ControlParameters parameters;
+ parameters
+ .setName(m_name)
+ .setCost(m_cost)
+ .setFaceId(faceId);
- faceUri.canonize(bind(&Nfdc::startFibAddNextHop, this, _1),
- bind(&Nfdc::onCanonizeFailure, this, _1),
- m_ioService, ndn::time::seconds(4));
- }
-}
-
-void
-Nfdc::startFibAddNextHop(const ndn::util::FaceUri& canonicalUri)
-{
- ControlParameters parameters;
- parameters.setUri(canonicalUri.toString());
-
- m_controller.start<FaceCreateCommand>(parameters,
- [this](const ControlParameters& result) {
- fibAddNextHop(result);
- },
- bind(&Nfdc::onError, this, _1, _2,
- "Face creation failed"));
-}
-
-void
-Nfdc::fibAddNextHop(const ControlParameters& faceCreateResult)
-{
- ControlParameters ribParameters;
- ribParameters
- .setName(m_name)
- .setCost(m_cost)
- .setFaceId(faceCreateResult.getFaceId());
-
- m_controller.start<FibAddNextHopCommand>(ribParameters,
- bind(&Nfdc::onSuccess, this, _1,
- "Nexthop insertion succeeded"),
- bind(&Nfdc::onError, this, _1, _2,
- "Nexthop insertion failed"));
+ m_controller
+ .start<FibAddNextHopCommand>(parameters,
+ bind(&Nfdc::onSuccess, this, _1,
+ "Nexthop insertion succeeded"),
+ bind(&Nfdc::onError, this, _1, _2,
+ "Nexthop insertion failed"));
+ },
+ bind(&Nfdc::onObtainFaceIdFailure, this, _1));
}
void
Nfdc::fibRemoveNextHop()
{
m_name = m_commandLineArguments[0];
- try {
- m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
- }
- catch (const std::exception& e) {
- std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
- return;
- }
+ const std::string& faceName = m_commandLineArguments[1];
- ControlParameters parameters;
- parameters
- .setName(m_name)
- .setFaceId(m_faceId);
+ FaceIdFetcher::start(m_face, m_controller, faceName, false,
+ [this] (const uint32_t faceId) {
+ ControlParameters parameters;
+ parameters
+ .setName(m_name)
+ .setFaceId(faceId);
- m_controller.start<FibRemoveNextHopCommand>(parameters,
- bind(&Nfdc::onSuccess, this, _1,
- "Nexthop removal succeeded"),
- bind(&Nfdc::onError, this, _1, _2,
- "Nexthop removal failed"));
+ m_controller
+ .start<FibRemoveNextHopCommand>(parameters,
+ bind(&Nfdc::onSuccess, this, _1,
+ "Nexthop removal succeeded"),
+ bind(&Nfdc::onError, this, _1, _2,
+ "Nexthop removal failed"));
+ },
+ bind(&Nfdc::onObtainFaceIdFailure, this, _1));
}
void
Nfdc::ribRegisterPrefix()
{
m_name = m_commandLineArguments[0];
- ControlParameters parameters;
- parameters
- .setName(m_name)
- .setCost(m_cost)
- .setFlags(m_flags)
- .setOrigin(m_origin);
+ const std::string& faceName = m_commandLineArguments[1];
- if (m_expires != DEFAULT_EXPIRATION_PERIOD)
- parameters.setExpirationPeriod(m_expires);
+ FaceIdFetcher::start(m_face, m_controller, faceName, true,
+ [this] (const uint32_t faceId) {
+ ControlParameters parameters;
+ parameters
+ .setName(m_name)
+ .setCost(m_cost)
+ .setFlags(m_flags)
+ .setOrigin(m_origin)
+ .setFaceId(faceId);
- if (!isValidUri(m_commandLineArguments[1])) {
- try { //So the uri is not valid, may be a faceId is provided.
- m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
- }
- catch (const std::exception& e) {
- std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
- return;
- }
- parameters.setFaceId(m_faceId);
- ribRegisterPrefix(parameters);
- }
- else {
- ndn::util::FaceUri faceUri;
- faceUri.parse(m_commandLineArguments[1]);
+ if (m_expires != DEFAULT_EXPIRATION_PERIOD)
+ parameters.setExpirationPeriod(m_expires);
- faceUri.canonize(bind(&Nfdc::startRibRegisterPrefix, this, _1),
- bind(&Nfdc::onCanonizeFailure, this, _1),
- m_ioService, ndn::time::seconds(4));
- }
-}
-
-void
-Nfdc::startRibRegisterPrefix(const ndn::util::FaceUri& canonicalUri)
-{
- ControlParameters parameters;
- parameters.setUri(canonicalUri.toString());
-
- m_controller.start<FaceCreateCommand>(parameters,
- [this](const ControlParameters& result) {
- ribRegisterPrefix(result);
- },
- bind(&Nfdc::onError, this, _1, _2,
- "Face creation failed"));
-}
-
-void
-Nfdc::ribRegisterPrefix(const ControlParameters& faceCreateResult)
-{
- ControlParameters ribParameters;
- ribParameters
- .setName(m_name)
- .setCost(m_cost)
- .setFlags(m_flags)
- .setOrigin(m_origin)
- .setFaceId(faceCreateResult.getFaceId());
-
- if (m_expires != DEFAULT_EXPIRATION_PERIOD)
- ribParameters.setExpirationPeriod(m_expires);
-
- m_controller.start<RibRegisterCommand>(ribParameters,
- bind(&Nfdc::onSuccess, this, _1,
- "Successful in name registration"),
- bind(&Nfdc::onError, this, _1, _2,
- "Failed in name registration"));
+ m_controller
+ .start<RibRegisterCommand>(parameters,
+ bind(&Nfdc::onSuccess, this, _1,
+ "Successful in name registration"),
+ bind(&Nfdc::onError, this, _1, _2,
+ "Failed in name registration"));
+ },
+ bind(&Nfdc::onObtainFaceIdFailure, this, _1));
}
void
Nfdc::ribUnregisterPrefix()
{
m_name = m_commandLineArguments[0];
- try {
- m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
- }
- catch (const std::exception& e) {
- std::cerr << "No valid faceId is provided" << std::endl;
- return;
- }
+ const std::string& faceName = m_commandLineArguments[1];
- ControlParameters parameters;
- parameters
- .setName(m_name)
- .setFaceId(m_faceId)
- .setOrigin(m_origin);
+ FaceIdFetcher::start(m_face, m_controller, faceName, false,
+ [this] (const uint32_t faceId) {
+ ControlParameters parameters;
+ parameters
+ .setName(m_name)
+ .setFaceId(faceId)
+ .setOrigin(m_origin);
- m_controller.start<RibUnregisterCommand>(parameters,
- bind(&Nfdc::onSuccess, this, _1,
- "Successful in unregistering name"),
- bind(&Nfdc::onError, this, _1, _2,
- "Failed in unregistering name"));
+ m_controller
+ .start<RibUnregisterCommand>(parameters,
+ bind(&Nfdc::onSuccess, this, _1,
+ "Successful in unregistering name"),
+ bind(&Nfdc::onError, this, _1, _2,
+ "Failed in unregistering name"));
+ },
+ bind(&Nfdc::onObtainFaceIdFailure, this, _1));
}
void
@@ -337,9 +419,16 @@
}
void
+Nfdc::onObtainFaceIdFailure(const std::string& message)
+{
+ std::cerr << "Obtain faceId failure: " << message << std::endl;
+}
+
+void
Nfdc::faceCreate()
{
- if (!isValidUri(m_commandLineArguments[0]))
+ boost::regex e("^[a-z0-9]+\\:.*");
+ if (!boost::regex_match(m_commandLineArguments[0], e))
throw Error("invalid uri format");
ndn::util::FaceUri faceUri;
@@ -367,52 +456,20 @@
Nfdc::faceDestroy()
{
ControlParameters parameters;
- if (!isValidUri(m_commandLineArguments[0])) {
- try { //So the uri is not valid, may be a faceId is provided.
- m_faceId = boost::lexical_cast<int>(m_commandLineArguments[0]);
- }
- catch (const std::exception& e) {
- std::cerr << "No valid faceUri or faceId is provided" << std::endl;
- return;
- }
- parameters.setFaceId(m_faceId);
- faceDestroy(parameters);
- }
- else{
- ndn::util::FaceUri faceUri;
- faceUri.parse(m_commandLineArguments[0]);
+ const std::string& faceName = m_commandLineArguments[0];
- faceUri.canonize(bind(&Nfdc::startFaceDestroy, this, _1),
- bind(&Nfdc::onCanonizeFailure, this, _1),
- m_ioService, ndn::time::seconds(4));
- }
-}
+ FaceIdFetcher::start(m_face, m_controller, faceName, false,
+ [this] (const uint32_t faceId) {
+ ControlParameters faceParameters;
+ faceParameters.setFaceId(faceId);
-void
-Nfdc::startFaceDestroy(const ndn::util::FaceUri& canonicalUri)
-{
- ControlParameters parameters;
- parameters.setUri(canonicalUri.toString());
-
- m_controller.start<FaceCreateCommand>(parameters,
- [this](const ControlParameters& result) {
- faceDestroy(result);
- },
- bind(&Nfdc::onError, this, _1, _2,
- "Face destroy failed"));
-}
-
-void
-Nfdc::faceDestroy(const ControlParameters& faceCreateResult)
-{
- ControlParameters faceParameters;
- faceParameters.setFaceId(faceCreateResult.getFaceId());
-
- m_controller.start<FaceDestroyCommand>(faceParameters,
- bind(&Nfdc::onSuccess, this, _1,
- "Face destroy succeeded"),
- bind(&Nfdc::onError, this, _1, _2,
- "Face destroy failed"));
+ m_controller.start<FaceDestroyCommand>(faceParameters,
+ bind(&Nfdc::onSuccess, this, _1,
+ "Face destroy succeeded"),
+ bind(&Nfdc::onError, this, _1, _2,
+ "Face destroy failed"));
+ },
+ bind(&Nfdc::onObtainFaceIdFailure, this, _1));
}
void
@@ -462,8 +519,6 @@
throw Error(os.str());
}
-
-
} // namespace nfdc
int
diff --git a/tools/nfdc.hpp b/tools/nfdc.hpp
index eb7bc51..f8895b5 100644
--- a/tools/nfdc.hpp
+++ b/tools/nfdc.hpp
@@ -31,6 +31,7 @@
#include <ndn-cxx/util/time.hpp>
#include <ndn-cxx/management/nfd-controller.hpp>
#include <ndn-cxx/util/face-uri.hpp>
+#include <memory>
namespace nfdc {
@@ -53,6 +54,74 @@
}
};
+ class FaceIdFetcher
+ {
+ public:
+ typedef std::function<void(uint32_t)> SuccessCallback;
+ typedef std::function<void(const std::string&)> FailureCallback;
+
+ /** \brief obtain FaceId from input
+ * \param face Reference to the Face that should be used to fetch data
+ * \param controller Reference to the controller that should be used to sign the Interest
+ * \param input User input, either FaceId or FaceUri
+ * \param allowCreate Whether creating face is allowed
+ * \param onSucceed Callback to be fired when faceId is obtained
+ * \param onFail Callback to be fired when an error occurs
+ */
+ static void
+ start(ndn::Face& face,
+ Controller& controller,
+ const std::string& input,
+ bool allowCreate,
+ const SuccessCallback& onSucceed,
+ const FailureCallback& onFail);
+
+ private:
+ FaceIdFetcher(ndn::Face& face,
+ Controller& controller,
+ bool allowCreate,
+ const SuccessCallback& onSucceed,
+ const FailureCallback& onFail);
+
+ void
+ onQuerySuccess(const ndn::ConstBufferPtr& data,
+ const ndn::util::FaceUri& canonicalUri);
+
+ void
+ onQueryFailure(uint32_t errorCode,
+ const ndn::util::FaceUri& canonicalUri);
+
+ void
+ onCanonizeSuccess(const ndn::util::FaceUri& canonicalUri);
+
+ void
+ onCanonizeFailure(const std::string& reason);
+
+ void
+ startGetFaceId(const ndn::util::FaceUri& faceUri);
+
+ void
+ startFaceCreate(const ndn::util::FaceUri& canonicalUri);
+
+ void
+ onFaceCreateError(uint32_t code,
+ const std::string& error,
+ const std::string& message);
+
+ void
+ succeed(uint32_t faceId);
+
+ void
+ fail(const std::string& reason);
+
+ private:
+ ndn::Face& m_face;
+ Controller& m_controller;
+ bool m_allowCreate;
+ SuccessCallback m_onSucceed;
+ FailureCallback m_onFail;
+ };
+
explicit
Nfdc(ndn::Face& face);
@@ -74,13 +143,6 @@
fibAddNextHop();
/**
- * \brief Adds a nexthop to a FIB entry using faceId provided in the faceCreateResult
- *
- */
- void
- fibAddNextHop(const ControlParameters& faceCreateResult);
-
- /**
* \brief Removes a nexthop from an existing FIB entry
*
* If the last nexthop record in a FIB entry is removed, the FIB entry is also deleted
@@ -102,17 +164,10 @@
ribRegisterPrefix();
/**
- * \brief Registers name to the faceId provided in faceCreateResult
- *
- */
- void
- ribRegisterPrefix(const ControlParameters& faceCreateResult);
-
- /**
- * \brief Unregisters name from the given faceId
+ * \brief Unregisters name from the given faceId/faceUri
*
* cmd format:
- * name faceId
+ * name faceId/faceUri
*/
void
ribUnregisterPrefix();
@@ -140,16 +195,6 @@
faceDestroy();
/**
- * \brief Destroys face based on faceId provided in faceCreateResult
- *
- * cmd format:
- * faceId|faceUri
- *
- */
- void
- faceDestroy(const ControlParameters& faceCreateResult);
-
- /**
* \brief Sets the strategy for a namespace
*
* cmd format:
@@ -185,13 +230,7 @@
startFaceCreate(const ndn::util::FaceUri& canonicalUri);
void
- startFaceDestroy(const ndn::util::FaceUri& canonicalUri);
-
- void
- startFibAddNextHop(const ndn::util::FaceUri& canonicalUri);
-
- void
- startRibRegisterPrefix(const ndn::util::FaceUri& canonicalUri);
+ onObtainFaceIdFailure(const std::string& message);
public:
const char* m_programName;
@@ -206,9 +245,9 @@
ndn::time::milliseconds m_expires;
std::string m_name;
-
private:
ndn::KeyChain m_keyChain;
+ ndn::Face& m_face;
Controller m_controller;
boost::asio::io_service& m_ioService;
};