security: handle Nack in Validator

ref #3332

Change-Id: Ieb31ea4015ef3ae412ccbdd9f3eeade065f052ec
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index 2e1e637..62e4938 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2014 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -266,22 +266,52 @@
 }
 
 void
+Validator::onNack(const Interest& interest,
+                  const lp::Nack& nack,
+                  int remainingRetries,
+                  const OnFailure& onFailure,
+                  const shared_ptr<ValidationRequest>& validationRequest)
+{
+  if (remainingRetries > 0) {
+    Interest newInterest = Interest(interest);
+    newInterest.refreshNonce();
+
+    //Express the same interest with different nonce and decremented remainingRetries.
+    m_face->expressInterest(newInterest,
+                            bind(&Validator::onData, this, _1, _2, validationRequest),
+                            bind(&Validator::onNack, this, _1, _2,
+                                 remainingRetries - 1, onFailure, validationRequest),
+                            bind(&Validator::onTimeout, this, _1,
+                                 remainingRetries - 1, onFailure, validationRequest));
+  }
+  else {
+    onFailure("Cannot fetch cert: " + interest.getName().toUri());
+  }
+}
+
+void
 Validator::onTimeout(const Interest& interest,
                      int remainingRetries,
                      const OnFailure& onFailure,
                      const shared_ptr<ValidationRequest>& validationRequest)
 {
-  if (remainingRetries > 0)
-    // Issue the same expressInterest except decrement nRetrials.
-    m_face->expressInterest(interest,
+  if (remainingRetries > 0) {
+    Interest newInterest = Interest(interest);
+    newInterest.refreshNonce();
+
+    // Express the same interest with different nonce and decremented remainingRetries.
+    m_face->expressInterest(newInterest,
                             bind(&Validator::onData, this, _1, _2, validationRequest),
+                            bind(&Validator::onNack, this, _1, _2,
+                                 remainingRetries - 1, onFailure, validationRequest),
                             bind(&Validator::onTimeout, this, _1,
                                  remainingRetries - 1, onFailure, validationRequest));
-  else
+  }
+  else {
     onFailure("Cannot fetch cert: " + interest.getName().toUri());
+  }
 }
 
-
 void
 Validator::afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
                             const OnFailure& onFailure)
@@ -297,6 +327,8 @@
     {
       m_face->expressInterest((*it)->m_interest,
                               bind(&Validator::onData, this, _1, _2, *it),
+                              bind(&Validator::onNack, this, _1, _2,
+                                   (*it)->m_nRetries, onFailure, *it),
                               bind(&Validator::onTimeout,
                                    this, _1, (*it)->m_nRetries,
                                    onFailure,
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index 83e394e..bf8e1ca 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -282,6 +282,24 @@
   }
 
   /**
+   * @brief trigger when interest retrieves a Nack.
+   *
+   * Validator can decide how to handle a Nack, either call onFailure, or retry.
+   *
+   * @param interest The interest that retrieves a Nack.
+   * @param nack The Nack that is retrieved.
+   * @param nRemainingRetries The number of retries left.
+   * @param onFailure Failure callback when there is no more retries remaining.
+   * @param validationRequest The validationRequest containing the context of the interest.
+   */
+  virtual void
+  onNack(const Interest& interest,
+         const lp::Nack& nack,
+         int nRemainingRetries,
+         const OnFailure& onFailure,
+         const shared_ptr<ValidationRequest>& validationRequest);
+
+  /**
    * @brief trigger when interest for certificate times out.
    *
    * Validator can decide how to handle the timeout, either call onFailure, or retry.
@@ -291,7 +309,6 @@
    * @param onFailure Failure callback when there is no more retries remaining.
    * @param validationRequest The validationRequest containing the context of the interest.
    */
-
   virtual void
   onTimeout(const Interest& interest,
             int nRemainingRetries,