blob: 185927ba6aeaf811ec5b7ae7f4cf3ae13b2814f0 [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/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * Based on code originally written by Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070013 */
14
Jeff Thompsonb9e3c8e2013-08-02 11:42:51 -070015#ifndef NDN_FACE_HPP
Jeff Thompsona0d18c92013-08-06 13:55:32 -070016#define NDN_FACE_HPP
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070017
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080018#include "common.hpp"
19#include "interest.hpp"
20#include "data.hpp"
21
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080022#include "transport/transport.hpp"
23#include "transport/unix-transport.hpp"
Alexander Afanasyev20d2c582014-01-26 15:32:51 -080024#include "transport/tcp-transport.hpp"
Jeff Thompsonbeb8b7d2013-07-16 15:49:21 -070025
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080026#include "management/controller.hpp"
27
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070028#include "util/scheduler.hpp"
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080029#include "detail/registered-prefix.hpp"
30#include "detail/pending-interest.hpp"
31
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070032namespace ndn {
33
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080034struct PendingInterestId;
35struct RegisteredPrefixId;
36
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070037/**
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080038 * An OnData function object is used to pass a callback to expressInterest.
39 */
40typedef function<void(const Interest&, Data&)> OnData;
41
42/**
43 * An OnTimeout function object is used to pass a callback to expressInterest.
44 */
45typedef function<void(const Interest&)> OnTimeout;
46
47/**
48 * An OnInterest function object is used to pass a callback to registerPrefix.
49 */
50typedef function<void (const Name&, const Interest&)> OnInterest;
51
52/**
53 * An OnRegisterFailed function object is used to report when registerPrefix fails.
54 */
55typedef function<void(const Name&, const std::string&)> OnSetInterestFilterFailed;
56
57
58
59/**
60 * @brief Abstraction to communicate with local or remote NDN forwarder
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070061 */
Alexander Afanasyev8460afb2014-02-15 20:31:42 -080062class Face : noncopyable
63{
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070064public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070065 class Error : public std::runtime_error
66 {
67 public:
68 explicit
69 Error(const std::string& what)
70 : std::runtime_error(what)
71 {
72 }
73 };
Alexander Afanasyevb790d952014-01-24 12:07:53 -080074
75 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070076 * @brief Create a new Face using the default transport (UnixTransport)
77 *
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060078 * @throws ConfigFile::Error on configuration file parse failure
79 * @throws Face::Error on unsupported protocol
Alexander Afanasyevb790d952014-01-24 12:07:53 -080080 */
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080081 Face();
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080082
83 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070084 * @brief Create a new Face using the default transport (UnixTransport)
85 *
86 * @deprecated This constructor is deprecated. Use `Face(boost::asio::io_service&)`
87 * instead.
88 *
89 * @param ioService A shared pointer to boost::io_service object that should control all
90 * IO operations
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060091 * @throws ConfigFile::Error on configuration file parse failure
92 * @throws Face::Error on unsupported protocol
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070093 */
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080094 explicit
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080095 Face(const shared_ptr<boost::asio::io_service>& ioService);
96
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -070097 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070098 * @brief Create a new Face using the default transport (UnixTransport)
99 *
100 * @par Usage examples:
101 *
102 * Face face1;
103 * Face face2(face1.getIoService());
104 *
105 * // Now the following ensures that events on both faces are processed
106 * face1.processEvents();
107 * // or face1.getIoService().run();
108 *
109 * @par or
110 *
111 * boost::asio::io_service ioService;
112 * Face face1(ioService);
113 * Face face2(ioService);
114 * ...
115 *
116 * ioService.run();
117 *
118 * @param ioService A reference to boost::io_service object that should control all
119 * IO operations.
120 * @throws ConfigFile::Error on configuration file parse failure
121 * @throws Face::Error on unsupported protocol
122 */
123 explicit
124 Face(boost::asio::io_service& ioService);
125
126 /**
127 * @brief Create a new Face using TcpTransport
128 *
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -0700129 * @param host The host of the NDN hub.
Alexander Afanasyev20d2c582014-01-26 15:32:51 -0800130 * @param port The port or service name of the NDN hub. If omitted. use 6363.
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600131 * @throws Face::Error on unsupported protocol
Jeff Thompsonfe08e5a2013-08-13 11:15:59 -0700132 */
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800133 Face(const std::string& host, const std::string& port = "6363");
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
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800137 * @param transport A shared_ptr to a Transport object used for communication.
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600138 * @throws Face::Error on unsupported protocol
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800139 */
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -0800140 explicit
141 Face(const shared_ptr<Transport>& transport);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800142
143 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700144 * @brief Create a new Face using the given Transport and IO service object
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800145 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700146 * @sa Face(boost::asio::io_service&)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800147 *
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600148 * @throws Face::Error on unsupported protocol
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800149 */
150 Face(const shared_ptr<Transport>& transport,
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700151 boost::asio::io_service& ioService);
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800152
153 /**
Alexander Afanasyev505646e2014-02-24 20:13:37 -0800154 * @brief Set controller used for prefix registration
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800155 */
Alexander Afanasyev505646e2014-02-24 20:13:37 -0800156 void
157 setController(const shared_ptr<Controller>& controller);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700158
Jeff Thompson4fe45512013-08-23 14:06:38 -0700159 /**
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800160 * @brief Express Interest
161 *
162 * @param interest A reference to the Interest. This copies the Interest.
163 * @param onData A function object to call when a matching data packet is received.
164 * @param onTimeout A function object to call if the interest times out.
165 * If onTimeout is an empty OnTimeout(), this does not use it.
166 *
Jeff Thompson11095142013-10-01 16:20:28 -0700167 * @return The pending interest ID which can be used with removePendingInterest.
Jeff Thompson4fe45512013-08-23 14:06:38 -0700168 */
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800169 const PendingInterestId*
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800170 expressInterest(const Interest& interest,
171 const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
Jeff Thompson4fe45512013-08-23 14:06:38 -0700172
173 /**
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800174 * @brief Express Interest using name and Interest template
175 *
176 * @param name Name of the Interest
177 * @param tmpl Interest template to fill parameters
178 * @param onData A callback to call when a matching data packet is received.
179 * @param onTimeout A callback to call if the interest times out.
180 * If onTimeout is an empty OnTimeout(), this does not use it.
181 *
Jeff Thompson11095142013-10-01 16:20:28 -0700182 * @return The pending interest ID which can be used with removePendingInterest.
Jeff Thompson7aec0252013-08-22 17:29:57 -0700183 */
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800184 const PendingInterestId*
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800185 expressInterest(const Name& name,
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800186 const Interest& tmpl,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800187 const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700188
Jeff Thompson11095142013-10-01 16:20:28 -0700189 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700190 * @brief Remove the pending interest entry with the pendingInterestId from the pending
191 * interest table.
192 *
193 * This does not affect another pending interest with a different pendingInterestId,
194 * even it if has the same interest name. If there is no entry with the
195 * pendingInterestId, do nothing.
196 *
Jeff Thompson11095142013-10-01 16:20:28 -0700197 * @param pendingInterestId The ID returned from expressInterest.
198 */
199 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800200 removePendingInterest(const PendingInterestId* pendingInterestId);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700201
Jeff Thompson432c8be2013-08-09 16:16:08 -0700202 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700203 * @brief Register prefix with the connected NDN hub and call onInterest when a matching
204 * interest is received.
205 *
206 * @param prefix A reference to a Name for the prefix to register
207 * @param onInterest A function object to call when a matching interest is received
208 *
209 * @param onRegisterFailed A function object to call if failed to retrieve the connected
210 * hub’s ID or failed to register the prefix. This calls
211 * onRegisterFailed(prefix) where prefix is the prefix given to
212 * registerPrefix.
213 *
214 * @param flags The flags for finer control of which interests are forward to the
215 * application.
Jeff Thompson11095142013-10-01 16:20:28 -0700216 * @return The registered prefix ID which can be used with removeRegisteredPrefix.
Jeff Thompson86507bc2013-08-23 20:51:38 -0700217 */
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800218 const RegisteredPrefixId*
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800219 setInterestFilter(const Name& prefix,
220 const OnInterest& onInterest,
221 const OnSetInterestFilterFailed& onSetInterestFilterFailed);
Jeff Thompson11095142013-10-01 16:20:28 -0700222
223 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700224 * @brief Remove the registered prefix entry with the registeredPrefixId from the
225 * pending interest table.
226 *
227 * This does not affect another registered prefix with a different registeredPrefixId,
228 * even it if has the same prefix name. If there is no entry with the
229 * registeredPrefixId, do nothing.
230 *
Jeff Thompson11095142013-10-01 16:20:28 -0700231 * @param registeredPrefixId The ID returned from registerPrefix.
232 */
233 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800234 unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId);
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800235
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800236 /**
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800237 * @brief Publish data packet
238 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700239 * This method can be called to satisfy the incoming Interest or to put Data packet into
240 * the cache of the local NDN forwarder
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800241 */
242 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800243 put(const Data& data);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700244
Jeff Thompson86507bc2013-08-23 20:51:38 -0700245 /**
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700246 * @brief Process any data to receive or call timeout callbacks.
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800247 *
248 * This call will block forever (default timeout == 0) to process IO on the face.
249 * To exit, one expected to call face.shutdown() from one of the callback methods.
250 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700251 * If positive timeout is specified, then processEvents will exit after this timeout, if
252 * not stopped earlier with face.shutdown() or when all active events finish. The call
253 * can be called repeatedly, if desired.
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800254 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700255 * If negative timeout is specified, then processEvents will not block and process only
256 * pending events.
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800257 *
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700258 * @param timeout maximum time to block the thread.
259 * @param keepThread Keep thread in a blocked state (in event processing), even when
260 * there are no outstanding events (e.g., no Interest/Data is expected)
261 *
262 * @throw This may throw an exception for reading data or in the callback for processing
263 * the data. If you call this from an main event loop, you may want to catch and
264 * log/disregard all exceptions.
Jeff Thompson432c8be2013-08-09 16:16:08 -0700265 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700266 void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700267 processEvents(const time::milliseconds& timeout = time::milliseconds::zero(),
268 bool keepThread = false);
Jeff Thompson432c8be2013-08-09 16:16:08 -0700269
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700270 /**
271 * @brief Shutdown face operations
272 *
273 * This method cancels all pending operations and closes connection to NDN Forwarder.
274 *
275 * Note that this method does not stop IO service and if the same IO service is shared
276 * between multiple Faces or with other IO objects (e.g., Scheduler).
277 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700278 void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700279 shutdown();
Yingdi Yu0d920812014-01-30 14:50:57 -0800280
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700281 /**
282 * @brief Get shared_ptr of the IO service object
283 *
284 * @deprecated Use getIoService instead
285 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700286 shared_ptr<boost::asio::io_service>
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700287 ioService()
288 {
289 return m_ioService;
290 }
291
292 /**
293 * @brief Get reference to IO service object
294 */
295 boost::asio::io_service&
296 getIoService()
297 {
298 return *m_ioService;
299 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800300
301private:
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600302
303 /**
304 * @throws Face::Error on unsupported protocol
305 */
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800306 void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800307 construct(const shared_ptr<Transport>& transport,
Alexander Afanasyev505646e2014-02-24 20:13:37 -0800308 const shared_ptr<boost::asio::io_service>& ioService);
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600309
310 bool
311 isSupportedNfdProtocol(const std::string& protocol);
312
313 bool
314 isSupportedNrdProtocol(const std::string& protocol);
315
316 bool
317 isSupportedNdndProtocol(const std::string& protocol);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700318
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700319 class ProcessEventsTimeout
320 {
321 };
322
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800323 typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
324 typedef std::list<shared_ptr<RegisteredPrefix> > RegisteredPrefixTable;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700325
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800326 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800327 asyncExpressInterest(const shared_ptr<const Interest>& interest,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800328 const OnData& onData, const OnTimeout& onTimeout);
329
330 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800331 asyncRemovePendingInterest(const PendingInterestId* pendingInterestId);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800332
333 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800334 asyncUnsetInterestFilter(const RegisteredPrefixId* registeredPrefixId);
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800335
336 void
Alexander Afanasyev52afb3f2014-03-07 09:05:35 +0000337 finalizeUnsetInterestFilter(RegisteredPrefixTable::iterator item);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700338
339 void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800340 onReceiveElement(const Block& wire);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800341
Alexander Afanasyev7dced462014-03-19 15:12:32 -0700342 void
343 asyncShutdown();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700344
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800345 static void
346 fireProcessEventsTimeout(const boost::system::error_code& error);
347
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800348 void
349 satisfyPendingInterests(Data& data);
350
351 void
352 processInterestFilters(Interest& interest);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700353
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800354 void
355 checkPitExpire();
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800356
Jeff Thompsonb982b6d2013-07-15 18:15:45 -0700357private:
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800358 shared_ptr<boost::asio::io_service> m_ioService;
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700359 shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700360 shared_ptr<monotonic_deadline_timer> m_pitTimeoutCheckTimer;
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800361 bool m_pitTimeoutCheckTimerActive;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700362 shared_ptr<monotonic_deadline_timer> m_processEventsTimeoutTimer;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700363
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800364 shared_ptr<Transport> m_transport;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800365
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800366 PendingInterestTable m_pendingInterestTable;
367 RegisteredPrefixTable m_registeredPrefixTable;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800368
369 shared_ptr<Controller> m_fwController;
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600370
371 ConfigFile m_config;
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700372};
373
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600374inline bool
375Face::isSupportedNfdProtocol(const std::string& protocol)
376{
377 return protocol == "nfd-0.1";
378}
379
380inline bool
381Face::isSupportedNrdProtocol(const std::string& protocol)
382{
383 return protocol == "nrd-0.1";
384}
385
386inline bool
387Face::isSupportedNdndProtocol(const std::string& protocol)
388{
389 return protocol == "ndnd-tlv-0.7";
390}
391
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800392} // namespace ndn
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700393
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800394#endif // NDN_FACE_HPP