Fix failure status bug: when status is failure, request should be stopped

Change-Id: I699d9ae6bdc34ac67d9a8b3c69e9d789f9709c6d
diff --git a/src/ca-module.cpp b/src/ca-module.cpp
index 6b93ee4..9df8384 100644
--- a/src/ca-module.cpp
+++ b/src/ca-module.cpp
@@ -192,12 +192,17 @@
     return;
   }
   JsonSection contentJson = challenge->handleChallengeRequest(request, certRequest);
-  try {
-    m_storage->updateRequest(certRequest);
+  if (certRequest.getStatus() == ChallengeModule::FAILURE) {
+    m_storage->deleteRequest(certRequest.getRequestId());
   }
-  catch (const std::exception& e) {
-    _LOG_TRACE("Cannot update request instance " << e.what());
-    return;
+  else {
+    try {
+      m_storage->updateRequest(certRequest);
+    }
+    catch (const std::exception& e) {
+      _LOG_TRACE("Cannot update request instance " << e.what());
+      return;
+    }
   }
 
   Data result;
@@ -233,14 +238,18 @@
     return;
   }
   JsonSection contentJson = challenge->handleChallengeRequest(request, certRequest);
-  try {
-    m_storage->updateRequest(certRequest);
+  if (certRequest.getStatus() == ChallengeModule::FAILURE) {
+    m_storage->deleteRequest(certRequest.getRequestId());
   }
-  catch (const std::exception& e) {
-    _LOG_TRACE("Cannot update request instance " << e.what());
-    return;
+  else {
+    try {
+      m_storage->updateRequest(certRequest);
+    }
+    catch (const std::exception& e) {
+      _LOG_TRACE("Cannot update request instance " << e.what());
+      return;
+    }
   }
-
   Data result;
   result.setName(request.getName());
   result.setContent(dataContentFromJson(contentJson));
diff --git a/src/challenge-module.cpp b/src/challenge-module.cpp
index 59a0e58..371be25 100644
--- a/src/challenge-module.cpp
+++ b/src/challenge-module.cpp
@@ -30,6 +30,7 @@
 const std::string ChallengeModule::WAIT_SELECTION = "wait-selection";
 const std::string ChallengeModule::SUCCESS = "success";
 const std::string ChallengeModule::PENDING = "pending";
+const std::string ChallengeModule::FAILURE = "failure";
 
 ChallengeModule::ChallengeModule(const std::string& uniqueType)
   : CHALLENGE_TYPE(uniqueType)
diff --git a/src/challenge-module.hpp b/src/challenge-module.hpp
index 7e36d4c..af0d40b 100644
--- a/src/challenge-module.hpp
+++ b/src/challenge-module.hpp
@@ -173,6 +173,7 @@
   static const std::string WAIT_SELECTION;
   static const std::string SUCCESS;
   static const std::string PENDING;
+  static const std::string FAILURE;
 
 private:
   typedef function<unique_ptr<ChallengeModule> ()> ChallengeCreateFunc;
diff --git a/src/challenge-module/challenge-credential.cpp b/src/challenge-module/challenge-credential.cpp
index 2a35395..2a47e7a 100644
--- a/src/challenge-module/challenge-credential.cpp
+++ b/src/challenge-module/challenge-credential.cpp
@@ -91,7 +91,7 @@
   catch (const std::exception& e) {
     _LOG_TRACE("Cannot load credential parameter: cert" << e.what());
     request.setStatus(FAILURE_INVALID_FORMAT);
-    return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_FORMAT);
+    return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_INVALID_FORMAT);
   }
   ss1.str("");
   ss1.clear();
@@ -104,7 +104,7 @@
   catch (const std::exception& e) {
     _LOG_TRACE("Cannot load credential parameter: self-signed cert" << e.what());
     request.setStatus(FAILURE_INVALID_FORMAT);
-    return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_FORMAT);
+    return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_INVALID_FORMAT);
   }
   ss2.str("");
   ss2.clear();
