tools: create face during nfdc route add

refs #4332

Change-Id: I1a30bf87abd57bab08a2c027870e779392de0104
diff --git a/tools/nfdc/face-module.cpp b/tools/nfdc/face-module.cpp
index 37f5bd9..e46279d2 100644
--- a/tools/nfdc/face-module.cpp
+++ b/tools/nfdc/face-module.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "face-module.hpp"
+#include "canonizer.hpp"
 #include "find-face.hpp"
 
 namespace nfd {
@@ -179,34 +180,19 @@
     mtu = static_cast<uint64_t>(v);
   }
 
-  FaceUri canonicalRemote;
+  optional<FaceUri> canonicalRemote;
   optional<FaceUri> canonicalLocal;
 
-  auto handleCanonizeError = [&] (const FaceUri& faceUri, const std::string& error) {
-    ctx.exitCode = static_cast<int>(FindFace::Code::CANONIZE_ERROR);
-    ctx.err << "Error when canonizing '" << faceUri << "': " << error << '\n';
-  };
-
-  auto printPositiveResult = [&] (const std::string& actionSummary, const ControlParameters& resp) {
-    text::ItemAttributes ia;
-    ctx.out << actionSummary << ' '
-            << ia("id") << resp.getFaceId()
-            << ia("local") << resp.getLocalUri()
-            << ia("remote") << resp.getUri()
-            << ia("persistency") << resp.getFacePersistency();
-    printFaceParams(ctx.out, ia, resp);
-  };
-
-  auto updateFace = [&printPositiveResult] (ControlParameters respParams, ControlParameters resp) {
+  auto updateFace = [&] (ControlParameters respParams, ControlParameters resp) {
     // faces/update response does not have FaceUris, copy from faces/create response
     resp.setLocalUri(respParams.getLocalUri())
         .setUri(respParams.getUri());
-    printPositiveResult("face-updated", resp);
+    printSuccess(ctx.out, "face-updated", resp);
   };
 
   auto handle409 = [&] (const ControlResponse& resp) {
     ControlParameters respParams(resp.getBody());
-    if (respParams.getUri() != canonicalRemote.toString()) {
+    if (respParams.getUri() != canonicalRemote->toString()) {
       // we are conflicting with a different face, which is a general error
       return false;
     }
@@ -256,7 +242,7 @@
     }
     else {
       // don't do anything
-      printPositiveResult("face-exists", respParams);
+      printSuccess(ctx.out, "face-exists", respParams);
     }
 
     return true;
@@ -264,7 +250,7 @@
 
   auto doCreateFace = [&] {
     ControlParameters params;
-    params.setUri(canonicalRemote.toString());
+    params.setUri(canonicalRemote->toString());
     if (canonicalLocal) {
       params.setLocalUri(canonicalLocal->toString());
     }
@@ -287,7 +273,9 @@
 
     ctx.controller.start<ndn::nfd::FaceCreateCommand>(
       params,
-      bind(printPositiveResult, "face-created", _1),
+      [&] (const ControlParameters& resp) {
+        printSuccess(ctx.out, "face-created", resp);
+      },
       [&] (const ControlResponse& resp) {
         if (resp.getCode() == 409 && handle409(resp)) {
           return;
@@ -297,24 +285,33 @@
       ctx.makeCommandOptions());
   };
 
-  remoteUri.canonize(
-    [&] (const FaceUri& canonicalUri) {
-      canonicalRemote = canonicalUri;
-      if (localUri) {
-        localUri->canonize(
-          [&] (const FaceUri& canonicalUri) {
-            canonicalLocal = canonicalUri;
-            doCreateFace();
-          },
-          bind(handleCanonizeError, *localUri, _1),
-          ctx.face.getIoService(), ctx.getTimeout());
-      }
-      else {
+  std::string error;
+  std::tie(canonicalRemote, error) = canonize(ctx, remoteUri);
+  if (canonicalRemote) {
+    // RemoteUri canonization successful
+    if (localUri) {
+      std::tie(canonicalLocal, error) = canonize(ctx, *localUri);
+      if (canonicalLocal) {
+        // LocalUri canonization successful
         doCreateFace();
       }
-    },
-    bind(handleCanonizeError, remoteUri, _1),
-    ctx.face.getIoService(), ctx.getTimeout());
+      else {
+        // LocalUri canonization failure
+        auto canonizationError = canonizeErrorHelper(*localUri, error, "local FaceUri");
+        ctx.exitCode = static_cast<int>(canonizationError.first);
+        ctx.err << canonizationError.second << '\n';
+      }
+    }
+    else {
+      doCreateFace();
+    }
+  }
+  else {
+    // RemoteUri canonization failure
+    auto canonizationError = canonizeErrorHelper(remoteUri, error, "remote FaceUri");
+    ctx.exitCode = static_cast<int>(canonizationError.first);
+    ctx.err << canonizationError.second << '\n';
+  }
 
   ctx.face.processEvents();
 }
@@ -349,6 +346,7 @@
   ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
     ControlParameters().setFaceId(face.getFaceId()),
     [&] (const ControlParameters& resp) {
+      // We can't use printSuccess because some face attributes come from FaceStatus not ControlResponse
       ctx.out << "face-destroyed ";
       text::ItemAttributes ia;
       ctx.out << ia("id") << face.getFaceId()
@@ -528,6 +526,20 @@
 }
 
 void
+FaceModule::printSuccess(std::ostream& os,
+                         const std::string& actionSummary,
+                         const ControlParameters& resp)
+{
+  text::ItemAttributes ia;
+  os << actionSummary << ' '
+     << ia("id") << resp.getFaceId()
+     << ia("local") << resp.getLocalUri()
+     << ia("remote") << resp.getUri()
+     << ia("persistency") << resp.getFacePersistency();
+  printFaceParams(os, ia, resp);
+}
+
+void
 FaceModule::printFaceParams(std::ostream& os, text::ItemAttributes& ia, const ControlParameters& resp)
 {
   os << ia("reliability") << text::OnOff{resp.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)}