face: don't set TransportState to FAILED if connection is closed cleanly

Change-Id: I0989cdf49558574f30b55a172d467b39683f9bb6
Refs: #4099
diff --git a/daemon/face/stream-transport.hpp b/daemon/face/stream-transport.hpp
index cba7c78..2a57d68 100644
--- a/daemon/face/stream-transport.hpp
+++ b/daemon/face/stream-transport.hpp
@@ -276,10 +276,13 @@
 void
 StreamTransport<T>::handleError(const boost::system::error_code& error)
 {
-  if (error != boost::asio::error::eof)
+  if (error == boost::asio::error::eof) {
+    this->setState(TransportState::CLOSING);
+  }
+  else {
     NFD_LOG_FACE_ERROR("Send or receive operation failed: " << error.message());
-
-  this->setState(TransportState::FAILED);
+    this->setState(TransportState::FAILED);
+  }
   doClose();
 }
 
diff --git a/daemon/face/transport.hpp b/daemon/face/transport.hpp
index ff5363f..85a0fd7 100644
--- a/daemon/face/transport.hpp
+++ b/daemon/face/transport.hpp
@@ -40,9 +40,9 @@
  */
 enum class TransportState {
   NONE,
-  UP, ///< the transport is up
-  DOWN, ///< the transport is down temporarily, and is being recovered
-  CLOSING, ///< the transport is requested to be closed
+  UP, ///< the transport is up and can transmit packets
+  DOWN, ///< the transport is temporarily down, and is being recovered
+  CLOSING, ///< the transport is being closed gracefully, either by the peer or by a call to close()
   FAILED, ///< the transport is being closed due to a failure
   CLOSED ///< the transport is closed, and can be safely deallocated
 };
diff --git a/tests/daemon/face/stream-transport.t.cpp b/tests/daemon/face/stream-transport.t.cpp
index 587c818..ad8d60c 100644
--- a/tests/daemon/face/stream-transport.t.cpp
+++ b/tests/daemon/face/stream-transport.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -144,7 +144,7 @@
 
   int nStateChanges = 0;
   this->transport->afterStateChange.connect(
-    [this, &nStateChanges] (TransportState oldState, TransportState newState) {
+    [&nStateChanges] (TransportState oldState, TransportState newState) {
       switch (nStateChanges) {
       case 0:
         BOOST_CHECK_EQUAL(oldState, TransportState::UP);
@@ -173,7 +173,7 @@
 {
   this->initialize();
 
-  this->transport->afterStateChange.connectSingleShot([this] (TransportState oldState, TransportState newState) {
+  this->transport->afterStateChange.connectSingleShot([] (TransportState oldState, TransportState newState) {
     BOOST_CHECK_EQUAL(oldState, TransportState::UP);
     BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
   });
@@ -195,7 +195,7 @@
 
   this->transport->afterStateChange.connectSingleShot([this] (TransportState oldState, TransportState newState) {
     BOOST_CHECK_EQUAL(oldState, TransportState::UP);
-    BOOST_CHECK_EQUAL(newState, TransportState::FAILED);
+    BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
     this->limitedIo.afterOp();
   });
 
@@ -203,7 +203,7 @@
   BOOST_REQUIRE_EQUAL(this->limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
 
   this->transport->afterStateChange.connectSingleShot([this] (TransportState oldState, TransportState newState) {
-    BOOST_CHECK_EQUAL(oldState, TransportState::FAILED);
+    BOOST_CHECK_EQUAL(oldState, TransportState::CLOSING);
     BOOST_CHECK_EQUAL(newState, TransportState::CLOSED);
     this->limitedIo.afterOp();
   });