@@ -128,7 +128,7 @@
 ChallengeCredential::processValidateInterest(const Interest& interest, CertificateRequest& request)
 {
   // there is no validate request here, do nothing
-  return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_FORMAT);
+  return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_INVALID_FORMAT);
 }
 
 std::list<std::string>
diff --git a/src/challenge-module/challenge-credential.hpp b/src/challenge-module/challenge-credential.hpp
index a617f18..bcd8b5d 100644
--- a/src/challenge-module/challenge-credential.hpp
+++ b/src/challenge-module/challenge-credential.hpp
@@ -40,8 +40,10 @@
  *   1. Requester provides a certificate signed by that trusted certificate as credential.
  *   2. The challenge module will verify the signature of the credential.
  *
- * There are several challenge status in EMAIL challenge:
- *   FAILURE_INVALID_SIG: When the credential cannot be validated.
+ * Failure info when application fails:
+ *   FAILURE_INVALID_CREDENTIAL: When the cert issued from trust anchor or self-signed cert
+ *     cannot be validated.
+ *   FAILURE_INVALID_FORMAT: When the credential format is wrong.
  */
 class ChallengeCredential : public ChallengeModule
 {
@@ -76,6 +78,7 @@
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   static const std::string FAILURE_INVALID_CREDENTIAL;
   static const std::string FAILURE_INVALID_FORMAT;
+
   static const std::string JSON_CREDENTIAL_CERT;
   static const std::string JSON_CREDENTIAL_SELF;
 
diff --git a/src/challenge-module/challenge-email.cpp b/src/challenge-module/challenge-email.cpp
index 036ccd2..fc25d8c 100644
--- a/src/challenge-module/challenge-email.cpp
+++ b/src/challenge-module/challenge-email.cpp
@@ -31,9 +31,10 @@
 
 const std::string ChallengeEmail::NEED_CODE = "need-code";
 const std::string ChallengeEmail::WRONG_CODE = "wrong-code";
-const std::string ChallengeEmail::FAILURE_TIMEOUT = "failure-timeout";
-const std::string ChallengeEmail::FAILURE_MAXRETRY = "failure-max-retry";
+
 const std::string ChallengeEmail::FAILURE_INVALID_EMAIL = "failure-invalid-email";
+const std::string ChallengeEmail::FAILURE_TIMEOUT = "timeout";
+const std::string ChallengeEmail::FAILURE_MAXRETRY = "max-retry";
 
 const std::string ChallengeEmail::JSON_EMAIL = "email";
 const std::string ChallengeEmail::JSON_CODE_TP = "code-timepoint";
@@ -43,7 +44,7 @@
 ChallengeEmail::ChallengeEmail(const std::string& scriptPath,
                                const size_t& maxAttemptTimes,
                                const time::seconds secretLifetime)
-  : ChallengeModule("EMAIL")
+  : ChallengeModule("Email")
   , m_sendEmailScript(scriptPath)
   , m_maxAttemptTimes(maxAttemptTimes)
   , m_secretLifetime(secretLifetime)
@@ -60,7 +61,7 @@
   if (!isValidEmailAddress(emailAddress)) {
     request.setStatus(FAILURE_INVALID_EMAIL);
     request.setChallengeType(CHALLENGE_TYPE);
-    return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_EMAIL);
+    return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_INVALID_EMAIL);
   }
 
   std::string emailCode = generateSecretCode();
@@ -69,8 +70,7 @@
   request.setStatus(NEED_CODE);
   request.setChallengeType(CHALLENGE_TYPE);
   request.setChallengeSecrets(generateStoredSecrets(time::system_clock::now(),
-                                                    emailCode,
-                                                    m_maxAttemptTimes));
+                                                    emailCode, m_maxAttemptTimes));
   return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, NEED_CODE);
 }
 
