blob: b45911d895c698e36d456afacfd963422b6d1eb9 [file] [log] [blame]
Jeff Thompson25b4e612013-10-10 16:03:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -07002/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07003 * Copyright (C) 2013 Regents of the University of California.
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -07004 * See COPYING for copyright and distribution information.
5 */
6
Jeff Thompsonb9e3c8e2013-08-02 11:42:51 -07007#ifndef NDN_FACE_HPP
Jeff Thompsona0d18c92013-08-06 13:55:32 -07008#define NDN_FACE_HPP
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -07009
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080010#include "common.hpp"
11#include "interest.hpp"
12#include "data.hpp"
13
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080014#include "transport/transport.hpp"
15#include "transport/unix-transport.hpp"
Alexander Afanasyev20d2c582014-01-26 15:32:51 -080016#include "transport/tcp-transport.hpp"
Jeff Thompsonbeb8b7d2013-07-16 15:49:21 -070017
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080018#include "management/controller.hpp"
19
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070020#include "util/scheduler.hpp"
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080021#include "detail/registered-prefix.hpp"
22#include "detail/pending-interest.hpp"
23
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070024namespace ndn {
25
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080026struct PendingInterestId;
27struct RegisteredPrefixId;
28
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070029/**
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080030 * An OnData function object is used to pass a callback to expressInterest.
31 */
32typedef function<void(const Interest&, Data&)> OnData;
33
34/**
35 * An OnTimeout function object is used to pass a callback to expressInterest.
36 */
37typedef function<void(const Interest&)> OnTimeout;
38
39/**
40 * An OnInterest function object is used to pass a callback to registerPrefix.
41 */
42typedef function<void (const Name&, const Interest&)> OnInterest;
43
44/**
45 * An OnRegisterFailed function object is used to report when registerPrefix fails.
46 */
47typedef function<void(const Name&, const std::string&)> OnSetInterestFilterFailed;
48
49
50
51/**
52 * @brief Abstraction to communicate with local or remote NDN forwarder
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070053 */
Alexander Afanasyev8460afb2014-02-15 20:31:42 -080054class Face : noncopyable
55{
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070056public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057 class Error : public std::runtime_error
58 {
59 public:
60 explicit
61 Error(const std::string& what)
62 : std::runtime_error(what)
63 {
64 }
65 };
Alexander Afanasyevb790d952014-01-24 12:07:53 -080066
67 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070068 * @brief Create a new Face using the default transport (UnixTransport)
69 *
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060070 * @throws ConfigFile::Error on configuration file parse failure
71 * @throws Face::Error on unsupported protocol
Alexander Afanasyevb790d952014-01-24 12:07:53 -080072 */
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080073 Face();
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080074
75 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070076 * @brief Create a new Face using the default transport (UnixTransport)
77 *
78 * @deprecated This constructor is deprecated. Use `Face(boost::asio::io_service&)`
79 * instead.
80 *
81 * @param ioService A shared pointer to boost::io_service object that should control all
82 * IO operations
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060083 * @throws ConfigFile::Error on configuration file parse failure
84 * @throws Face::Error on unsupported protocol
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070085 */
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080086 explicit
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080087 Face(const shared_ptr<boost::asio::io_service>& ioService);
88
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070089 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070090 * @brief Create a new Face using the default transport (UnixTransport)
91 *
92 * @par Usage examples:
93 *
94 * Face face1;
95 * Face face2(face1.getIoService());
96 *
97 * // Now the following ensures that events on both faces are processed
98 * face1.processEvents();
99 * // or face1.getIoService().run();
100 *
101 * @par or
102 *
103 * boost::asio::io_service ioService;
104 * Face face1(ioService);
105 * Face face2(ioService);
106 * ...
107 *
108 * ioService.run();
109 *
110 * @param ioService A reference to boost::io_service object that should control all
111 * IO operations.
112 * @throws ConfigFile::Error on configuration file parse failure
113 * @throws Face::Error on unsupported protocol
114 */
115 explicit
116 Face(boost::asio::io_service& ioService);
117
118 /**
119 * @brief Create a new Face using TcpTransport
120 *
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -0700121 * @param host The host of the NDN hub.
Alexander Afanasyev20d2c582014-01-26 15:32:51 -0800122 * @param port The port or service name of the NDN hub. If omitted. use 6363.
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600123 * @throws Face::Error on unsupported protocol
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -0700124 */
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800125 Face(const std::string& host, const std::string& port = "6363");
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800126
127 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700128 * @brief Create a new Face using the given Transport
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800129 * @param transport A shared_ptr to a Transport object used for communication.
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600130 * @throws Face::Error on unsupported protocol
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800131 */
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -0800132 explicit
133 Face(const shared_ptr<Transport>& transport);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800134
135 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700136 * @brief Create a new Face using the given Transport and IO service object
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800137 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700138 * @sa Face(boost::asio::io_service&)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800139 *
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600140 * @throws Face::Error on unsupported protocol
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800141 */
142 Face(const shared_ptr<Transport>& transport,
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700143 boost::asio::io_service& ioService);
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800144
145 /**
Alexander Afanasyev505646e2014-02-24 20:13:37 -0800146 * @brief Set controller used for prefix registration
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800147 */
Alexander Afanasyev505646e2014-02-24 20:13:37 -0800148 void
149 setController(const shared_ptr<Controller>& controller);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700150
Jeff Thompson4fe45512013-08-23 14:06:38 -0700151 /**
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800152 * @brief Express Interest
153 *
154 * @param interest A reference to the Interest. This copies the Interest.
155 * @param onData A function object to call when a matching data packet is received.
156 * @param onTimeout A function object to call if the interest times out.
157 * If onTimeout is an empty OnTimeout(), this does not use it.
158 *
Jeff Thompson11095142013-10-01 16:20:28 -0700159 * @return The pending interest ID which can be used with removePendingInterest.
Jeff Thompson4fe45512013-08-23 14:06:38 -0700160 */
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800161 const PendingInterestId*
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800162 expressInterest(const Interest& interest,
163 const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
Jeff Thompson4fe45512013-08-23 14:06:38 -0700164
165 /**
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800166 * @brief Express Interest using name and Interest template
167 *
168 * @param name Name of the Interest
169 * @param tmpl Interest template to fill parameters
170 * @param onData A callback to call when a matching data packet is received.
171 * @param onTimeout A callback to call if the interest times out.
172 * If onTimeout is an empty OnTimeout(), this does not use it.
173 *
Jeff Thompson11095142013-10-01 16:20:28 -0700174 * @return The pending interest ID which can be used with removePendingInterest.
Jeff Thompson7aec0252013-08-22 17:29:57 -0700175 */
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800176 const PendingInterestId*
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800177 expressInterest(const Name& name,
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800178 const Interest& tmpl,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800179 const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700180
Jeff Thompson11095142013-10-01 16:20:28 -0700181 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700182 * @brief Remove the pending interest entry with the pendingInterestId from the pending
183 * interest table.
184 *
185 * This does not affect another pending interest with a different pendingInterestId,
186 * even it if has the same interest name. If there is no entry with the
187 * pendingInterestId, do nothing.
188 *
Jeff Thompson11095142013-10-01 16:20:28 -0700189 * @param pendingInterestId The ID returned from expressInterest.
190 */
191 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800192 removePendingInterest(const PendingInterestId* pendingInterestId);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700193
Jeff Thompson432c8be2013-08-09 16:16:08 -0700194 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700195 * @brief Register prefix with the connected NDN hub and call onInterest when a matching
196 * interest is received.
197 *
198 * @param prefix A reference to a Name for the prefix to register
199 * @param onInterest A function object to call when a matching interest is received
200 *
201 * @param onRegisterFailed A function object to call if failed to retrieve the connected
202 * hub’s ID or failed to register the prefix. This calls
203 * onRegisterFailed(prefix) where prefix is the prefix given to
204 * registerPrefix.
205 *
206 * @param flags The flags for finer control of which interests are forward to the
207 * application.
Jeff Thompson11095142013-10-01 16:20:28 -0700208 * @return The registered prefix ID which can be used with removeRegisteredPrefix.
Jeff Thompson86507bc2013-08-23 20:51:38 -0700209 */
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800210 const RegisteredPrefixId*
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800211 setInterestFilter(const Name& prefix,
212 const OnInterest& onInterest,
213 const OnSetInterestFilterFailed& onSetInterestFilterFailed);
Jeff Thompson11095142013-10-01 16:20:28 -0700214
215 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700216 * @brief Remove the registered prefix entry with the registeredPrefixId from the
217 * pending interest table.
218 *
219 * This does not affect another registered prefix with a different registeredPrefixId,
220 * even it if has the same prefix name. If there is no entry with the
221 * registeredPrefixId, do nothing.
222 *
Jeff Thompson11095142013-10-01 16:20:28 -0700223 * @param registeredPrefixId The ID returned from registerPrefix.
224 */
225 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800226 unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId);
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800227
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800228 /**
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800229 * @brief Publish data packet
230 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700231 * This method can be called to satisfy the incoming Interest or to put Data packet into
232 * the cache of the local NDN forwarder
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800233 */
234 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800235 put(const Data& data);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700236
Jeff Thompson86507bc2013-08-23 20:51:38 -0700237 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700238 * @brief Process any data to receive or call timeout callbacks.
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800239 *
240 * This call will block forever (default timeout == 0) to process IO on the face.
241 * To exit, one expected to call face.shutdown() from one of the callback methods.
242 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700243 * If positive timeout is specified, then processEvents will exit after this timeout, if
244 * not stopped earlier with face.shutdown() or when all active events finish. The call
245 * can be called repeatedly, if desired.
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800246 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700247 * If negative timeout is specified, then processEvents will not block and process only
248 * pending events.
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800249 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700250 * @param timeout maximum time to block the thread.
251 * @param keepThread Keep thread in a blocked state (in event processing), even when
252 * there are no outstanding events (e.g., no Interest/Data is expected)
253 *
254 * @throw This may throw an exception for reading data or in the callback for processing
255 * the data. If you call this from an main event loop, you may want to catch and
256 * log/disregard all exceptions.
Jeff Thompson432c8be2013-08-09 16:16:08 -0700257 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700258 void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700259 processEvents(const time::milliseconds& timeout = time::milliseconds::zero(),
260 bool keepThread = false);
Jeff Thompson432c8be2013-08-09 16:16:08 -0700261
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700262 /**
263 * @brief Shutdown face operations
264 *
265 * This method cancels all pending operations and closes connection to NDN Forwarder.
266 *
267 * Note that this method does not stop IO service and if the same IO service is shared
268 * between multiple Faces or with other IO objects (e.g., Scheduler).
269 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700270 void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700271 shutdown();
Yingdi Yu0d920812014-01-30 14:50:57 -0800272
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700273 /**
274 * @brief Get shared_ptr of the IO service object
275 *
276 * @deprecated Use getIoService instead
277 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700278 shared_ptr<boost::asio::io_service>
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700279 ioService()
280 {
281 return m_ioService;
282 }
283
284 /**
285 * @brief Get reference to IO service object
286 */
287 boost::asio::io_service&
288 getIoService()
289 {
290 return *m_ioService;
291 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800292
293private:
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600294
295 /**
296 * @throws Face::Error on unsupported protocol
297 */
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800298 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800299 construct(const shared_ptr<Transport>& transport,
Alexander Afanasyev505646e2014-02-24 20:13:37 -0800300 const shared_ptr<boost::asio::io_service>& ioService);
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600301
302 bool
303 isSupportedNfdProtocol(const std::string& protocol);
304
305 bool
306 isSupportedNrdProtocol(const std::string& protocol);
307
308 bool
309 isSupportedNdndProtocol(const std::string& protocol);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700310
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700311 class ProcessEventsTimeout
312 {
313 };
314
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800315 typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
316 typedef std::list<shared_ptr<RegisteredPrefix> > RegisteredPrefixTable;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700317
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800318 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800319 asyncExpressInterest(const shared_ptr<const Interest>& interest,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800320 const OnData& onData, const OnTimeout& onTimeout);
321
322 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800323 asyncRemovePendingInterest(const PendingInterestId* pendingInterestId);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800324
325 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800326 asyncUnsetInterestFilter(const RegisteredPrefixId* registeredPrefixId);
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800327
328 void
Alexander Afanasyev52afb3f2014-03-07 09:05:35 +0000329 finalizeUnsetInterestFilter(RegisteredPrefixTable::iterator item);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700330
331 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800332 onReceiveElement(const Block& wire);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800333
Alexander Afanasyev7dced462014-03-19 15:12:32 -0700334 void
335 asyncShutdown();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700336
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800337 static void
338 fireProcessEventsTimeout(const boost::system::error_code& error);
339
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800340 void
341 satisfyPendingInterests(Data& data);
342
343 void
344 processInterestFilters(Interest& interest);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700345
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800346 void
347 checkPitExpire();
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800348
Jeff Thompsonb982b6d2013-07-15 18:15:45 -0700349private:
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800350 shared_ptr<boost::asio::io_service> m_ioService;
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700351 shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700352 shared_ptr<monotonic_deadline_timer> m_pitTimeoutCheckTimer;
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800353 bool m_pitTimeoutCheckTimerActive;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700354 shared_ptr<monotonic_deadline_timer> m_processEventsTimeoutTimer;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700355
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800356 shared_ptr<Transport> m_transport;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800357
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800358 PendingInterestTable m_pendingInterestTable;
359 RegisteredPrefixTable m_registeredPrefixTable;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800360
361 shared_ptr<Controller> m_fwController;
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600362
363 ConfigFile m_config;
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700364};
365
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600366inline bool
367Face::isSupportedNfdProtocol(const std::string& protocol)
368{
369 return protocol == "nfd-0.1";
370}
371
372inline bool
373Face::isSupportedNrdProtocol(const std::string& protocol)
374{
375 return protocol == "nrd-0.1";
376}
377
378inline bool
379Face::isSupportedNdndProtocol(const std::string& protocol)
380{
381 return protocol == "ndnd-tlv-0.7";
382}
383
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800384} // namespace ndn
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700385
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800386#endif // NDN_FACE_HPP