face: allow the creation of permanent TCP faces

Change-Id: I516c176b000a78012f2ef7bd7f1f3e74c1758a94
Refs: #3167
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index f9a8eb7..dee9fa6 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -68,6 +68,7 @@
 
 void
 TcpChannel::connect(const tcp::Endpoint& remoteEndpoint,
+                    ndn::nfd::FacePersistency persistency,
                     bool wantLocalFieldsEnabled,
                     const FaceCreatedCallback& onFaceCreated,
                     const FaceCreationFailedCallback& onConnectFailed,
@@ -88,8 +89,8 @@
   clientSocket->async_connect(remoteEndpoint,
                               bind(&TcpChannel::handleConnect, this,
                                    boost::asio::placeholders::error, remoteEndpoint,
-                                   clientSocket, wantLocalFieldsEnabled, timeoutEvent,
-                                   onFaceCreated, onConnectFailed));
+                                   clientSocket, persistency, wantLocalFieldsEnabled,
+                                   timeoutEvent, onFaceCreated, onConnectFailed));
 }
 
 void
@@ -153,9 +154,7 @@
   }
 
   NFD_LOG_CHAN_TRACE("Incoming connection from " << m_socket.remote_endpoint());
-
-  createFace(std::move(m_socket), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
-             false, onFaceCreated);
+  createFace(std::move(m_socket), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, false, onFaceCreated);
 
   // prepare accepting the next connection
   accept(onFaceCreated, onAcceptFailed);
@@ -165,6 +164,7 @@
 TcpChannel::handleConnect(const boost::system::error_code& error,
                           const tcp::Endpoint& remoteEndpoint,
                           const shared_ptr<ip::tcp::socket>& socket,
+                          ndn::nfd::FacePersistency persistency,
                           bool wantLocalFieldsEnabled,
                           const scheduler::EventId& connectTimeoutEvent,
                           const FaceCreatedCallback& onFaceCreated,
@@ -190,8 +190,7 @@
   }
 
   NFD_LOG_CHAN_TRACE("Connected to " << socket->remote_endpoint());
-  createFace(std::move(*socket), ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-             wantLocalFieldsEnabled, onFaceCreated);
+  createFace(std::move(*socket), persistency, wantLocalFieldsEnabled, onFaceCreated);
 }
 
 void
