blob: 4d02d15019aaf41fd23e028a7d19ed8f3c0ca93b [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
Junxiao Shi0ba6d642017-07-17 00:53:22 +000038/** \brief Parameters to ProtocolFactory constructor
39 *
40 * Every ProtocolFactory subclass is expected to have a constructor that accepts CtorParams,
41 * which in turn passes it to ProtocolFactory base class constructor. Parameters are passed as a
42 * struct rather than individually, so that a future change in list of parameters does not
43 * require updates to subclass constructors.
44 */
45struct ProtocolFactoryCtorParams
46{
47 FaceCreatedCallback addFace;
48 shared_ptr<ndn::net::NetworkMonitor> netmon;
49};
50
Junxiao Shi2d491752017-07-14 21:32:05 +000051/** \brief Provides support for an underlying protocol
Junxiao Shi38b24c72017-01-05 02:59:31 +000052 * \sa FaceSystem
53 *
54 * A protocol factory provides support for an underlying protocol and owns Channel objects.
55 * It can process a subsection of face_system config section and create channels and multicast
56 * faces accordingly.
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020057 */
Junxiao Shi38b24c72017-01-05 02:59:31 +000058class ProtocolFactory : noncopyable
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080059{
Junxiao Shib47247d2017-01-24 15:09:16 +000060public: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +000061 using CtorParams = ProtocolFactoryCtorParams;
62
Junxiao Shi2d491752017-07-14 21:32:05 +000063 /** \brief Register a protocol factory type
Davide Pesaventod27841b2018-11-13 00:22:24 -050064 * \tparam PF subclass of ProtocolFactory
Junxiao Shib47247d2017-01-24 15:09:16 +000065 * \param id factory identifier
66 */
67 template<typename PF>
68 static void
69 registerType(const std::string& id = PF::getId())
70 {
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040071 BOOST_ASSERT(!id.empty());
72 auto r = getRegistry().insert_or_assign(id, [] (auto&&... p) {
73 return make_unique<PF>(std::forward<decltype(p)>(p)...);
74 });
75 BOOST_VERIFY(r.second);
Junxiao Shib47247d2017-01-24 15:09:16 +000076 }
77
Junxiao Shi2d491752017-07-14 21:32:05 +000078 /** \brief Create a protocol factory instance
Davide Pesaventod27841b2018-11-13 00:22:24 -050079 * \retval nullptr if a factory with the given \p id is not registered
Junxiao Shib47247d2017-01-24 15:09:16 +000080 */
81 static unique_ptr<ProtocolFactory>
Junxiao Shi0ba6d642017-07-17 00:53:22 +000082 create(const std::string& id, const CtorParams& params);
Junxiao Shib47247d2017-01-24 15:09:16 +000083
Davide Pesaventod27841b2018-11-13 00:22:24 -050084 /** \brief Get all registered protocol factory ids
Junxiao Shib47247d2017-01-24 15:09:16 +000085 */
86 static std::set<std::string>
87 listRegistered();
88
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080089public:
Junxiao Shi0ba6d642017-07-17 00:53:22 +000090 /** \brief Base class for all exceptions thrown by ProtocolFactory subclasses
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080091 */
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020092 class Error : public std::runtime_error
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080093 {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020094 public:
Davide Pesaventod27841b2018-11-13 00:22:24 -050095 using std::runtime_error::runtime_error;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080096 };
Alexander Afanasyevd6655302014-02-28 08:41:28 -080097
Davide Pesaventod27841b2018-11-13 00:22:24 -050098 explicit
99 ProtocolFactory(const CtorParams& params);
100
Junxiao Shib47247d2017-01-24 15:09:16 +0000101 virtual
Davide Pesaventod27841b2018-11-13 00:22:24 -0500102 ~ProtocolFactory() = 0;
Junxiao Shib47247d2017-01-24 15:09:16 +0000103
104#ifdef DOXYGEN
Davide Pesaventod27841b2018-11-13 00:22:24 -0500105 /** \brief Get id for this protocol factory
Junxiao Shib47247d2017-01-24 15:09:16 +0000106 *
107 * face_system.factory-id config section is processed by the protocol factory.
108 */
109 static const std::string&
Davide Pesaventod27841b2018-11-13 00:22:24 -0500110 getId() noexcept;
Junxiao Shib47247d2017-01-24 15:09:16 +0000111#endif
112
Davide Pesaventod27841b2018-11-13 00:22:24 -0500113 /** \brief Get FaceUri schemes accepted by this protocol factory
Junxiao Shi38b24c72017-01-05 02:59:31 +0000114 */
115 const std::set<std::string>&
Davide Pesaventod27841b2018-11-13 00:22:24 -0500116 getProvidedSchemes() const
Junxiao Shi38b24c72017-01-05 02:59:31 +0000117 {
118 return providedSchemes;
119 }
120
Davide Pesaventod27841b2018-11-13 00:22:24 -0500121 /** \brief Process face_system subsection that corresponds to this protocol factory id
122 * \param configSection the configuration section or boost::none to indicate it is omitted
123 * \param context provides access to data structures and contextual information
124 * \throw ConfigFile::Error invalid configuration
125 */
126 void
127 processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
128
Davide Pesavento15b55052018-01-27 19:09:28 -0500129 /** \brief Encapsulates a face creation request and all its parameters
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800130 *
Eric Newberry944f38b2017-07-20 20:54:22 -0400131 * Parameters are passed as a struct rather than individually, so that a future change in the list
132 * of parameters does not require an update to the method signature in all subclasses.
133 */
Davide Pesavento15b55052018-01-27 19:09:28 -0500134 struct CreateFaceRequest
Eric Newberry944f38b2017-07-20 20:54:22 -0400135 {
136 FaceUri remoteUri;
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400137 std::optional<FaceUri> localUri;
Davide Pesavento15b55052018-01-27 19:09:28 -0500138 FaceParams params;
Eric Newberry944f38b2017-07-20 20:54:22 -0400139 };
140
Davide Pesaventod27841b2018-11-13 00:22:24 -0500141 /** \brief Create a unicast face
142 * \param req request object containing the face creation parameters
143 * \param onCreated callback if face creation succeeds or face already exists; the settings
144 * of an existing face are not updated if they differ from the request
145 * \param onFailure callback if face creation fails
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800146 */
Davide Pesaventod27841b2018-11-13 00:22:24 -0500147 void
Davide Pesavento15b55052018-01-27 19:09:28 -0500148 createFace(const CreateFaceRequest& req,
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800149 const FaceCreatedCallback& onCreated,
Davide Pesaventod27841b2018-11-13 00:22:24 -0500150 const FaceCreationFailedCallback& onFailure);
Junxiao Shi38b24c72017-01-05 02:59:31 +0000151
Junxiao Shieef49a92018-11-10 12:19:36 +0000152 /** \brief Create a netdev-bound face
153 * \param remote remote FaceUri, must be canonical
154 * \param netdev local network interface
155 * \return new face
156 * \throw Error cannot create a face using specified arguments
157 * \note The caller must ensure there is no existing netdev-bound face with same remote FaceUri
158 * on the same local network interface.
159 */
160 shared_ptr<Face>
161 createNetdevBoundFace(const FaceUri& remote,
162 const shared_ptr<const ndn::net::NetworkInterface>& netdev);
163
Davide Pesaventod27841b2018-11-13 00:22:24 -0500164 /** \brief Get list of open channels (listening + non-listening)
165 */
166 std::vector<shared_ptr<const Channel>>
167 getChannels() const;
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000168
Davide Pesaventod27841b2018-11-13 00:22:24 -0500169protected:
Junxiao Shi38b24c72017-01-05 02:59:31 +0000170 template<typename ChannelMap>
171 static std::vector<shared_ptr<const Channel>>
172 getChannelsFromMap(const ChannelMap& channelMap)
173 {
174 std::vector<shared_ptr<const Channel>> channels;
175 boost::copy(channelMap | boost::adaptors::map_values, std::back_inserter(channels));
176 return channels;
177 }
178
Junxiao Shieef49a92018-11-10 12:19:36 +0000179private:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500180 /** \brief Process face_system subsection that corresponds to this protocol factory id
181 * \sa processConfig
182 *
183 * A subclass should override this method if it supports configuration options in the config
184 * file, and do all the required processing here. The subclass should throw ConfigFile::Error
185 * if it encounters unrecognized options or invalid values. It should also update
186 * \p providedSchemes as needed.
187 *
188 * The base class implementation does nothing.
189 */
190 virtual void
191 doProcessConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
192
193 /** \brief Create a unicast face
194 * \sa createFace
195 *
196 * The base class implementation always invokes the failure callback with error code 406,
197 * indicating unicast face creation is not supported.
198 */
199 virtual void
200 doCreateFace(const CreateFaceRequest& req,
201 const FaceCreatedCallback& onCreated,
202 const FaceCreationFailedCallback& onFailure);
203
Junxiao Shieef49a92018-11-10 12:19:36 +0000204 /** \brief Create a netdev-bound face
205 * \sa createNetdevBoundFace
206 *
Davide Pesaventod27841b2018-11-13 00:22:24 -0500207 * The base class implementation always throws Error, indicating netdev-bound faces are not
Junxiao Shieef49a92018-11-10 12:19:36 +0000208 * supported.
209 *
210 * A subclass that offers netdev-bound faces should override this method, and also expose
211 * "scheme+dev" in providedSchemes. For example, UdpFactory should provide "udp4+dev" scheme,
212 * in addition to "udp4" scheme.
213 *
214 * The face should be constructed immediately. Face persistency shall be reported as PERMANENT.
215 * Face state shall remain DOWN until underlying transport is connected. The face shall remain
216 * open until after .close() is invoked, and survive all socket errors; in case the network
217 * interface disappears, the face shall remain DOWN until .close() is invoked.
218 */
219 virtual shared_ptr<Face>
220 doCreateNetdevBoundFace(const FaceUri& remote,
221 const shared_ptr<const ndn::net::NetworkInterface>& netif);
222
Davide Pesaventod27841b2018-11-13 00:22:24 -0500223 /** \brief Get list of open channels (listening + non-listening)
224 * \sa getChannels
225 *
226 * The base class implementation returns an empty list.
227 */
228 virtual std::vector<shared_ptr<const Channel>>
229 doGetChannels() const;
230
Junxiao Shib47247d2017-01-24 15:09:16 +0000231private: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000232 using CreateFunc = std::function<unique_ptr<ProtocolFactory>(const CtorParams&)>;
233 using Registry = std::map<std::string, CreateFunc>; // indexed by factory id
Junxiao Shib47247d2017-01-24 15:09:16 +0000234
235 static Registry&
236 getRegistry();
237
Junxiao Shi38b24c72017-01-05 02:59:31 +0000238protected:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500239 std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this protocol factory
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000240 FaceCreatedCallback addFace; ///< callback when a new face is created
241
Junxiao Shi2d491752017-07-14 21:32:05 +0000242 /** \brief NetworkMonitor for listing available network interfaces and monitoring their changes
243 *
244 * ProtocolFactory subclass should check the NetworkMonitor has sufficient capabilities prior
245 * to usage.
Junxiao Shi38b24c72017-01-05 02:59:31 +0000246 */
Junxiao Shi2d491752017-07-14 21:32:05 +0000247 shared_ptr<ndn::net::NetworkMonitor> netmon;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800248};
249
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400250} // namespace nfd::face
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800251
Davide Pesaventod27841b2018-11-13 00:22:24 -0500252/** \brief Registers a protocol factory
Junxiao Shib47247d2017-01-24 15:09:16 +0000253 *
Davide Pesaventod27841b2018-11-13 00:22:24 -0500254 * This macro should appear once in the .cpp file of each protocol factory.
Junxiao Shib47247d2017-01-24 15:09:16 +0000255 */
256#define NFD_REGISTER_PROTOCOL_FACTORY(PF) \
257static class NfdAuto ## PF ## ProtocolFactoryRegistrationClass \
258{ \
259public: \
260 NfdAuto ## PF ## ProtocolFactoryRegistrationClass() \
261 { \
262 ::nfd::face::ProtocolFactory::registerType<PF>(); \
263 } \
264} g_nfdAuto ## PF ## ProtocolFactoryRegistrationVariable
265
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700266#endif // NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP