diff --git a/tools/nfdc.cpp b/tools/nfdc.cpp index 2ecba4d0..dcb228ca 100644 --- a/tools/nfdc.cpp +++ b/tools/nfdc.cpp @@ -31,6 +31,10 @@ #include #include +#include +#include +#include + void usage(const char* programName) { @@ -48,7 +52,7 @@ usage(const char* programName) " (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 \n" + " unregister [-o origin] name \n" " unregister name from the given faceId\n" " create \n" " Create a face in one of the following formats:\n" @@ -63,7 +67,7 @@ usage(const char* programName) " add-nexthop [-c ] \n" " Add a nexthop to a FIB entry\n" " -c: specify cost (default 0)\n" - " remove-nexthop \n" + " remove-nexthop \n" " Remove a nexthop from a FIB entry\n" << std::endl; } @@ -75,11 +79,181 @@ using std::bind; 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(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(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(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 @@ Nfdc::dispatch(const std::string& command) 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(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(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(ribParameters, - bind(&Nfdc::onSuccess, this, _1, - "Nexthop insertion succeeded"), - bind(&Nfdc::onError, this, _1, _2, - "Nexthop insertion failed")); + m_controller + .start(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(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(parameters, - bind(&Nfdc::onSuccess, this, _1, - "Nexthop removal succeeded"), - bind(&Nfdc::onError, this, _1, _2, - "Nexthop removal failed")); + m_controller + .start(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(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(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(ribParameters, - bind(&Nfdc::onSuccess, this, _1, - "Successful in name registration"), - bind(&Nfdc::onError, this, _1, _2, - "Failed in name registration")); + m_controller + .start(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(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(parameters, - bind(&Nfdc::onSuccess, this, _1, - "Successful in unregistering name"), - bind(&Nfdc::onError, this, _1, _2, - "Failed in unregistering name")); + m_controller + .start(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 @@ -336,10 +418,17 @@ Nfdc::onCanonizeFailure(const std::string& reason) std::cerr << reason << std::endl; } +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 @@ void 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(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(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(faceParameters, - bind(&Nfdc::onSuccess, this, _1, - "Face destroy succeeded"), - bind(&Nfdc::onError, this, _1, _2, - "Face destroy failed")); + m_controller.start(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 @@ Nfdc::onError(uint32_t code, const std::string& error, const std::string& messag throw Error(os.str()); } - - } // namespace nfdc int diff --git a/tools/nfdc.hpp b/tools/nfdc.hpp index eb7bc51f..f8895b54 100644 --- a/tools/nfdc.hpp +++ b/tools/nfdc.hpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace nfdc { @@ -53,6 +54,74 @@ public: } }; + class FaceIdFetcher + { + public: + typedef std::function SuccessCallback; + typedef std::function 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); @@ -73,13 +142,6 @@ public: void 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 * @@ -102,17 +164,10 @@ public: 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(); @@ -139,16 +194,6 @@ public: void 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 * @@ -185,13 +230,7 @@ private: 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 @@ public: 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; };