ndn-cxx: NDN C++ Library 0.9.0-33-g832ea91d
Loading...
Searching...
No Matches
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-2025 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
23#include "ndn-cxx/face.hpp"
25
26#include <boost/lexical_cast.hpp>
27
28namespace ndn::nfd {
29
31 : m_face(face)
32 , m_keyChain(keyChain)
33 , m_validator(validator)
34 , m_signer(keyChain)
35{
36}
37
39{
40 for (const auto& sp : m_fetchers) {
41 sp->stop();
42 }
43}
44
45void
46Controller::sendCommandRequest(Interest& interest,
47 const security::SigningInfo& signingInfo,
48 ResponseParametersValidator checkResponse,
49 CommandSuccessCallback onSuccess,
50 const CommandFailureCallback& onFailure)
51{
52 BOOST_ASSERT(checkResponse);
53
54 m_signer.makeSignedInterest(interest, signingInfo);
55
56 m_face.expressInterest(interest,
57 [=, check = std::move(checkResponse), success = std::move(onSuccess)] (const auto&, const Data& d) {
58 processCommandResponse(d, std::move(check), std::move(success), onFailure);
59 },
60 [onFailure] (const Interest&, const lp::Nack& nack) {
61 if (onFailure)
63 "received Nack: " + boost::lexical_cast<std::string>(nack.getReason())));
64 },
65 [onFailure] (const Interest&) {
66 if (onFailure)
67 onFailure(ControlResponse(Controller::ERROR_TIMEOUT, "request timed out"));
68 });
69}
70
71void
72Controller::processCommandResponse(const Data& data,
73 ResponseParametersValidator checkResponse,
74 CommandSuccessCallback onSuccess,
75 const CommandFailureCallback& onFailure)
76{
78 [check = std::move(checkResponse), success = std::move(onSuccess), onFailure] (const Data& d) {
79 processValidatedCommandResponse(d, check, success, onFailure);
80 },
81 [onFailure] (const Data&, const auto& error) {
82 if (onFailure)
83 onFailure(ControlResponse(ERROR_VALIDATION, boost::lexical_cast<std::string>(error)));
84 }
85 );
86}
87
88void
89Controller::processValidatedCommandResponse(const Data& data,
90 const ResponseParametersValidator& checkResponse,
91 const CommandSuccessCallback& onSuccess,
92 const CommandFailureCallback& onFailure)
93{
94 ControlResponse response;
95 try {
96 response.wireDecode(data.getContent().blockFromValue());
97 }
98 catch (const tlv::Error& e) {
99 if (onFailure)
100 onFailure(ControlResponse(ERROR_SERVER, "ControlResponse decoding failure: "s + e.what()));
101 return;
102 }
103
104 if (response.getCode() >= ERROR_LBOUND) {
105 if (onFailure)
106 onFailure(response);
107 return;
108 }
109
110 ControlParameters parameters;
111 try {
112 parameters.wireDecode(response.getBody());
113 }
114 catch (const tlv::Error& e) {
115 if (onFailure)
116 onFailure(ControlResponse(ERROR_SERVER, "ControlParameters decoding failure: "s + e.what()));
117 return;
118 }
119
120 try {
121 checkResponse(parameters);
122 }
123 catch (const std::invalid_argument& e) {
124 if (onFailure)
125 onFailure(ControlResponse(ERROR_SERVER, "Invalid response: "s + e.what()));
126 return;
127 }
128
129 if (onSuccess)
130 onSuccess(parameters);
131}
132
133void
134Controller::fetchDataset(const Name& prefix,
135 const std::function<void(ConstBufferPtr)>& processResponse,
136 const DatasetFailureCallback& onFailure,
137 const CommandOptions& options)
138{
139 SegmentFetcher::Options fetcherOptions;
140 fetcherOptions.maxTimeout = options.getTimeout();
141
142 auto fetcher = SegmentFetcher::start(m_face, Interest(prefix), m_validator, fetcherOptions);
143 fetcher->onComplete.connect(processResponse);
144 if (onFailure) {
145 fetcher->onError.connect([onFailure] (uint32_t code, const std::string& msg) {
146 processDatasetFetchError(onFailure, code, msg);
147 });
148 }
149
150 auto it = m_fetchers.insert(fetcher).first;
151 fetcher->onComplete.connect([this, it] (auto&&...) { m_fetchers.erase(it); });
152 fetcher->onError.connect([this, it] (auto&&...) { m_fetchers.erase(it); });
153}
154
155void
156Controller::processDatasetFetchError(const DatasetFailureCallback& onFailure,
157 uint32_t code, std::string msg)
158{
159 BOOST_ASSERT(onFailure);
160
161 switch (static_cast<SegmentFetcher::ErrorCode>(code)) {
162 // It's intentional to cast to SegmentFetcher::ErrorCode and to not have a 'default' clause.
163 // This forces the switch statement to handle every defined SegmentFetcher::ErrorCode,
164 // and breaks compilation if it does not.
166 onFailure(ERROR_TIMEOUT, msg);
167 break;
170 onFailure(ERROR_SERVER, msg);
171 break;
173 // TODO: When SegmentFetcher exposes validator error code, Controller::ERROR_VALIDATION
174 // should be replaced with a range that corresponds to validator error codes.
175 onFailure(ERROR_VALIDATION, msg);
176 break;
178 onFailure(ERROR_NACK, msg);
179 break;
180 }
181}
182
183} // namespace ndn::nfd
Represents a Data packet.
Definition data.hpp:39
Provide a communication channel with local or remote NDN forwarder.
Definition face.hpp:91
PendingInterestHandle expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express an Interest.
Definition face.cpp:151
Represents an Interest packet.
Definition interest.hpp:50
static shared_ptr< SegmentFetcher > start(Face &face, const Interest &baseInterest, security::Validator &validator, const Options &options={})
Initiates segment fetching.
ErrorCode
Error codes passed to onError.
@ INTEREST_TIMEOUT
Retrieval timed out because the maximum timeout between the successful receipt of segments was exceed...
@ FINALBLOCKID_NOT_SEGMENT
A received FinalBlockId did not contain a segment component.
@ NACK_ERROR
An unrecoverable Nack was received during retrieval.
@ SEGMENT_VALIDATION_FAIL
One of the retrieved segments failed user-provided validation.
@ DATA_HAS_NO_SEGMENT
One of the retrieved Data packets lacked a segment number in the last Name component (excl....
SegmentFetcherOptions Options
Represents a Network Nack.
Definition nack.hpp:39
void wireDecode(const Block &block)
Controller(Face &face, KeyChain &keyChain, security::Validator &validator=security::getAcceptAllValidator())
Construct a Controller that uses face as transport and keyChain to sign commands.
@ ERROR_LBOUND
Inclusive lower bound of error codes.
@ ERROR_VALIDATION
Error code for response validation failure.
@ ERROR_SERVER
Error code for server error.
@ ERROR_NACK
Error code for network Nack.
@ ERROR_TIMEOUT
Error code for timeout.
security::InterestSigner m_signer
security::Validator & m_validator
std::set< shared_ptr< SegmentFetcher > > m_fetchers
void makeSignedInterest(Interest &interest, SigningInfo params=SigningInfo(), uint32_t signingFlags=WantNonce|WantTime)
Signs an Interest (following Packet Specification v0.3 or newer)
The main interface for signing key management.
Definition key-chain.hpp:87
Signing parameters passed to KeyChain.
Interface for validating data and interest packets.
Definition validator.hpp:61
void validate(const Data &data, const DataValidationSuccessCallback &successCb, const DataValidationFailureCallback &failureCb)
Asynchronously validate data.
Definition validator.cpp:47
std::function< void(const ControlResponse &)> CommandFailureCallback
Callback on command failure.
std::function< void(uint32_t code, const std::string &reason)> DatasetFailureCallback
Callback on dataset retrieval failure.
std::function< void(const ControlParameters &)> CommandSuccessCallback
Callback on command success.
Contains classes and functions related to the NFD Management protocol.
mgmt::ControlResponse ControlResponse
@ Data
Definition tlv.hpp:69
@ Interest
Definition tlv.hpp:68
std::shared_ptr< const Buffer > ConstBufferPtr
Definition buffer.hpp:140
time::milliseconds maxTimeout
Maximum allowed time between successful receipt of segments.