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-2017 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"
26 #include "util/segment-fetcher.hpp"
27 
28 #include <boost/lexical_cast.hpp>
29 
30 namespace ndn {
31 namespace nfd {
32 
34 
35 const uint32_t Controller::ERROR_TIMEOUT = 10060; // WinSock ESAETIMEDOUT
36 const uint32_t Controller::ERROR_NACK = 10800; // 10000 + TLV-TYPE of Nack header
37 const uint32_t Controller::ERROR_VALIDATION = 10021; // 10000 + TLS1_ALERT_DECRYPTION_FAILED
38 const uint32_t Controller::ERROR_SERVER = 500;
39 const uint32_t Controller::ERROR_LBOUND = 400;
40 
41 Controller::Controller(Face& face, KeyChain& keyChain, security::v2::Validator& validator)
42  : m_face(face)
43  , m_keyChain(keyChain)
44  , m_validator(validator)
45  , m_signer(keyChain)
46 {
47 }
48 
49 void
50 Controller::startCommand(const shared_ptr<ControlCommand>& command,
51  const ControlParameters& parameters,
52  const CommandSucceedCallback& onSuccess1,
53  const CommandFailCallback& onFailure1,
54  const CommandOptions& options)
55 {
56  const CommandSucceedCallback& onSuccess = onSuccess1 ?
57  onSuccess1 : [] (const ControlParameters&) {};
58  const CommandFailCallback& onFailure = onFailure1 ?
59  onFailure1 : [] (const ControlResponse&) {};
60 
61  Name requestName = command->getRequestName(options.getPrefix(), parameters);
62  Interest interest = m_signer.makeCommandInterest(requestName, options.getSigningInfo());
63  interest.setInterestLifetime(options.getTimeout());
64 
65  m_face.expressInterest(interest,
66  [=] (const Interest&, const Data& data) {
67  this->processCommandResponse(data, command, onSuccess, onFailure);
68  },
69  [=] (const Interest&, const lp::Nack&) {
70  onFailure(ControlResponse(Controller::ERROR_NACK, "network Nack received"));
71  },
72  [=] (const Interest&) {
73  onFailure(ControlResponse(Controller::ERROR_TIMEOUT, "request timed out"));
74  });
75 }
76 
77 void
78 Controller::processCommandResponse(const Data& data,
79  const shared_ptr<ControlCommand>& command,
80  const CommandSucceedCallback& onSuccess,
81  const CommandFailCallback& onFailure)
82 {
83  m_validator.validate(data,
84  [=] (const Data& data) {
85  this->processValidatedCommandResponse(data, command, onSuccess, onFailure);
86  },
87  [=] (const Data& data, const security::v2::ValidationError& error) {
88  onFailure(ControlResponse(ERROR_VALIDATION, boost::lexical_cast<std::string>(error)));
89  }
90  );
91 }
92 
93 void
94 Controller::processValidatedCommandResponse(const Data& data,
95  const shared_ptr<ControlCommand>& command,
96  const CommandSucceedCallback& onSuccess,
97  const CommandFailCallback& onFailure)
98 {
99  ControlResponse response;
100  try {
101  response.wireDecode(data.getContent().blockFromValue());
102  }
103  catch (const tlv::Error& e) {
104  onFailure(ControlResponse(ERROR_SERVER, e.what()));
105  return;
106  }
107 
108  uint32_t code = response.getCode();
109  if (code >= ERROR_LBOUND) {
110  onFailure(response);
111  return;
112  }
113 
114  ControlParameters parameters;
115  try {
116  parameters.wireDecode(response.getBody());
117  }
118  catch (const tlv::Error& e) {
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  onFailure(ControlResponse(ERROR_SERVER, e.what()));
128  return;
129  }
130 
131  onSuccess(parameters);
132 }
133 
134 void
135 Controller::fetchDataset(const Name& prefix,
136  const std::function<void(const ConstBufferPtr&)>& processResponse,
137  const DatasetFailCallback& onFailure,
138  const CommandOptions& options)
139 {
140  Interest baseInterest(prefix);
141  baseInterest.setInterestLifetime(options.getTimeout());
142 
143  SegmentFetcher::fetch(m_face, baseInterest, m_validator, processResponse,
144  bind(&Controller::processDatasetFetchError, this, onFailure, _1, _2));
145 }
146 
147 void
148 Controller::processDatasetFetchError(const DatasetFailCallback& onFailure,
149  uint32_t code, std::string msg)
150 {
151  switch (static_cast<SegmentFetcher::ErrorCode>(code)) {
152  // It's intentional to cast as SegmentFetcher::ErrorCode, and to not have a 'default' clause.
153  // This forces the switch statement to handle every defined SegmentFetcher::ErrorCode,
154  // and breaks compilation if it does not.
155  case SegmentFetcher::ErrorCode::INTEREST_TIMEOUT:
156  onFailure(ERROR_TIMEOUT, msg);
157  break;
158  case SegmentFetcher::ErrorCode::DATA_HAS_NO_SEGMENT:
159  onFailure(ERROR_SERVER, msg);
160  break;
161  case SegmentFetcher::ErrorCode::SEGMENT_VALIDATION_FAIL:
164  onFailure(ERROR_VALIDATION, msg);
165  break;
166  case SegmentFetcher::ErrorCode::NACK_ERROR:
167  onFailure(ERROR_NACK, msg);
168  break;
169  }
170 }
171 
172 } // namespace nfd
173 } // namespace ndn
void wireDecode(const Block &wire) final
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
represents parameters in a ControlCommand request or response
security::CommandInterestSigner m_signer
Definition: controller.hpp:174
const Block & getBody() const
Utility class to fetch latest version of the segmented data.
represents an Interest packet
Definition: interest.hpp:42
function< void(const ControlResponse &)> CommandFailCallback
a callback on command failure
Definition: controller.hpp:59
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
function< void(const ControlParameters &)> CommandSucceedCallback
a callback on command success
Definition: controller.hpp:55
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:323
contains options for ControlCommand execution
void validate(const Data &data, const DataValidationSuccessCallback &successCb, const DataValidationFailureCallback &failureCb)
Asynchronously validate data.
Definition: validator.cpp:75
static void fetch(Face &face, const Interest &baseInterest, security::v2::Validator &validator, const CompleteCallback &completeCallback, const ErrorCallback &errorCallback)
Initiate segment fetching.
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:95
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:41
Interest makeCommandInterest(const Name &name, const SigningInfo &params=KeyChain::getDefaultSigningInfo())
Create CommandInterest.
Represents an absolute name.
Definition: name.hpp:42
void wireDecode(const Block &block)
Interest & setInterestLifetime(time::milliseconds interestLifetime)
Set Interest&#39;s lifetime.
Definition: interest.cpp:332
Validation error code and optional detailed error message.
const Block & getContent() const
Get Content.
Definition: data.cpp:185
security::v2::Validator & m_validator
Definition: controller.hpp:173
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
function< void(uint32_t code, const std::string &reason)> DatasetFailCallback
a callback on dataset retrieval failure
Definition: controller.hpp:63
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:89