blob: ed87de3266b4bdaf31ff2ba46221e0041cba4a98 [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 Pesaventocb425e82019-07-14 21:48:22 -04003 * Copyright (c) 2014-2019, 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
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080036namespace nfd {
Junxiao Shi38b24c72017-01-05 02:59:31 +000037namespace face {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080038
Junxiao Shi0ba6d642017-07-17 00:53:22 +000039/** \brief Parameters to ProtocolFactory constructor
40 *
41 * Every ProtocolFactory subclass is expected to have a constructor that accepts CtorParams,
42 * which in turn passes it to ProtocolFactory base class constructor. Parameters are passed as a
43 * struct rather than individually, so that a future change in list of parameters does not
44 * require updates to subclass constructors.
45 */
46struct ProtocolFactoryCtorParams
47{
48 FaceCreatedCallback addFace;
49 shared_ptr<ndn::net::NetworkMonitor> netmon;
50};
51
Junxiao Shi2d491752017-07-14 21:32:05 +000052/** \brief Provides support for an underlying protocol
Junxiao Shi38b24c72017-01-05 02:59:31 +000053 * \sa FaceSystem
54 *
55 * A protocol factory provides support for an underlying protocol and owns Channel objects.
56 * It can process a subsection of face_system config section and create channels and multicast
57 * faces accordingly.
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020058 */
Junxiao Shi38b24c72017-01-05 02:59:31 +000059class ProtocolFactory : noncopyable
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080060{
Junxiao Shib47247d2017-01-24 15:09:16 +000061public: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +000062 using CtorParams = ProtocolFactoryCtorParams;
63
Junxiao Shi2d491752017-07-14 21:32:05 +000064 /** \brief Register a protocol factory type
Davide Pesaventod27841b2018-11-13 00:22:24 -050065 * \tparam PF subclass of ProtocolFactory
Junxiao Shib47247d2017-01-24 15:09:16 +000066 * \param id factory identifier
67 */
68 template<typename PF>
69 static void
70 registerType(const std::string& id = PF::getId())
71 {
72 Registry& registry = getRegistry();
73 BOOST_ASSERT(registry.count(id) == 0);
Davide Pesaventod27841b2018-11-13 00:22:24 -050074 registry[id] = [] (const CtorParams& p) { return make_unique<PF>(p); };
Junxiao Shib47247d2017-01-24 15:09:16 +000075 }
76
Junxiao Shi2d491752017-07-14 21:32:05 +000077 /** \brief Create a protocol factory instance
Davide Pesaventod27841b2018-11-13 00:22:24 -050078 * \retval nullptr if a factory with the given \p id is not registered
Junxiao Shib47247d2017-01-24 15:09:16 +000079 */
80 static unique_ptr<ProtocolFactory>
Junxiao Shi0ba6d642017-07-17 00:53:22 +000081 create(const std::string& id, const CtorParams& params);
Junxiao Shib47247d2017-01-24 15:09:16 +000082
Davide Pesaventod27841b2018-11-13 00:22:24 -050083 /** \brief Get all registered protocol factory ids
Junxiao Shib47247d2017-01-24 15:09:16 +000084 */
85 static std::set<std::string>
86 listRegistered();
87
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080088public:
Junxiao Shi0ba6d642017-07-17 00:53:22 +000089 /** \brief Base class for all exceptions thrown by ProtocolFactory subclasses
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080090 */
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020091 class Error : public std::runtime_error
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080092 {
Davide Pesavento1d7e7af2015-10-10 23:54:08 +020093 public:
Davide Pesaventod27841b2018-11-13 00:22:24 -050094 using std::runtime_error::runtime_error;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080095 };
Alexander Afanasyevd6655302014-02-28 08:41:28 -080096
Davide Pesaventod27841b2018-11-13 00:22:24 -050097 explicit
98 ProtocolFactory(const CtorParams& params);
99
Junxiao Shib47247d2017-01-24 15:09:16 +0000100 virtual
Davide Pesaventod27841b2018-11-13 00:22:24 -0500101 ~ProtocolFactory() = 0;
Junxiao Shib47247d2017-01-24 15:09:16 +0000102
103#ifdef DOXYGEN
Davide Pesaventod27841b2018-11-13 00:22:24 -0500104 /** \brief Get id for this protocol factory
Junxiao Shib47247d2017-01-24 15:09:16 +0000105 *
106 * face_system.factory-id config section is processed by the protocol factory.
107 */
108 static const std::string&
Davide Pesaventod27841b2018-11-13 00:22:24 -0500109 getId() noexcept;
Junxiao Shib47247d2017-01-24 15:09:16 +0000110#endif
111
Davide Pesaventod27841b2018-11-13 00:22:24 -0500112 /** \brief Get FaceUri schemes accepted by this protocol factory
Junxiao Shi38b24c72017-01-05 02:59:31 +0000113 */
114 const std::set<std::string>&
Davide Pesaventod27841b2018-11-13 00:22:24 -0500115 getProvidedSchemes() const
Junxiao Shi38b24c72017-01-05 02:59:31 +0000116 {
117 return providedSchemes;
118 }
119
Davide Pesaventod27841b2018-11-13 00:22:24 -0500120 /** \brief Process face_system subsection that corresponds to this protocol factory id
121 * \param configSection the configuration section or boost::none to indicate it is omitted
122 * \param context provides access to data structures and contextual information
123 * \throw ConfigFile::Error invalid configuration
124 */
125 void
126 processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
127
Davide Pesavento15b55052018-01-27 19:09:28 -0500128 /** \brief Encapsulates a face creation request and all its parameters
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800129 *
Eric Newberry944f38b2017-07-20 20:54:22 -0400130 * Parameters are passed as a struct rather than individually, so that a future change in the list
131 * of parameters does not require an update to the method signature in all subclasses.
132 */
Davide Pesavento15b55052018-01-27 19:09:28 -0500133 struct CreateFaceRequest
Eric Newberry944f38b2017-07-20 20:54:22 -0400134 {
135 FaceUri remoteUri;
Davide Pesavento87fc0f82018-04-11 23:43:51 -0400136 optional<FaceUri> localUri;
Davide Pesavento15b55052018-01-27 19:09:28 -0500137 FaceParams params;
Eric Newberry944f38b2017-07-20 20:54:22 -0400138 };
139
Davide Pesaventod27841b2018-11-13 00:22:24 -0500140 /** \brief Create a unicast face
141 * \param req request object containing the face creation parameters
142 * \param onCreated callback if face creation succeeds or face already exists; the settings
143 * of an existing face are not updated if they differ from the request
144 * \param onFailure callback if face creation fails
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800145 */
Davide Pesaventod27841b2018-11-13 00:22:24 -0500146 void
Davide Pesavento15b55052018-01-27 19:09:28 -0500147 createFace(const CreateFaceRequest& req,
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800148 const FaceCreatedCallback& onCreated,
Davide Pesaventod27841b2018-11-13 00:22:24 -0500149 const FaceCreationFailedCallback& onFailure);
Junxiao Shi38b24c72017-01-05 02:59:31 +0000150
Junxiao Shieef49a92018-11-10 12:19:36 +0000151 /** \brief Create a netdev-bound face
152 * \param remote remote FaceUri, must be canonical
153 * \param netdev local network interface
154 * \return new face
155 * \throw Error cannot create a face using specified arguments
156 * \note The caller must ensure there is no existing netdev-bound face with same remote FaceUri
157 * on the same local network interface.
158 */
159 shared_ptr<Face>
160 createNetdevBoundFace(const FaceUri& remote,
161 const shared_ptr<const ndn::net::NetworkInterface>& netdev);
162
Davide Pesaventod27841b2018-11-13 00:22:24 -0500163 /** \brief Get list of open channels (listening + non-listening)
164 */
165 std::vector<shared_ptr<const Channel>>
166 getChannels() const;
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000167
Davide Pesaventod27841b2018-11-13 00:22:24 -0500168protected:
Junxiao Shi38b24c72017-01-05 02:59:31 +0000169 template<typename ChannelMap>
170 static std::vector<shared_ptr<const Channel>>
171 getChannelsFromMap(const ChannelMap& channelMap)
172 {
173 std::vector<shared_ptr<const Channel>> channels;
174 boost::copy(channelMap | boost::adaptors::map_values, std::back_inserter(channels));
175 return channels;
176 }
177
Junxiao Shieef49a92018-11-10 12:19:36 +0000178private:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500179 /** \brief Process face_system subsection that corresponds to this protocol factory id
180 * \sa processConfig
181 *
182 * A subclass should override this method if it supports configuration options in the config
183 * file, and do all the required processing here. The subclass should throw ConfigFile::Error
184 * if it encounters unrecognized options or invalid values. It should also update
185 * \p providedSchemes as needed.
186 *
187 * The base class implementation does nothing.
188 */
189 virtual void
190 doProcessConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
191
192 /** \brief Create a unicast face
193 * \sa createFace
194 *
195 * The base class implementation always invokes the failure callback with error code 406,
196 * indicating unicast face creation is not supported.
197 */
198 virtual void
199 doCreateFace(const CreateFaceRequest& req,
200 const FaceCreatedCallback& onCreated,
201 const FaceCreationFailedCallback& onFailure);
202
Junxiao Shieef49a92018-11-10 12:19:36 +0000203 /** \brief Create a netdev-bound face
204 * \sa createNetdevBoundFace
205 *
Davide Pesaventod27841b2018-11-13 00:22:24 -0500206 * The base class implementation always throws Error, indicating netdev-bound faces are not
Junxiao Shieef49a92018-11-10 12:19:36 +0000207 * supported.
208 *
209 * A subclass that offers netdev-bound faces should override this method, and also expose
210 * "scheme+dev" in providedSchemes. For example, UdpFactory should provide "udp4+dev" scheme,
211 * in addition to "udp4" scheme.
212 *
213 * The face should be constructed immediately. Face persistency shall be reported as PERMANENT.
214 * Face state shall remain DOWN until underlying transport is connected. The face shall remain
215 * open until after .close() is invoked, and survive all socket errors; in case the network
216 * interface disappears, the face shall remain DOWN until .close() is invoked.
217 */
218 virtual shared_ptr<Face>
219 doCreateNetdevBoundFace(const FaceUri& remote,
220 const shared_ptr<const ndn::net::NetworkInterface>& netif);
221
Davide Pesaventod27841b2018-11-13 00:22:24 -0500222 /** \brief Get list of open channels (listening + non-listening)
223 * \sa getChannels
224 *
225 * The base class implementation returns an empty list.
226 */
227 virtual std::vector<shared_ptr<const Channel>>
228 doGetChannels() const;
229
Junxiao Shib47247d2017-01-24 15:09:16 +0000230private: // registry
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000231 using CreateFunc = std::function<unique_ptr<ProtocolFactory>(const CtorParams&)>;
232 using Registry = std::map<std::string, CreateFunc>; // indexed by factory id
Junxiao Shib47247d2017-01-24 15:09:16 +0000233
234 static Registry&
235 getRegistry();
236
Junxiao Shi38b24c72017-01-05 02:59:31 +0000237protected:
Davide Pesaventod27841b2018-11-13 00:22:24 -0500238 std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this protocol factory
Junxiao Shi0ba6d642017-07-17 00:53:22 +0000239 FaceCreatedCallback addFace; ///< callback when a new face is created
240
Junxiao Shi2d491752017-07-14 21:32:05 +0000241 /** \brief NetworkMonitor for listing available network interfaces and monitoring their changes
242 *
243 * ProtocolFactory subclass should check the NetworkMonitor has sufficient capabilities prior
244 * to usage.
Junxiao Shi38b24c72017-01-05 02:59:31 +0000245 */
Junxiao Shi2d491752017-07-14 21:32:05 +0000246 shared_ptr<ndn::net::NetworkMonitor> netmon;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800247};
248
Junxiao Shi38b24c72017-01-05 02:59:31 +0000249} // namespace face
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800250} // namespace nfd
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