@@ -86,7 +86,7 @@
     // secret expires
     request.setStatus(FAILURE_TIMEOUT);
     request.setChallengeSecrets(JsonSection());
-    return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_TIMEOUT);
+    return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_TIMEOUT);
   }
   else if (givenCode == std::get<1>(parsedSecret)) {
     request.setStatus(SUCCESS);
@@ -108,7 +108,7 @@
       // run out times
       request.setStatus(FAILURE_MAXRETRY);
       request.setChallengeSecrets(JsonSection());
-      return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_MAXRETRY);
+      return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_MAXRETRY);
     }
   }
 }
@@ -129,7 +129,7 @@
     result.push_back("Please input your verification code:");
   }
   else if (status == WRONG_CODE) {
-    result.push_back("Incorrect PIN code, please input your verification code:");
+    result.push_back("Incorrect PIN code, please try again and input your verification code:");
   }
   return result;
 }
diff --git a/src/challenge-module/challenge-email.hpp b/src/challenge-module/challenge-email.hpp
index b00a3de..0f0d935 100644
--- a/src/challenge-module/challenge-email.hpp
+++ b/src/challenge-module/challenge-email.hpp
@@ -40,9 +40,11 @@
  * There are several challenge status in EMAIL challenge:
  *   NEED_CODE: When email address is provided and the verification code has been sent out.
  *   WRONG_CODE: Wrong code but still within secret lifetime and within max try times.
+ *
+ * Failure info when application fails:
+ *   FAILURE_MAXRETRY: When run out retry times.
  *   FAILURE_INVALID_EMAIL: When the email is invalid.
  *   FAILURE_TIMEOUT: When the secret lifetime expires.
- *   FAILURE_MAXRETRY: When run out retry times.
  */
 class ChallengeEmail : public ChallengeModule
 {
@@ -90,8 +92,9 @@
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   static const std::string NEED_CODE;
   static const std::string WRONG_CODE;
-  static const std::string FAILURE_INVALID_EMAIL;
+
   static const std::string FAILURE_TIMEOUT;
+  static const std::string FAILURE_INVALID_EMAIL;
   static const std::string FAILURE_MAXRETRY;
 
   static const std::string JSON_EMAIL;
diff --git a/src/challenge-module/challenge-pin.cpp b/src/challenge-module/challenge-pin.cpp
index 94ea3e7..2bb81ea 100644
--- a/src/challenge-module/challenge-pin.cpp
+++ b/src/challenge-module/challenge-pin.cpp
@@ -32,6 +32,7 @@
 
 const std::string ChallengePin::NEED_CODE = "need-code";
 const std::string ChallengePin::WRONG_CODE = "wrong-code";
+
 const std::string ChallengePin::FAILURE_TIMEOUT = "failure-timeout";
 const std::string ChallengePin::FAILURE_MAXRETRY = "failure-max-retry";
 
@@ -72,7 +73,7 @@
     // secret expires
     request.setStatus(FAILURE_TIMEOUT);
     request.setChallengeSecrets(JsonSection());
-    return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_TIMEOUT);
+    return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_TIMEOUT);
   }
   else if (givenCode == std::get<1>(parsedSecret)) {
     request.setStatus(SUCCESS);
@@ -94,7 +95,7 @@
       // run out times
       request.setStatus(FAILURE_MAXRETRY);
       request.setChallengeSecrets(JsonSection());
-      return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_MAXRETRY);
+      return genFailureJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE, FAILURE_MAXRETRY);
     }
   }
 }
@@ -114,7 +115,7 @@
     result.push_back("Please input your verification code:");
   }
   else if (status == WRONG_CODE) {
-    result.push_back("Incorrect PIN code, please input your verification code:");
+    result.push_back("Incorrect PIN code, please try again and input your verification code:");
   }
   return result;
 }
