node+transport: Fixing bug that prevented reconnection to the forwarder after being disconnected for some reason

tools/ndnputcatchunks shows an example how to design a daemon
application that is resilient to the local daemon shutdowns/restarts.

Note that when local forwarder disconnects, all pending interests and
registered prefixes will get flushed.

Change-Id: I2933e2b5d6fd8420de4f055e53c748dbd00cabe9
diff --git a/src/node.cpp b/src/node.cpp
index 6641bbc..26a3b07 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -274,12 +274,20 @@
       }
           
       ioService_->run();
+      ioService_->reset(); // so it is possible to run processEvents again (if necessary)
     }
   catch(Node::ProcessEventsTimeout &)
     {
       // break
       ioService_->reset();
     }
+  catch(const std::exception &)
+    {
+      ioService_->reset();
+      pendingInterestTable_.clear();
+      registeredPrefixTable_.clear();
+      throw;
+    }
 }
 
 void
@@ -364,13 +372,13 @@
 void 
 Node::shutdown()
 {
+  pendingInterestTable_.clear();
+  registeredPrefixTable_.clear();
+
   transport_->close();
   pitTimeoutCheckTimer_->cancel();
   processEventsTimeoutTimer_->cancel();
   pitTimeoutCheckTimerActive_ = false;
-  
-  // This will ensure that io_service::work will stop
-  ioServiceWork_.reset();
 }
 
 Node::PendingInterestTable::iterator 
diff --git a/src/transport/unix-transport.cpp b/src/transport/unix-transport.cpp
index 5aca79e..cd00a46 100644
--- a/src/transport/unix-transport.cpp
+++ b/src/transport/unix-transport.cpp
@@ -61,6 +61,7 @@
       {
         // may need to throw exception
         transport_.isConnected_ = false;
+        transport_.close();
         throw Transport::Error(error, "error while connecting to the forwarder");
       }
   }
@@ -82,14 +83,15 @@
   {
     if (!connectionInProgress_) {
       connectionInProgress_ = true;
-      socket_.open();
-      socket_.async_connect(protocol::endpoint(transport_.unixSocket_),
-                            func_lib::bind(&Impl::connectHandler, this, _1));
 
       // Wait at most 4 seconds to connect
       /// @todo Decide whether this number should be configurable
       connectTimer_.expires_from_now(boost::posix_time::seconds(4));
       connectTimer_.async_wait(func_lib::bind(&Impl::connectTimeoutHandler, this, _1));
+      
+      socket_.open();
+      socket_.async_connect(protocol::endpoint(transport_.unixSocket_),
+                            func_lib::bind(&Impl::connectHandler, this, _1));
     }
   }
 
diff --git a/tools/ndnputchunks.cpp b/tools/ndnputchunks.cpp
index 68755a9..a1d581b 100644
--- a/tools/ndnputchunks.cpp
+++ b/tools/ndnputchunks.cpp
@@ -121,7 +121,19 @@
       std::cerr << "Preparing the input..." << std::endl;
       Producer producer (argv[1]);
       std::cerr << "Ready... (took " << ((ndn::getNow() - time)/1000) << " seconds)" << std::endl;
-      producer.run ();
+      while(true)
+        {
+          try
+            {
+              producer.run (); // this will exit when daemon dies... so try to connect again if possible
+            }
+          catch (std::exception& e)
+            {
+              std::cerr << "ERROR: " << e.what () << std::endl;
+              // and keep going
+              sleep (1);
+            }
+        }
     }
   catch (std::exception& e)
     {