ccnx: Make verifier thread-safe; use it in ccnx-wrapper

Change-Id: I5ba3d2565921c461cabe912fb86504bc36b6a69f
diff --git a/ccnx/ccnx-verifier.cpp b/ccnx/ccnx-verifier.cpp
index cee45a9..6090274 100644
--- a/ccnx/ccnx-verifier.cpp
+++ b/ccnx/ccnx-verifier.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "ccnx-verifier.h"
+#include "ccnx-wrapper.h"
 
 namespace Ccnx {
 
@@ -47,20 +48,24 @@
   }
 
   HashPtr publisherPublicKeyDigest = pco->publisherPublicKeyDigest();
-  CertCache::iterator it = m_certCache.find(*publisherPublicKeyDigest);
-  if (it != m_certCache.end())
+
   {
-    CertPtr cert = it->second;
-    if (cert->validity() == Cert::WITHIN_VALID_TIME_SPAN)
+    UniqueRecLock lock(m_cacheLock);
+    CertCache::iterator it = m_certCache.find(*publisherPublicKeyDigest);
+    if (it != m_certCache.end())
     {
-      // integrity checked, and the key is trustworthy
-      pco->setVerified(true);
-      return true;
-    }
-    else
-    {
-      // delete the invalid cert cache
-      m_certCache.erase(it);
+      CertPtr cert = it->second;
+      if (cert->validity() == Cert::WITHIN_VALID_TIME_SPAN)
+      {
+        // integrity checked, and the key is trustworthy
+        pco->setVerified(true);
+        return true;
+      }
+      else
+      {
+        // delete the invalid cert cache
+        m_certCache.erase(it);
+      }
     }
   }
 
@@ -139,7 +144,10 @@
 
   // ok, keyObject verified, because metaObject is signed by the same parent key and integrity checked
   // so metaObject is also verified
-  m_certCache.insert(std::make_pair(cert->keyDigest(), cert));
+  {
+    UniqueRecLock lock(m_cacheLock);
+    m_certCache.insert(std::make_pair(cert->keyDigest(), cert));
+  }
 
   pco->setVerified(true);
   return true;
diff --git a/ccnx/ccnx-verifier.h b/ccnx/ccnx-verifier.h
index 0b1fd84..e4981d3 100644
--- a/ccnx/ccnx-verifier.h
+++ b/ccnx/ccnx-verifier.h
@@ -23,19 +23,18 @@
 #define CCNX_VERIFIER_H
 
 #include "ccnx-common.h"
-#include "ccnx-wrapper.h"
 #include "ccnx-name.h"
 #include "ccnx-cert.h"
 #include "ccnx-pco.h"
 #include <map>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/thread.hpp>
 
 namespace Ccnx {
 
 class CcnxWrapper;
 
-// not thread-safe, don't want to add a mutex for CertCache
-// which increases the possibility of dead-locking
-// ccnx-wrapper would take care of thread-safety issue
 class Verifier
 {
 public:
@@ -51,6 +50,9 @@
   Hash m_rootKeyDigest;
   typedef std::map<Hash, CertPtr> CertCache;
   CertCache m_certCache;
+  typedef boost::recursive_mutex RecLock;
+  typedef boost::unique_lock<RecLock> UniqueRecLock;
+  RecLock m_cacheLock;
 };
 
 } // Ccnx
diff --git a/ccnx/ccnx-wrapper.cpp b/ccnx/ccnx-wrapper.cpp
index 645f5fc..e318f19 100644
--- a/ccnx/ccnx-wrapper.cpp
+++ b/ccnx/ccnx-wrapper.cpp
@@ -31,6 +31,7 @@
 #include <boost/algorithm/string.hpp>
 #include <sstream>
 
+#include "ccnx-verifier.h"
 #include "logging.h"
 
 INIT_LOGGER ("Ccnx.Wrapper");
@@ -110,6 +111,7 @@
   , m_running (true)
   , m_connected (false)
   , m_executor (new Executor(1))
+  , m_verifier(new Verifier(this))
 {
   start ();
 }
@@ -146,6 +148,11 @@
 CcnxWrapper::~CcnxWrapper()
 {
   shutdown ();
+  if (m_verifier != 0)
+  {
+    delete m_verifier;
+    m_verifier = 0;
+  }
 }
 
 void
@@ -702,6 +709,12 @@
   return checked;
 }
 
+bool
+CcnxWrapper::verifyKey(PcoPtr &pco)
+{
+  return m_verifier->verify(pco);
+}
+
 // This is needed just for get function implementation
 struct GetState
 {
diff --git a/ccnx/ccnx-wrapper.h b/ccnx/ccnx-wrapper.h
index 914293c..5367fbb 100644
--- a/ccnx/ccnx-wrapper.h
+++ b/ccnx/ccnx-wrapper.h
@@ -37,6 +37,7 @@
 
 struct CcnxOperationException : boost::exception, std::exception { };
 
+class Verifier;
 class CcnxWrapper
 {
 public:
@@ -95,6 +96,9 @@
   bool
   checkPcoIntegrity(PcoPtr &pco);
 
+  bool
+  verifyKey(PcoPtr &pco);
+
   PcoPtr
   get (const Name &interest, const Selectors &selector = Selectors(), double maxWait = 4.0/*seconds*/);
 
@@ -126,6 +130,7 @@
   bool m_connected;
   std::map<Name, InterestCallback> m_registeredInterests;
   ExecutorPtr m_executor;
+  Verifier *m_verifier;
 };
 
 typedef boost::shared_ptr<CcnxWrapper> CcnxWrapperPtr;