blob: c490e07fd4915d4ffccbec4e15817a7f5652f75a [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 Pesaventob7bfcb92022-05-22 23:55:23 -04003 * Copyright (c) 2014-2022, 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 Pesaventoe422f9e2022-06-03 01:30:23 -040036namespace nfd::face {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080037
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040038/**
39 * \brief Parameters to ProtocolFactory constructor.
Junxiao Shi0ba6d642017-07-17 00:53:22 +000040 *
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040041 * Every ProtocolFactory subclass is expected to have a constructor that accepts
42 * ProtocolFactory::CtorParams, which in turn passes it to ProtocolFactory base class
43 * constructor. Parameters are passed as a struct rather than individually, so that
44 * any future changes in the list of parameters will not require updates to all subclass
45 * constructors.
Junxiao Shi0ba6d642017-07-17 00:53:22 +000046 */
47struct ProtocolFactoryCtorParams
48{
49 FaceCreatedCallback addFace;
50 shared_ptr<ndn::net::NetworkMonitor> netmon;
51};
52
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040053/**
54 * \brief Provides support for an underlying protocol.
Junxiao Shi38b24c72017-01-05 02:59:31 +000055 *
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040056 * A protocol factory provides support for an underlying protocol and owns Channel objects.
57 * It can process a subsection of the `face_system` configuration section and create channels
58 * and multicast faces accordingly.
59 *
60 * \sa FaceSystem
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020061 */
Junxiao Shi38b24c72017-01-05 02:59:31 +000062class ProtocolFactory : noncopyable
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080063{
Junxiao Shib47247d2017-01-24 15:09:16 +000064public: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +000065 using CtorParams = ProtocolFactoryCtorParams;
66
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040067 /**
68 * \brief Register a protocol factory type.
69 * \tparam PF subclass of ProtocolFactory
70 * \param id factory identifier
Junxiao Shib47247d2017-01-24 15:09:16 +000071 */
72 template<typename PF>
73 static void
74 registerType(const std::string& id = PF::getId())
75 {
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040076 BOOST_ASSERT(!id.empty());
77 auto r = getRegistry().insert_or_assign(id, [] (auto&&... p) {
78 return make_unique<PF>(std::forward<decltype(p)>(p)...);
79 });
80 BOOST_VERIFY(r.second);
Junxiao Shib47247d2017-01-24 15:09:16 +000081 }
82
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040083 /**
84 * \brief Create a protocol factory instance.
85 * \retval nullptr if a factory with the given \p id is not registered
Junxiao Shib47247d2017-01-24 15:09:16 +000086 */
87 static unique_ptr<ProtocolFactory>
Junxiao Shi0ba6d642017-07-17 00:53:22 +000088 create(const std::string& id, const CtorParams& params);
Junxiao Shib47247d2017-01-24 15:09:16 +000089
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040090 /**
91 * \brief Get all registered protocol factory IDs.
Junxiao Shib47247d2017-01-24 15:09:16 +000092 */
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040093 [[nodiscard]] static std::set<std::string>
Junxiao Shib47247d2017-01-24 15:09:16 +000094 listRegistered();
95
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080096public:
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040097 /**
98 * \brief Base class for all exceptions thrown by ProtocolFactory subclasses.
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080099 */
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200100 class Error : public std::runtime_error
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800101 {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200102 public:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500103 using std::runtime_error::runtime_error;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800104 };
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800105
Davide Pesaventod27841b2018-11-13 00:22:24 -0500106 explicit
107 ProtocolFactory(const CtorParams& params);
108
Junxiao Shib47247d2017-01-24 15:09:16 +0000109 virtual
Davide Pesaventod27841b2018-11-13 00:22:24 -0500110 ~ProtocolFactory() = 0;
Junxiao Shib47247d2017-01-24 15:09:16 +0000111
112#ifdef DOXYGEN
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400113 /**
114 * \brief Get the ID of this protocol factory.
Junxiao Shib47247d2017-01-24 15:09:16 +0000115 *
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400116 * `face_system.<factory-id>` config section is processed by the protocol factory.
Junxiao Shib47247d2017-01-24 15:09:16 +0000117 */
118 static const std::string&
Davide Pesaventod27841b2018-11-13 00:22:24 -0500119 getId() noexcept;
Junxiao Shib47247d2017-01-24 15:09:16 +0000120#endif
121
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400122 /**
123 * \brief Get FaceUri schemes accepted by this protocol factory.
Junxiao Shi38b24c72017-01-05 02:59:31 +0000124 */
125 const std::set<std::string>&
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400126 getProvidedSchemes() const noexcept
Junxiao Shi38b24c72017-01-05 02:59:31 +0000127 {
128 return providedSchemes;
129 }
130
Davide Pesaventod27841b2018-11-13 00:22:24 -0500131 /** \brief Process face_system subsection that corresponds to this protocol factory id
132 * \param configSection the configuration section or boost::none to indicate it is omitted
133 * \param context provides access to data structures and contextual information
134 * \throw ConfigFile::Error invalid configuration
135 */
136 void
137 processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
138
Davide Pesavento15b55052018-01-27 19:09:28 -0500139 /** \brief Encapsulates a face creation request and all its parameters
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800140 *
Eric Newberry944f38b2017-07-20 20:54:22 -0400141 * Parameters are passed as a struct rather than individually, so that a future change in the list
142 * of parameters does not require an update to the method signature in all subclasses.
143 */
Davide Pesavento15b55052018-01-27 19:09:28 -0500144 struct CreateFaceRequest
Eric Newberry944f38b2017-07-20 20:54:22 -0400145 {
146 FaceUri remoteUri;
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400147 std::optional<FaceUri> localUri;
Davide Pesavento15b55052018-01-27 19:09:28 -0500148 FaceParams params;
Eric Newberry944f38b2017-07-20 20:54:22 -0400149 };
150
Davide Pesaventod27841b2018-11-13 00:22:24 -0500151 /** \brief Create a unicast face
152 * \param req request object containing the face creation parameters
153 * \param onCreated callback if face creation succeeds or face already exists; the settings
154 * of an existing face are not updated if they differ from the request
155 * \param onFailure callback if face creation fails
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800156 */
Davide Pesaventod27841b2018-11-13 00:22:24 -0500157 void
Davide Pesavento15b55052018-01-27 19:09:28 -0500158 createFace(const CreateFaceRequest& req,
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800159 const FaceCreatedCallback& onCreated,
Davide Pesaventod27841b2018-11-13 00:22:24 -0500160 const FaceCreationFailedCallback& onFailure);
Junxiao Shi38b24c72017-01-05 02:59:31 +0000161
Junxiao Shieef49a92018-11-10 12:19:36 +0000162 /** \brief Create a netdev-bound face
163 * \param remote remote FaceUri, must be canonical
164 * \param netdev local network interface
165 * \return new face
166 * \throw Error cannot create a face using specified arguments
167 * \note The caller must ensure there is no existing netdev-bound face with same remote FaceUri
168 * on the same local network interface.
169 */
170 shared_ptr<Face>
171 createNetdevBoundFace(const FaceUri& remote,
172 const shared_ptr<const ndn::net::NetworkInterface>& netdev);
173
Davide Pesaventod27841b2018-11-13 00:22:24 -0500174 /** \brief Get list of open channels (listening + non-listening)
175 */
176 std::vector<shared_ptr<const Channel>>
177 getChannels() const;
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000178
Davide Pesaventod27841b2018-11-13 00:22:24 -0500179protected:
Junxiao Shi38b24c72017-01-05 02:59:31 +0000180 template<typename ChannelMap>
181 static std::vector<shared_ptr<const Channel>>
182 getChannelsFromMap(const ChannelMap& channelMap)
183 {
184 std::vector<shared_ptr<const Channel>> channels;
185 boost::copy(channelMap | boost::adaptors::map_values, std::back_inserter(channels));
186 return channels;
187 }
188
Junxiao Shieef49a92018-11-10 12:19:36 +0000189private:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500190 /** \brief Process face_system subsection that corresponds to this protocol factory id
191 * \sa processConfig
192 *
193 * A subclass should override this method if it supports configuration options in the config
194 * file, and do all the required processing here. The subclass should throw ConfigFile::Error
195 * if it encounters unrecognized options or invalid values. It should also update
196 * \p providedSchemes as needed.
197 *
198 * The base class implementation does nothing.
199 */
200 virtual void
201 doProcessConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
202
203 /** \brief Create a unicast face
204 * \sa createFace
205 *
206 * The base class implementation always invokes the failure callback with error code 406,
207 * indicating unicast face creation is not supported.
208 */
209 virtual void
210 doCreateFace(const CreateFaceRequest& req,
211 const FaceCreatedCallback& onCreated,
212 const FaceCreationFailedCallback& onFailure);
213
Junxiao Shieef49a92018-11-10 12:19:36 +0000214 /** \brief Create a netdev-bound face
215 * \sa createNetdevBoundFace
216 *
Davide Pesaventod27841b2018-11-13 00:22:24 -0500217 * The base class implementation always throws Error, indicating netdev-bound faces are not
Junxiao Shieef49a92018-11-10 12:19:36 +0000218 * supported.
219 *
220 * A subclass that offers netdev-bound faces should override this method, and also expose
221 * "scheme+dev" in providedSchemes. For example, UdpFactory should provide "udp4+dev" scheme,
222 * in addition to "udp4" scheme.
223 *
224 * The face should be constructed immediately. Face persistency shall be reported as PERMANENT.
225 * Face state shall remain DOWN until underlying transport is connected. The face shall remain
226 * open until after .close() is invoked, and survive all socket errors; in case the network
227 * interface disappears, the face shall remain DOWN until .close() is invoked.
228 */
229 virtual shared_ptr<Face>
230 doCreateNetdevBoundFace(const FaceUri& remote,
231 const shared_ptr<const ndn::net::NetworkInterface>& netif);
232
Davide Pesaventod27841b2018-11-13 00:22:24 -0500233 /** \brief Get list of open channels (listening + non-listening)
234 * \sa getChannels
235 *
236 * The base class implementation returns an empty list.
237 */
238 virtual std::vector<shared_ptr<const Channel>>
239 doGetChannels() const;
240
Junxiao Shib47247d2017-01-24 15:09:16 +0000241private: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000242 using CreateFunc = std::function<unique_ptr<ProtocolFactory>(const CtorParams&)>;
243 using Registry = std::map<std::string, CreateFunc>; // indexed by factory id
Junxiao Shib47247d2017-01-24 15:09:16 +0000244
245 static Registry&
246 getRegistry();
247
Junxiao Shi38b24c72017-01-05 02:59:31 +0000248protected:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500249 std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this protocol factory
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000250 FaceCreatedCallback addFace; ///< callback when a new face is created
251
Junxiao Shi2d491752017-07-14 21:32:05 +0000252 /** \brief NetworkMonitor for listing available network interfaces and monitoring their changes
253 *
254 * ProtocolFactory subclass should check the NetworkMonitor has sufficient capabilities prior
255 * to usage.
Junxiao Shi38b24c72017-01-05 02:59:31 +0000256 */
Junxiao Shi2d491752017-07-14 21:32:05 +0000257 shared_ptr<ndn::net::NetworkMonitor> netmon;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800258};
259
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400260} // namespace nfd::face
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800261
Davide Pesaventod27841b2018-11-13 00:22:24 -0500262/** \brief Registers a protocol factory
Junxiao Shib47247d2017-01-24 15:09:16 +0000263 *
Davide Pesaventod27841b2018-11-13 00:22:24 -0500264 * This macro should appear once in the .cpp file of each protocol factory.
Junxiao Shib47247d2017-01-24 15:09:16 +0000265 */
266#define NFD_REGISTER_PROTOCOL_FACTORY(PF) \
267static class NfdAuto ## PF ## ProtocolFactoryRegistrationClass \
268{ \
269public: \
270 NfdAuto ## PF ## ProtocolFactoryRegistrationClass() \
271 { \
272 ::nfd::face::ProtocolFactory::registerType<PF>(); \
273 } \
274} g_nfdAuto ## PF ## ProtocolFactoryRegistrationVariable
275
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700276#endif // NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP