node: Small complication to allow (in future) aggregation of Face processing threads

Change-Id: Ia318d4cee7da7ed1e0f069409e86f3e12f62b816
diff --git a/include/ndn-cpp/node.hpp b/include/ndn-cpp/node.hpp
index 4092330..b785be4 100644
--- a/include/ndn-cpp/node.hpp
+++ b/include/ndn-cpp/node.hpp
@@ -50,6 +50,20 @@
    * @param transport A shared_ptr to a Transport::ConnectionInfo to be used to connect to the transport.
    */
   Node(const ptr_lib::shared_ptr<Transport>& transport);
+
+  /**
+   * @brief Alternative (special use case) version of the constructor, can be used to aggregate
+   *        several Faces within one processing thread
+   *
+   * <code>
+   *     Face face1(...);
+   *     Face face2(..., face1.getAsyncService());
+   *
+   *     // Now the following ensures that events on both faces are processed
+   *     face1.processEvents();
+   * </code>
+   */
+  Node(const ptr_lib::shared_ptr<Transport>& transport, const ptr_lib::shared_ptr<boost::asio::io_service> &ioService);
   
   /**
    * Send the Interest through the transport, read the entire response and call onData(interest, data).
@@ -131,11 +145,7 @@
   void 
   onReceiveElement(const Block &wire);
 
-  void
-  onTransportError();
-
-  struct ProcessEventsTimeout {};
-  
+  struct ProcessEventsTimeout {};  
   static void
   fireProcessEventsTimeout(const boost::system::error_code& error);
 
@@ -305,9 +315,9 @@
   checkPitExpire();
   
 private:
-  boost::asio::io_service ioService_;
-  boost::asio::deadline_timer timer_;
-  boost::asio::deadline_timer processEventsTimeoutTimer_;
+  ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
+  ptr_lib::shared_ptr<boost::asio::deadline_timer> pitTimeoutCheckTimer_;
+  ptr_lib::shared_ptr<boost::asio::deadline_timer> processEventsTimeoutTimer_;
   
   ptr_lib::shared_ptr<Transport> transport_;
 
diff --git a/src/node.cpp b/src/node.cpp
index 5449a88..910685b 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -24,21 +24,34 @@
 uint64_t Node::RegisteredPrefix::lastRegisteredPrefixId_ = 0;
 
 Node::Node(const ptr_lib::shared_ptr<Transport>& transport)
-  : timer_ (ioService_)
-  , processEventsTimeoutTimer_(ioService_)
+  : transport_(transport)
+  , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
+{
+  ioService_ = ptr_lib::make_shared<boost::asio::io_service>();      
+  pitTimeoutCheckTimer_      = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
+  processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
+  
+  pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
+  pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
+}
+
+Node::Node(const ptr_lib::shared_ptr<Transport>& transport, const ptr_lib::shared_ptr<boost::asio::io_service> &ioService)
+  : ioService_(ioService)
   , transport_(transport)
   , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
 {
-  timer_.expires_from_now(boost::posix_time::milliseconds(100));
-  timer_.async_wait(func_lib::bind(&Node::checkPitExpire, this));
+  pitTimeoutCheckTimer_      = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
+  processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
+  
+  pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
+  pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
 }
 
 uint64_t 
 Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
 {
-  // TODO: Properly check if we are already connected to the expected host.
   if (!transport_->isConnected())
-    transport_->connect(ioService_,
+    transport_->connect(*ioService_,
                         ptr_lib::bind(&Node::onReceiveElement, this, _1));
   
   uint64_t pendingInterestId = PendingInterest::getNextPendingInterestId();
@@ -53,9 +66,8 @@
 void
 Node::put(const Data &data)
 {
-  // TODO: Properly check if we are already connected to the expected host.
   if (!transport_->isConnected())
-    transport_->connect(ioService_,
+    transport_->connect(*ioService_,
                         ptr_lib::bind(&Node::onReceiveElement, this, _1));
 
   transport_->send(data.wireEncode());
@@ -209,13 +221,13 @@
 {
   if (timeout > 0)
     {
-      processEventsTimeoutTimer_.expires_from_now(boost::posix_time::milliseconds(timeout));
-      processEventsTimeoutTimer_.async_wait(fireProcessEventsTimeout);
+      processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
+      processEventsTimeoutTimer_->async_wait(fireProcessEventsTimeout);
     }
   try
     {
-      ioService_.run();
-      ioService_.reset();
+      ioService_->run();
+      ioService_->reset();
     }
   catch(Node::ProcessEventsTimeout &)
     {
@@ -247,8 +259,8 @@
     }
   }
 
-  timer_.expires_from_now(boost::posix_time::milliseconds(100));
-  timer_.async_wait(func_lib::bind(&Node::checkPitExpire, this));
+  pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
+  pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
 }
 
 
@@ -281,20 +293,11 @@
     }
 }
 
-void
-Node::onTransportError()
-{
-  /// @todo Set some error code
-  
-  ioService_.stop();
-  throw Error("TransportError");
-}
-
 void 
 Node::shutdown()
 {
   transport_->close();
-  ioService_.stop();
+  ioService_->stop();
 }
 
 Node::PendingInterestTable::iterator