diff --git a/daemon/face/tcp-channel.hpp b/daemon/face/tcp-channel.hpp
index ea28c3e..129587e 100644
--- a/daemon/face/tcp-channel.hpp
+++ b/daemon/face/tcp-channel.hpp
@@ -87,6 +87,7 @@
    */
   void
   connect(const tcp::Endpoint& remoteEndpoint,
+          ndn::nfd::FacePersistency persistency,
           bool wantLocalFieldsEnabled,
           const FaceCreatedCallback& onFaceCreated,
           const FaceCreationFailedCallback& onConnectFailed,
@@ -112,6 +113,7 @@
   handleConnect(const boost::system::error_code& error,
                 const tcp::Endpoint& remoteEndpoint,
                 const shared_ptr<boost::asio::ip::tcp::socket>& socket,
+                ndn::nfd::FacePersistency persistency,
                 bool wantLocalFieldsEnabled,
                 const scheduler::EventId& connectTimeoutEvent,
                 const FaceCreatedCallback& onFaceCreated,
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index 5e8f3fb..49f1307 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -135,9 +135,9 @@
     return;
   }
 
-  if (persistency != ndn::nfd::FACE_PERSISTENCY_PERSISTENT) {
-    NFD_LOG_TRACE("createFace only supports FACE_PERSISTENCY_PERSISTENT");
-    onFailure(406, "Outgoing TCP faces only support persistent persistency");
+  if (persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
+    NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
+    onFailure(406, "Outgoing TCP faces do not support on-demand persistency");
     return;
   }
 
@@ -145,9 +145,9 @@
                          boost::lexical_cast<uint16_t>(remoteUri.getPort()));
 
   if (endpoint.address().is_multicast()) {
-   NFD_LOG_TRACE("createFace cannot create multicast faces");
-   onFailure(406, "Cannot create multicast TCP faces");
-   return;
+    NFD_LOG_TRACE("createFace does not support multicast faces");
+    onFailure(406, "Cannot create multicast TCP faces");
+    return;
   }
 
   if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end()) {
@@ -167,7 +167,7 @@
   for (const auto& i : m_channels) {
     if ((i.first.address().is_v4() && endpoint.address().is_v4()) ||
         (i.first.address().is_v6() && endpoint.address().is_v6())) {
-      i.second->connect(endpoint, wantLocalFieldsEnabled, onCreated, onFailure);
+      i.second->connect(endpoint, persistency, wantLocalFieldsEnabled, onCreated, onFailure);
       return;
     }
   }
diff --git a/tests/daemon/face/tcp-channel-fixture.hpp b/tests/daemon/face/tcp-channel-fixture.hpp
index 4f63035..798fedd 100644
--- a/tests/daemon/face/tcp-channel-fixture.hpp
+++ b/tests/daemon/face/tcp-channel-fixture.hpp
@@ -50,7 +50,7 @@
   connect(TcpChannel& channel) final
   {
     g_io.post([&] {
-      channel.connect(listenerEp, false,
+      channel.connect(listenerEp, ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false,
         [this] (const shared_ptr<Face>& newFace) {
           BOOST_REQUIRE(newFace != nullptr);
           connectFaceClosedSignal(*newFace, [this] { limitedIo.afterOp(); });
diff --git a/tests/daemon/face/tcp-channel.t.cpp b/tests/daemon/face/tcp-channel.t.cpp
index 8068364..986d471 100644
--- a/tests/daemon/face/tcp-channel.t.cpp
+++ b/tests/daemon/face/tcp-channel.t.cpp
@@ -46,7 +46,8 @@
   // do not listen
 
   auto channel = this->makeChannel(A());
-  channel->connect(tcp::Endpoint(address, 7040), false,
+  channel->connect(tcp::Endpoint(address, 7040),
+    ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false,
     [this] (const shared_ptr<nfd::Face>&) {
       BOOST_FAIL("Connect succeeded when it should have failed");
       this->limitedIo.afterOp();
diff --git a/tests/daemon/face/tcp-factory.t.cpp b/tests/daemon/face/tcp-factory.t.cpp
index 31e8918..d3f5fc9 100644
--- a/tests/daemon/face/tcp-factory.t.cpp
+++ b/tests/daemon/face/tcp-factory.t.cpp
@@ -185,35 +185,40 @@
              ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
              false,
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
+
+  createFace(factory,
+             FaceUri("tcp4://127.0.0.1:6363"),
+             {},
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             false,
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
+
+  createFace(factory,
+             FaceUri("tcp4://127.0.0.1:20072"),
+             {},
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             false,
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
 }
 
 BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
 {
   TcpFactory factory;
 
-  factory.createChannel("127.0.0.1", "20070");
   factory.createChannel("127.0.0.1", "20071");
   factory.createChannel("127.0.0.1", "20072");
 
   createFace(factory,
-             FaceUri("tcp4://127.0.0.1:20070"),
-             {},
-             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
-             false,
-             {CreateFaceExpectedResult::FAILURE, 406,
-               "Outgoing TCP faces only support persistent persistency"});
-
-  createFace(factory,
              FaceUri("tcp4://127.0.0.1:20071"),
              {},
              ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
              false,
              {CreateFaceExpectedResult::FAILURE, 406,
-               "Outgoing TCP faces only support persistent persistency"});
+               "Outgoing TCP faces do not support on-demand persistency"});
 
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:20072"),
-             FaceUri("udp4://127.0.0.1:20073"),
+             FaceUri("tcp4://127.0.0.1:20073"),
              ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
              false,
              {CreateFaceExpectedResult::FAILURE, 406,
@@ -227,8 +232,7 @@
   onFaceCreated(const shared_ptr<Face>& newFace)
   {
     BOOST_CHECK_MESSAGE(false, "Timeout expected");
-    BOOST_CHECK(!static_cast<bool>(face1));
-    face1 = newFace;
+    face = newFace;
 
     limitedIo.afterOp();
   }
@@ -243,14 +247,13 @@
 
 public:
   LimitedIo limitedIo;
-
-  shared_ptr<Face> face1;
+  shared_ptr<Face> face;
 };
 
 BOOST_FIXTURE_TEST_CASE(FaceCreateTimeout, FaceCreateTimeoutFixture)
 {
   TcpFactory factory;
-  shared_ptr<TcpChannel> channel = factory.createChannel("0.0.0.0", "20070");
+  factory.createChannel("0.0.0.0", "20070");
 
   factory.createFace(FaceUri("tcp4://192.0.2.1:20070"),
                      {},
@@ -259,10 +262,8 @@
                      bind(&FaceCreateTimeoutFixture::onFaceCreated, this, _1),
                      bind(&FaceCreateTimeoutFixture::onConnectFailed, this, _2));
 
-  BOOST_CHECK_MESSAGE(limitedIo.run(1, time::seconds(10)) == LimitedIo::EXCEED_OPS,
-                      "TcpChannel error: cannot connect or cannot accept connection");
-
-  BOOST_CHECK_EQUAL(static_cast<bool>(face1), false);
+  BOOST_REQUIRE_EQUAL(limitedIo.run(1, time::seconds(10)), LimitedIo::EXCEED_OPS);
+  BOOST_CHECK(face == nullptr);
 }
 
 class FakeNetworkInterfaceFixture : public BaseFixture
diff --git a/tests/daemon/face/udp-factory.t.cpp b/tests/daemon/face/udp-factory.t.cpp
index e658248..3270ad6 100644
--- a/tests/daemon/face/udp-factory.t.cpp
+++ b/tests/daemon/face/udp-factory.t.cpp
@@ -611,14 +611,14 @@
   factory.createChannel("127.0.0.1", "20071");
 
   createFace(factory,
-             FaceUri("udp4://127.0.0.1:20070"),
+             FaceUri("udp4://127.0.0.1:6363"),
              {},
              ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
              false,
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
-             FaceUri("udp4://127.0.0.1:20070"),
+             FaceUri("udp4://127.0.0.1:6363"),
              {},
              ndn::nfd::FACE_PERSISTENCY_PERMANENT,
              false,
@@ -636,11 +636,11 @@
 {
   UdpFactory factory;
 
-  factory.createChannel("127.0.0.1", "20070");
   factory.createChannel("127.0.0.1", "20071");
+  factory.createChannel("127.0.0.1", "20072");
 
   createFace(factory,
-             FaceUri("udp4://127.0.0.1:20070"),
+             FaceUri("udp4://127.0.0.1:20071"),
              {},
              ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
              false,
@@ -648,7 +648,7 @@
                "Outgoing unicast UDP faces do not support on-demand persistency"});
 
   createFace(factory,
-             FaceUri("udp4://127.0.0.1:20071"),
+             FaceUri("udp4://127.0.0.1:20072"),
              FaceUri("udp4://127.0.0.1:20073"),
              ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
              false,
diff --git a/tests/daemon/mgmt/face-manager-create-face.t.cpp b/tests/daemon/mgmt/face-manager-create-face.t.cpp
index 5cfe952..f96e532 100644
--- a/tests/daemon/mgmt/face-manager-create-face.t.cpp
+++ b/tests/daemon/mgmt/face-manager-create-face.t.cpp
@@ -27,8 +27,6 @@
 #include "face-manager-command-fixture.hpp"
 #include "nfd-manager-common-fixture.hpp"
 
-#include <thread>
-
 namespace nfd {
 namespace tests {
 
@@ -40,7 +38,7 @@
 class TcpFaceOnDemand
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -52,7 +50,7 @@
 class TcpFacePersistent
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -64,7 +62,7 @@
 class TcpFacePermanent
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -76,7 +74,7 @@
 class UdpFaceOnDemand
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -88,7 +86,7 @@
 class UdpFacePersistent
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -100,7 +98,7 @@
 class UdpFacePermanent
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -113,7 +111,7 @@
                            // fails because remote endpoint is prohibited
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -124,7 +122,7 @@
 class LocalTcpFaceLocalFieldsEnabled
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -137,7 +135,7 @@
 class LocalTcpFaceLocalFieldsDisabled
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -150,7 +148,7 @@
 class NonLocalUdpFaceLocalFieldsEnabled // won't work because non-local scope
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -163,7 +161,7 @@
 class NonLocalUdpFaceLocalFieldsDisabled
 {
 public:
-  ControlParameters
+  static ControlParameters
   getParameters()
   {
     return ControlParameters()
@@ -176,9 +174,10 @@
 namespace mpl = boost::mpl;
 
 // pairs of CreateCommand and Success/Failure status
-typedef mpl::vector<mpl::pair<TcpFaceOnDemand, CommandFailure<406>>,
+using TestCases = mpl::vector<
+                    mpl::pair<TcpFaceOnDemand, CommandFailure<406>>,
                     mpl::pair<TcpFacePersistent, CommandSuccess>,
-                    mpl::pair<TcpFacePermanent, CommandFailure<406>>,
+                    mpl::pair<TcpFacePermanent, CommandSuccess>,
                     mpl::pair<UdpFaceOnDemand, CommandFailure<406>>,
                     mpl::pair<UdpFacePersistent, CommandSuccess>,
                     mpl::pair<UdpFacePermanent, CommandSuccess>,
@@ -186,16 +185,16 @@
                     mpl::pair<LocalTcpFaceLocalFieldsEnabled, CommandSuccess>,
                     mpl::pair<LocalTcpFaceLocalFieldsDisabled, CommandSuccess>,
                     mpl::pair<NonLocalUdpFaceLocalFieldsEnabled, CommandFailure<406>>,
-                    mpl::pair<NonLocalUdpFaceLocalFieldsDisabled, CommandSuccess>> Faces;
+                    mpl::pair<NonLocalUdpFaceLocalFieldsDisabled, CommandSuccess>>;
 
-BOOST_FIXTURE_TEST_CASE_TEMPLATE(NewFace, T, Faces, FaceManagerCommandFixture)
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(NewFace, T, TestCases, FaceManagerCommandFixture)
 {
-  typedef typename T::first FaceType;
-  typedef typename T::second CreateResult;
+  using FaceType = typename T::first;
+  using CreateResult = typename T::second;
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(FaceType().getParameters().wireEncode());
+  commandName.append(FaceType::getParameters().wireEncode());
   auto command = makeInterest(commandName);
   m_keyChain.sign(*command);
 
@@ -206,12 +205,12 @@
     }
 
     ControlResponse actual(response.getContent().blockFromValue());
-    ControlResponse expected(CreateResult().getExpected());
+    ControlResponse expected(CreateResult::getExpected());
     BOOST_TEST_MESSAGE(actual.getText());
     BOOST_CHECK_EQUAL(expected.getCode(), actual.getCode());
 
     if (actual.getBody().hasWire()) {
-      ControlParameters expectedParams(FaceType().getParameters());
+      ControlParameters expectedParams(FaceType::getParameters());
       ControlParameters actualParams(actual.getBody());
 
       BOOST_CHECK(actualParams.hasFaceId());
@@ -234,7 +233,7 @@
 
     if (actual.getCode() != 200) {
       // ensure face not created
-      FaceUri uri(FaceType().getParameters().getUri());
+      FaceUri uri(FaceType::getParameters().getUri());
       auto& faceTable = this->node1.manager.m_faceTable;
       BOOST_CHECK(std::none_of(faceTable.begin(), faceTable.end(), [uri] (Face& face) {
         return face.getRemoteUri() == uri;
@@ -259,7 +258,7 @@
 
     Name commandName("/localhost/nfd/faces");
     commandName.append("create");
-    commandName.append(FaceType().getParameters().wireEncode());
+    commandName.append(FaceType::getParameters().wireEncode());
     auto command = makeInterest(commandName);
     m_keyChain.sign(*command);
 
@@ -268,7 +267,7 @@
   }
 
   // find the created face
-  auto foundFace = this->node1.findFaceByUri(FaceType().getParameters().getUri());
+  auto foundFace = this->node1.findFaceByUri(FaceType::getParameters().getUri());
   BOOST_REQUIRE(foundFace != nullptr);
 
   {
@@ -276,7 +275,7 @@
 
     Name commandName("/localhost/nfd/faces");
     commandName.append("create");
-    commandName.append(FaceType().getParameters().wireEncode());
+    commandName.append(FaceType::getParameters().wireEncode());
     auto command = makeInterest(commandName);
     m_keyChain.sign(*command);
 
diff --git a/tests/other/face-benchmark.cpp b/tests/other/face-benchmark.cpp
index 36bc4f4..289a270 100644
--- a/tests/other/face-benchmark.cpp
+++ b/tests/other/face-benchmark.cpp
@@ -128,6 +128,7 @@
     auto port = boost::lexical_cast<uint16_t>(uriR.getPort());
     if (uriR.getScheme() == "tcp4") {
       m_tcpChannel.connect(tcp::Endpoint(addr, port),
+                           ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                            false,
                            bind(&FaceBenchmark::onRightFaceCreated, this, faceL, _1),
                            bind(&FaceBenchmark::onFaceCreationFailed, _1, _2));