blob: 56095bbe6e37e42ac176416efb265f8810503915 [file] [log] [blame]
Alexander Afanasyeva9034b02014-01-26 18:32:02 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2d491752017-07-14 21:32:05 +00002/*
Davide Pesavento2c9d2ca2024-01-27 16:36:51 -05003 * Copyright (c) 2014-2024, Regents of the University of California,
Davide Pesavento1d7e7af2015-10-10 23:54:08 +02004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Steve DiBenedettoef04f272014-06-04 14:28:31 -060024 */
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080025
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070026#ifndef NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP
27#define NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080028
Davide Pesavento47ab0292015-11-02 18:45:39 +010029#include "channel.hpp"
Davide Pesaventocb425e82019-07-14 21:48:22 -040030#include "face.hpp"
Junxiao Shi38b24c72017-01-05 02:59:31 +000031#include "face-system.hpp"
Davide Pesaventoe5eebad2017-04-06 20:23:26 -040032
Junxiao Shi38b24c72017-01-05 02:59:31 +000033#include <boost/range/adaptor/map.hpp>
34#include <boost/range/algorithm/copy.hpp>
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080035
Davide Pesavento2c9d2ca2024-01-27 16:36:51 -050036#include <functional>
37#include <map>
38#include <set>
39
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040040namespace nfd::face {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080041
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040042/**
43 * \brief Parameters to ProtocolFactory constructor.
Junxiao Shi0ba6d642017-07-17 00:53:22 +000044 *
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040045 * Every ProtocolFactory subclass is expected to have a constructor that accepts
46 * ProtocolFactory::CtorParams, which in turn passes it to ProtocolFactory base class
47 * constructor. Parameters are passed as a struct rather than individually, so that
48 * any future changes in the list of parameters will not require updates to all subclass
49 * constructors.
Junxiao Shi0ba6d642017-07-17 00:53:22 +000050 */
51struct ProtocolFactoryCtorParams
52{
53 FaceCreatedCallback addFace;
54 shared_ptr<ndn::net::NetworkMonitor> netmon;
55};
56
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040057/**
58 * \brief Provides support for an underlying protocol.
Junxiao Shi38b24c72017-01-05 02:59:31 +000059 *
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040060 * A protocol factory provides support for an underlying protocol and owns Channel objects.
61 * It can process a subsection of the `face_system` configuration section and create channels
62 * and multicast faces accordingly.
63 *
64 * \sa FaceSystem
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020065 */
Junxiao Shi38b24c72017-01-05 02:59:31 +000066class ProtocolFactory : noncopyable
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080067{
Junxiao Shib47247d2017-01-24 15:09:16 +000068public: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +000069 using CtorParams = ProtocolFactoryCtorParams;
70
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040071 /**
72 * \brief Register a protocol factory type.
73 * \tparam PF subclass of ProtocolFactory
74 * \param id factory identifier
Junxiao Shib47247d2017-01-24 15:09:16 +000075 */
76 template<typename PF>
77 static void
78 registerType(const std::string& id = PF::getId())
79 {
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040080 BOOST_ASSERT(!id.empty());
81 auto r = getRegistry().insert_or_assign(id, [] (auto&&... p) {
82 return make_unique<PF>(std::forward<decltype(p)>(p)...);
83 });
84 BOOST_VERIFY(r.second);
Junxiao Shib47247d2017-01-24 15:09:16 +000085 }
86
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040087 /**
88 * \brief Create a protocol factory instance.
89 * \retval nullptr if a factory with the given \p id is not registered
Junxiao Shib47247d2017-01-24 15:09:16 +000090 */
91 static unique_ptr<ProtocolFactory>
Junxiao Shi0ba6d642017-07-17 00:53:22 +000092 create(const std::string& id, const CtorParams& params);
Junxiao Shib47247d2017-01-24 15:09:16 +000093
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040094 /**
95 * \brief Get all registered protocol factory IDs.
Junxiao Shib47247d2017-01-24 15:09:16 +000096 */
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040097 [[nodiscard]] static std::set<std::string>
Junxiao Shib47247d2017-01-24 15:09:16 +000098 listRegistered();
99
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800100public:
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400101 /**
102 * \brief Base class for all exceptions thrown by ProtocolFactory subclasses.
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800103 */
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200104 class Error : public std::runtime_error
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800105 {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200106 public:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500107 using std::runtime_error::runtime_error;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800108 };
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800109
Davide Pesaventod27841b2018-11-13 00:22:24 -0500110 explicit
111 ProtocolFactory(const CtorParams& params);
112
Junxiao Shib47247d2017-01-24 15:09:16 +0000113 virtual
Davide Pesaventod27841b2018-11-13 00:22:24 -0500114 ~ProtocolFactory() = 0;
Junxiao Shib47247d2017-01-24 15:09:16 +0000115
116#ifdef DOXYGEN
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400117 /**
118 * \brief Get the ID of this protocol factory.
Junxiao Shib47247d2017-01-24 15:09:16 +0000119 *
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400120 * `face_system.<factory-id>` config section is processed by the protocol factory.
Junxiao Shib47247d2017-01-24 15:09:16 +0000121 */
122 static const std::string&
Davide Pesaventod27841b2018-11-13 00:22:24 -0500123 getId() noexcept;
Junxiao Shib47247d2017-01-24 15:09:16 +0000124#endif
125
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400126 /**
127 * \brief Get FaceUri schemes accepted by this protocol factory.
Junxiao Shi38b24c72017-01-05 02:59:31 +0000128 */
129 const std::set<std::string>&
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400130 getProvidedSchemes() const noexcept
Junxiao Shi38b24c72017-01-05 02:59:31 +0000131 {
132 return providedSchemes;
133 }
134
Davide Pesaventod27841b2018-11-13 00:22:24 -0500135 /** \brief Process face_system subsection that corresponds to this protocol factory id
136 * \param configSection the configuration section or boost::none to indicate it is omitted
137 * \param context provides access to data structures and contextual information
138 * \throw ConfigFile::Error invalid configuration
139 */
140 void
141 processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
142
Davide Pesavento15b55052018-01-27 19:09:28 -0500143 /** \brief Encapsulates a face creation request and all its parameters
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800144 *
Eric Newberry944f38b2017-07-20 20:54:22 -0400145 * Parameters are passed as a struct rather than individually, so that a future change in the list
146 * of parameters does not require an update to the method signature in all subclasses.
147 */
Davide Pesavento15b55052018-01-27 19:09:28 -0500148 struct CreateFaceRequest
Eric Newberry944f38b2017-07-20 20:54:22 -0400149 {
150 FaceUri remoteUri;
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400151 std::optional<FaceUri> localUri;
Davide Pesavento15b55052018-01-27 19:09:28 -0500152 FaceParams params;
Eric Newberry944f38b2017-07-20 20:54:22 -0400153 };
154
Davide Pesaventod27841b2018-11-13 00:22:24 -0500155 /** \brief Create a unicast face
156 * \param req request object containing the face creation parameters
157 * \param onCreated callback if face creation succeeds or face already exists; the settings
158 * of an existing face are not updated if they differ from the request
159 * \param onFailure callback if face creation fails
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800160 */
Davide Pesaventod27841b2018-11-13 00:22:24 -0500161 void
Davide Pesavento15b55052018-01-27 19:09:28 -0500162 createFace(const CreateFaceRequest& req,
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800163 const FaceCreatedCallback& onCreated,
Davide Pesaventod27841b2018-11-13 00:22:24 -0500164 const FaceCreationFailedCallback& onFailure);
Junxiao Shi38b24c72017-01-05 02:59:31 +0000165
Junxiao Shieef49a92018-11-10 12:19:36 +0000166 /** \brief Create a netdev-bound face
167 * \param remote remote FaceUri, must be canonical
168 * \param netdev local network interface
169 * \return new face
170 * \throw Error cannot create a face using specified arguments
171 * \note The caller must ensure there is no existing netdev-bound face with same remote FaceUri
172 * on the same local network interface.
173 */
174 shared_ptr<Face>
175 createNetdevBoundFace(const FaceUri& remote,
176 const shared_ptr<const ndn::net::NetworkInterface>& netdev);
177
Davide Pesaventod27841b2018-11-13 00:22:24 -0500178 /** \brief Get list of open channels (listening + non-listening)
179 */
180 std::vector<shared_ptr<const Channel>>
181 getChannels() const;
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000182
Davide Pesaventod27841b2018-11-13 00:22:24 -0500183protected:
Junxiao Shi38b24c72017-01-05 02:59:31 +0000184 template<typename ChannelMap>
185 static std::vector<shared_ptr<const Channel>>
186 getChannelsFromMap(const ChannelMap& channelMap)
187 {
188 std::vector<shared_ptr<const Channel>> channels;
189 boost::copy(channelMap | boost::adaptors::map_values, std::back_inserter(channels));
190 return channels;
191 }
192
Junxiao Shieef49a92018-11-10 12:19:36 +0000193private:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500194 /** \brief Process face_system subsection that corresponds to this protocol factory id
195 * \sa processConfig
196 *
197 * A subclass should override this method if it supports configuration options in the config
198 * file, and do all the required processing here. The subclass should throw ConfigFile::Error
199 * if it encounters unrecognized options or invalid values. It should also update
200 * \p providedSchemes as needed.
201 *
202 * The base class implementation does nothing.
203 */
204 virtual void
205 doProcessConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
206
207 /** \brief Create a unicast face
208 * \sa createFace
209 *
210 * The base class implementation always invokes the failure callback with error code 406,
211 * indicating unicast face creation is not supported.
212 */
213 virtual void
214 doCreateFace(const CreateFaceRequest& req,
215 const FaceCreatedCallback& onCreated,
216 const FaceCreationFailedCallback& onFailure);
217
Junxiao Shieef49a92018-11-10 12:19:36 +0000218 /** \brief Create a netdev-bound face
219 * \sa createNetdevBoundFace
220 *
Davide Pesaventod27841b2018-11-13 00:22:24 -0500221 * The base class implementation always throws Error, indicating netdev-bound faces are not
Junxiao Shieef49a92018-11-10 12:19:36 +0000222 * supported.
223 *
224 * A subclass that offers netdev-bound faces should override this method, and also expose
225 * "scheme+dev" in providedSchemes. For example, UdpFactory should provide "udp4+dev" scheme,
226 * in addition to "udp4" scheme.
227 *
228 * The face should be constructed immediately. Face persistency shall be reported as PERMANENT.
229 * Face state shall remain DOWN until underlying transport is connected. The face shall remain
230 * open until after .close() is invoked, and survive all socket errors; in case the network
231 * interface disappears, the face shall remain DOWN until .close() is invoked.
232 */
233 virtual shared_ptr<Face>
234 doCreateNetdevBoundFace(const FaceUri& remote,
235 const shared_ptr<const ndn::net::NetworkInterface>& netif);
236
Davide Pesaventod27841b2018-11-13 00:22:24 -0500237 /** \brief Get list of open channels (listening + non-listening)
238 * \sa getChannels
239 *
240 * The base class implementation returns an empty list.
241 */
242 virtual std::vector<shared_ptr<const Channel>>
243 doGetChannels() const;
244
Junxiao Shib47247d2017-01-24 15:09:16 +0000245private: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000246 using CreateFunc = std::function<unique_ptr<ProtocolFactory>(const CtorParams&)>;
247 using Registry = std::map<std::string, CreateFunc>; // indexed by factory id
Junxiao Shib47247d2017-01-24 15:09:16 +0000248
249 static Registry&
250 getRegistry();
251
Junxiao Shi38b24c72017-01-05 02:59:31 +0000252protected:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500253 std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this protocol factory
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000254 FaceCreatedCallback addFace; ///< callback when a new face is created
255
Junxiao Shi2d491752017-07-14 21:32:05 +0000256 /** \brief NetworkMonitor for listing available network interfaces and monitoring their changes
257 *
258 * ProtocolFactory subclass should check the NetworkMonitor has sufficient capabilities prior
259 * to usage.
Junxiao Shi38b24c72017-01-05 02:59:31 +0000260 */
Junxiao Shi2d491752017-07-14 21:32:05 +0000261 shared_ptr<ndn::net::NetworkMonitor> netmon;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800262};
263
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400264} // namespace nfd::face
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800265
Davide Pesaventod27841b2018-11-13 00:22:24 -0500266/** \brief Registers a protocol factory
Junxiao Shib47247d2017-01-24 15:09:16 +0000267 *
Davide Pesaventod27841b2018-11-13 00:22:24 -0500268 * This macro should appear once in the .cpp file of each protocol factory.
Junxiao Shib47247d2017-01-24 15:09:16 +0000269 */
270#define NFD_REGISTER_PROTOCOL_FACTORY(PF) \
271static class NfdAuto ## PF ## ProtocolFactoryRegistrationClass \
272{ \
273public: \
274 NfdAuto ## PF ## ProtocolFactoryRegistrationClass() \
275 { \
276 ::nfd::face::ProtocolFactory::registerType<PF>(); \
277 } \
278} g_nfdAuto ## PF ## ProtocolFactoryRegistrationVariable
279
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700280#endif // NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP