blob: f0bf841746b877c6f5bc5a200c4b739d0b3a877f [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "face-id-fetcher.hpp"
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
#include <ndn-cxx/mgmt/nfd/face-query-filter.hpp>
#include <ndn-cxx/mgmt/nfd/face-status.hpp>
#include <ndn-cxx/security/validator-null.hpp>
#include <ndn-cxx/util/segment-fetcher.hpp>
namespace nfd {
namespace tools {
namespace nfdc {
FaceIdFetcher::FaceIdFetcher(ndn::Face& face,
ndn::nfd::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
FaceIdFetcher::start(ndn::Face& face,
ndn::nfd::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 {
uint32_t faceId = boost::lexical_cast<uint32_t>(input);
onSucceed(faceId);
return;
}
catch (const boost::bad_lexical_cast&) {
onFail("No valid faceId or faceUri is provided");
return;
}
}
else {
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
FaceIdFetcher::startGetFaceId(const FaceUri& faceUri)
{
faceUri.canonize(bind(&FaceIdFetcher::onCanonizeSuccess, this, _1),
bind(&FaceIdFetcher::onCanonizeFailure, this, _1),
m_face.getIoService(), time::seconds(4));
}
void
FaceIdFetcher::onCanonizeSuccess(const 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(time::milliseconds(4000));
auto interest = std::make_shared<ndn::Interest>(interestPacket);
ndn::util::SegmentFetcher::fetch(
m_face, *interest, ndn::security::v2::getAcceptAllValidator(),
bind(&FaceIdFetcher::onQuerySuccess, this, _1, canonicalUri),
bind(&FaceIdFetcher::onQueryFailure, this, _1, canonicalUri));
}
void
FaceIdFetcher::onCanonizeFailure(const std::string& reason)
{
fail("Canonize faceUri failed : " + reason);
}
void
FaceIdFetcher::onQuerySuccess(const ndn::ConstBufferPtr& data,
const FaceUri& canonicalUri)
{
size_t offset = 0;
bool isOk = false;
ndn::Block block;
std::tie(isOk, block) = ndn::Block::fromBuffer(data, offset);
if (!isOk) {
if (m_allowCreate) {
startFaceCreate(canonicalUri);
}
else {
fail("Fail to find faceId");
}
}
else {
try {
ndn::nfd::FaceStatus status(block);
succeed(status.getFaceId());
}
catch (const ndn::tlv::Error& e) {
std::string errorMessage(e.what());
fail("ERROR: " + errorMessage);
}
}
}
void
FaceIdFetcher::onQueryFailure(uint32_t errorCode,
const FaceUri& canonicalUri)
{
std::stringstream ss;
ss << "Cannot fetch data (code " << errorCode << ")";
fail(ss.str());
}
void
FaceIdFetcher::onFaceCreateError(const ndn::nfd::ControlResponse& response,
const std::string& message)
{
std::stringstream ss;
ss << message << " : " << response.getText() << " (code " << response.getCode() << ")";
fail(ss.str());
}
void
FaceIdFetcher::startFaceCreate(const FaceUri& canonicalUri)
{
ndn::nfd::ControlParameters parameters;
parameters.setUri(canonicalUri.toString());
m_controller.start<ndn::nfd::FaceCreateCommand>(parameters,
[this] (const ndn::nfd::ControlParameters& result) { succeed(result.getFaceId()); },
bind(&FaceIdFetcher::onFaceCreateError, this, _1, "Face creation failed"));
}
void
FaceIdFetcher::succeed(uint32_t faceId)
{
m_onSucceed(faceId);
delete this;
}
void
FaceIdFetcher::fail(const std::string& reason)
{
m_onFail(reason);
delete this;
}
} // namespace nfdc
} // namespace tools
} // namespace nfd