controller.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2018 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
22 #include "controller.hpp"
23 #include "face.hpp"
25 #include "util/segment-fetcher.hpp"
26 
27 #include <boost/lexical_cast.hpp>
28 
29 namespace ndn {
30 namespace nfd {
31 
33 
34 const uint32_t Controller::ERROR_TIMEOUT = 10060; // WinSock ESAETIMEDOUT
35 const uint32_t Controller::ERROR_NACK = 10800; // 10000 + TLV-TYPE of Nack header
36 const uint32_t Controller::ERROR_VALIDATION = 10021; // 10000 + TLS1_ALERT_DECRYPTION_FAILED
37 const uint32_t Controller::ERROR_SERVER = 500;
38 const uint32_t Controller::ERROR_LBOUND = 400;
39 
40 Controller::Controller(Face& face, KeyChain& keyChain, security::v2::Validator& validator)
41  : m_face(face)
42  , m_keyChain(keyChain)
43  , m_validator(validator)
44  , m_signer(keyChain)
45 {
46 }
47 
48 void
49 Controller::startCommand(const shared_ptr<ControlCommand>& command,
50  const ControlParameters& parameters,
51  const CommandSucceedCallback& onSuccess,
52  const CommandFailCallback& onFailure,
53  const CommandOptions& options)
54 {
55  Name requestName = command->getRequestName(options.getPrefix(), parameters);
56  Interest interest = m_signer.makeCommandInterest(requestName, options.getSigningInfo());
57  interest.setInterestLifetime(options.getTimeout());
58 
59  m_face.expressInterest(interest,
60  [=] (const Interest&, const Data& data) {
61  processCommandResponse(data, command, onSuccess, onFailure);
62  },
63  [=] (const Interest&, const lp::Nack&) {
64  if (onFailure)
65  onFailure(ControlResponse(Controller::ERROR_NACK, "network Nack received"));
66  },
67  [=] (const Interest&) {
68  if (onFailure)
69  onFailure(ControlResponse(Controller::ERROR_TIMEOUT, "request timed out"));
70  });
71 }
72 
73 void
74 Controller::processCommandResponse(const Data& data,
75  const shared_ptr<ControlCommand>& command,
76  const CommandSucceedCallback& onSuccess,
77  const CommandFailCallback& onFailure)
78 {
79  m_validator.validate(data,
80  [=] (const Data& data) {
81  processValidatedCommandResponse(data, command, onSuccess, onFailure);
82  },
83  [=] (const Data&, const auto& error) {
84  if (onFailure)
85  onFailure(ControlResponse(ERROR_VALIDATION, boost::lexical_cast<std::string>(error)));
86  }
87  );
88 }
89 
90 void
91 Controller::processValidatedCommandResponse(const Data& data,
92  const shared_ptr<ControlCommand>& command,
93  const CommandSucceedCallback& onSuccess,
94  const CommandFailCallback& onFailure)
95 {
96  ControlResponse response;
97  try {
98  response.wireDecode(data.getContent().blockFromValue());
99  }
100  catch (const tlv::Error& e) {
101  if (onFailure)
102  onFailure(ControlResponse(ERROR_SERVER, e.what()));
103  return;
104  }
105 
106  uint32_t code = response.getCode();
107  if (code >= ERROR_LBOUND) {
108  if (onFailure)
109  onFailure(response);
110  return;
111  }
112 
113  ControlParameters parameters;
114  try {
115  parameters.wireDecode(response.getBody());
116  }
117  catch (const tlv::Error& e) {
118  if (onFailure)
119  onFailure(ControlResponse(ERROR_SERVER, e.what()));
120  return;
121  }
122 
123  try {
124  command->validateResponse(parameters);
125  }
126  catch (const ControlCommand::ArgumentError& e) {
127  if (onFailure)
128  onFailure(ControlResponse(ERROR_SERVER, e.what()));
129  return;
130  }
131 
132  if (onSuccess)
133  onSuccess(parameters);
134 }
135 
136 void
137 Controller::fetchDataset(const Name& prefix,
138  const std::function<void(ConstBufferPtr)>& processResponse,
139  const DatasetFailCallback& onFailure,
140  const CommandOptions& options)
141 {
142  SegmentFetcher::Options fetcherOptions;
143  fetcherOptions.maxTimeout = options.getTimeout();
144 
145  auto fetcher = SegmentFetcher::start(m_face, Interest(prefix), m_validator, fetcherOptions);
146  if (processResponse) {
147  fetcher->onComplete.connect(processResponse);
148  }
149  if (onFailure) {
150  fetcher->onError.connect([=] (uint32_t code, const std::string& msg) {
151  processDatasetFetchError(onFailure, code, msg);
152  });
153  }
154 }
155 
156 void
157 Controller::processDatasetFetchError(const DatasetFailCallback& onFailure,
158  uint32_t code, std::string msg)
159 {
160  BOOST_ASSERT(onFailure);
161 
162  switch (static_cast<SegmentFetcher::ErrorCode>(code)) {
163  // It's intentional to cast as SegmentFetcher::ErrorCode, and to not have a 'default' clause.
164  // This forces the switch statement to handle every defined SegmentFetcher::ErrorCode,
165  // and breaks compilation if it does not.
166  case SegmentFetcher::ErrorCode::INTEREST_TIMEOUT:
167  onFailure(ERROR_TIMEOUT, msg);
168  break;
169  case SegmentFetcher::ErrorCode::DATA_HAS_NO_SEGMENT:
170  case SegmentFetcher::ErrorCode::FINALBLOCKID_NOT_SEGMENT:
171  onFailure(ERROR_SERVER, msg);
172  break;
173  case SegmentFetcher::ErrorCode::SEGMENT_VALIDATION_FAIL:
176  onFailure(ERROR_VALIDATION, msg);
177  break;
178  case SegmentFetcher::ErrorCode::NACK_ERROR:
179  onFailure(ERROR_NACK, msg);
180  break;
181  }
182 }
183 
184 } // namespace nfd
185 } // namespace ndn
void wireDecode(const Block &wire) final
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:65
represents parameters in a ControlCommand request or response
security::CommandInterestSigner m_signer
Definition: controller.hpp:174
function< void(const ControlResponse &)> CommandFailCallback
a callback on command failure
Definition: controller.hpp:59
const Block & getBody() const
function< void(uint32_t code, const std::string &reason)> DatasetFailCallback
a callback on dataset retrieval failure
Definition: controller.hpp:63
time::milliseconds maxTimeout
maximum allowed time between successful receipt of segments
Utility class to fetch the latest version of a segmented object.
Represents an Interest packet.
Definition: interest.hpp:43
const Name & getPrefix() const
static const uint32_t ERROR_TIMEOUT
error code for timeout
Definition: controller.hpp:152
represents a Network Nack
Definition: nack.hpp:40
static const uint32_t ERROR_LBOUND
inclusive lower bound of error codes
Definition: controller.hpp:168
mgmt::ControlResponse ControlResponse
Block blockFromValue() const
Definition: block.cpp:322
contains options for ControlCommand execution
static shared_ptr< SegmentFetcher > start(Face &face, const Interest &baseInterest, security::v2::Validator &validator, const Options &options=Options())
Initiates segment fetching.
void validate(const Data &data, const DataValidationSuccessCallback &successCb, const DataValidationFailureCallback &failureCb)
Asynchronously validate data.
Definition: validator.cpp:75
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:90
static const uint32_t ERROR_VALIDATION
error code for response validation failure
Definition: controller.hpp:160
Controller(Face &face, KeyChain &keyChain, security::v2::Validator &validator=security::getAcceptAllValidator())
construct a Controller that uses face for transport, and uses the passed KeyChain to sign commands ...
Definition: controller.cpp:40
Interest makeCommandInterest(const Name &name, const SigningInfo &params=KeyChain::getDefaultSigningInfo())
Create CommandInterest.
Represents an absolute name.
Definition: name.hpp:42
function< void(const ControlParameters &)> CommandSucceedCallback
a callback on command success
Definition: controller.hpp:55
void wireDecode(const Block &block)
const Block & getContent() const
Get Content.
Definition: data.cpp:234
security::v2::Validator & m_validator
Definition: controller.hpp:173
Interest & setInterestLifetime(time::milliseconds lifetime)
Set Interest&#39;s lifetime.
Definition: interest.cpp:578
ControlCommand response.
const PendingInterestId * expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express Interest.
Definition: face.cpp:178
represents an error in ControlParameters
Represents a Data packet.
Definition: data.hpp:35
const time::milliseconds & getTimeout() const
represents an error in TLV encoding or decoding
Interface for validating data and interest packets.
Definition: validator.hpp:61
static const uint32_t ERROR_SERVER
error code for server error
Definition: controller.hpp:164
static const uint32_t ERROR_NACK
error code for network Nack
Definition: controller.hpp:156
const security::SigningInfo & getSigningInfo() const
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:126