diff --git a/src/challenge-module/challenge-pin.hpp b/src/challenge-module/challenge-pin.hpp
index 31ea05f..982ed4e 100644
--- a/src/challenge-module/challenge-pin.hpp
+++ b/src/challenge-module/challenge-pin.hpp
@@ -40,6 +40,8 @@
  * There are four specific status defined in this challenge:
  *   NEED_CODE: When selection is made.
  *   WRONG_CODE: Get wrong verification code but still with secret lifetime and max retry times.
+ *
+ * Failure info when application fails:
  *   FAILURE_TIMEOUT: When secret is out-dated.
  *   FAILURE_MAXRETRY: When requester tries too many times.
  */
@@ -81,6 +83,7 @@
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   static const std::string NEED_CODE;
   static const std::string WRONG_CODE;
+
   static const std::string FAILURE_TIMEOUT;
   static const std::string FAILURE_MAXRETRY;
 
diff --git a/src/client-module.cpp b/src/client-module.cpp
index 157f28d..b0f9825 100644
--- a/src/client-module.cpp
+++ b/src/client-module.cpp
@@ -21,6 +21,7 @@
 #include "client-module.hpp"
 #include "logging.hpp"
 #include "json-helper.hpp"
+#include "challenge-module.hpp"
 #include <ndn-cxx/security/signing-helpers.hpp>
 #include <ndn-cxx/security/verification-helpers.hpp>
 
@@ -391,8 +392,8 @@
 ClientModule::checkStatus(const RequestState& state, const JsonSection& json,
                           const ErrorCallback& errorCallback)
 {
-  if (state.m_status == "error") {
-    errorCallback(json.get(JSON_ERROR_INFO, ""));
+  if (state.m_status == ChallengeModule::FAILURE) {
+    errorCallback(json.get(JSON_FAILURE_INFO, ""));
     return false;
   }
   if (state.m_requestId.empty() || state.m_status.empty()) {
diff --git a/src/json-helper.cpp b/src/json-helper.cpp
index 78969fc..81fa829 100644
--- a/src/json-helper.cpp
+++ b/src/json-helper.cpp
@@ -69,11 +69,14 @@
 }
 
 const JsonSection
-genErrorJson(const std::string& errorInfo)
+genFailureJson(const std::string& requestId, const std::string& challengeType,
+               const std::string& status, const std::string& failureInfo)
 {
   JsonSection root;
-  root.put(JSON_STATUS, "error");
-  root.put(JSON_ERROR_INFO, errorInfo);
+  root.put(JSON_REQUEST_ID, requestId);
+  root.put(JSON_CHALLENGE_TYPE, challengeType);
+  root.put(JSON_STATUS, status);
+  root.put(JSON_FAILURE_INFO, failureInfo);
   return root;
 }
 
diff --git a/src/json-helper.hpp b/src/json-helper.hpp
index 791fc12..4540596 100644
--- a/src/json-helper.hpp
+++ b/src/json-helper.hpp
@@ -32,7 +32,7 @@
 const std::string JSON_REQUEST_ID = "request-id";
 const std::string JSON_CHALLENGES = "challenges";
 const std::string JSON_CHALLENGE_TYPE = "challenge-type";
-const std::string JSON_ERROR_INFO = "error-info";
+const std::string JSON_FAILURE_INFO = "failure-info";
 const std::string JSON_CERTIFICATE = "certificate";
 
 /**
@@ -100,12 +100,15 @@
  *
  * Target JSON format:
  * {
- *   "status": "error",
- *   "error-info": "@p errorInfo"
+ *   "request-id": "@p requestId",
+ *   "challenge-type": "@p challengeType",
+ *   "status": "failure",
+ *   "failure-info": "@p errorInfo",
  * }
  */
 const JsonSection
-genErrorJson(const std::string& errorInfo);
+genFailureJson(const std::string& requestId, const std::string& challengeType,
+               const std::string& status, const std::string& failureInfo);
 
 } // namespace ndncert
 } // namespace ndn