support for NS, TXT, NDNCERT, FH
diff --git a/src/app/name-caching-resolver.cpp b/src/app/name-caching-resolver.cpp
deleted file mode 100644
index 728d0b0..0000000
--- a/src/app/name-caching-resolver.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, Regents of the University of California.
- *
- * This file is part of NDNS (Named Data Networking Domain Name Service).
- * See AUTHORS.md for complete list of NDNS authors and contributors.
- *
- * NDNS is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-#include "name-caching-resolver.hpp"
-
-namespace ndn {
-namespace ndns {
-
-NameCachingResolver::NameCachingResolver(const char *programName, const char *prefix)
-: NDNApp(programName, prefix)
-//, m_resolverType(CachingResolver)
-{
-  this->setInterestLifetime(time::milliseconds(2000));
-}
-
-
-
-void
-NameCachingResolver::run()
-{
-  boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
-  signalSet.async_wait(boost::bind(&NDNApp::signalHandler, this));
- // boost::bind(&NdnTlvPingServer::signalHandler, this)
-
-  Name name(m_prefix);
-  name.append(Query::toString(Query::QUERY_DNS_R));
-
-  m_face.setInterestFilter(name,
-               bind(&NameCachingResolver::onInterest,
-                  this, _1, _2),
-               bind(&NDNApp::onRegisterFailed,
-                  this, _1,_2));
-
-  std::cout << "\n=== NDNS Resolver "<<m_programName
-            <<" with routeble prefix "<< name.toUri()
-            << " starts===\n" << std::endl;
-
-  try {
-    m_face.processEvents();
-  }
-  catch (std::exception& e) {
-    std::cerr << "ERROR: " << e.what() << std::endl;
-    m_hasError = true;
-    m_ioService.stop();
-  }
-}
-
-
-
-void
-NameCachingResolver::onData(const Interest& interest, Data &data, IterativeQuery& iq)
-{
-  if (interest.getName() != iq.getLastInterest().getName())
-  {
-    std::cout<<iq<<std::endl;
-    std::cout<<"waiting for "<<iq.getLastInterest().getName().toUri()<<std::endl;
-    std::cout<<"coming data "<<data.getName().toUri()<<std::endl;
-    return;
-  }
-
-  iq.doData(data);
-
-  if (iq.getStep() == IterativeQuery::AnswerStub)
-  {
-    Data data = iq.getLastResponse().toData();
-    Name name = iq.getQuery().getAuthorityZone();
-    name.append(Query::toString(iq.getQuery().getQueryType()));
-    name.append(iq.getQuery().getRrLabel());
-    name.append(RR::toString(iq.getQuery().getRrType()));
-    name.appendVersion();
-    data.setName(name);
-    data.setFreshnessPeriod(iq.getLastResponse().getFreshness());
-
-    m_keyChain.sign(data);
-    m_face.put(data);
-    std::cout<<"[* <- *] answer Response ("
-        <<Response::toString(iq.getLastResponse().getResponseType())<<") to stub:"<<std::endl;
-    std::cout<<iq.getLastResponse()<<std::endl;
-    for (int i=0; i<15; i++)
-    {
-      std::cout<<"----";
-    }
-    std::cout<<std::endl<<std::endl;
-
-  } else if (iq.getStep() == IterativeQuery::NSQuery){
-    resolve(iq);
-  } else if (iq.getStep() == IterativeQuery::RRQuery) {
-    resolve(iq);
-  } else if (iq.getStep() == IterativeQuery::Abort) {
-    return;
-  } else {
-    std::cout<<"let me see the current step="<<IterativeQuery::toString(iq.getStep())<<std::endl;
-    std::cout<<iq<<std::endl;
-  }
-
-}
-
-
-void
-NameCachingResolver::answerRespNack(IterativeQuery& iq)
-{
-  Response re;
-
-  Name name = iq.getQuery().getAuthorityZone();
-  name.append(Query::toString(iq.getQuery().getQueryType()));
-  name.append(iq.getQuery().getRrLabel());
-  name.append(RR::toString(iq.getQuery().getRrType()));
-  name.appendVersion();
-
-  re.setResponseType(Response::NDNS_Nack);
-  re.setFreshness(this->getContentFreshness());
-  re.setQueryName(name);
-  Data data = re.toData();
-
-  m_keyChain.sign(data);
-  m_face.put(data);
-  std::cout<<"[* <- *] answer RRs to stub:"<<std::endl;
-  std::cout<<iq.getLastResponse().getStringRRs()<<std::endl;
-  for (int i=0; i<15; i++)
-  {
-    std::cout<<"----";
-  }
-  std::cout<<std::endl<<std::endl;
-}
-
-void
-NameCachingResolver::onInterest(const Name &name, const Interest &interest)
-{
-  Query query;
-  query.fromInterest(interest);
-  std::cout<<"[* -> *] receive Interest: "<<interest.getName().toUri()<<std::endl;
-  if (query.getQueryType() == Query::QUERY_DNS)
-  {
-    cout<<m_programName<<" is not in charge of Query_DNS"<<endl;
-  }
-
-  IterativeQuery iq(query);
-  //iq.setQuery(query);
-  resolve(iq);
-
-}
-
-
-void
-NameCachingResolver::onTimeout(const Interest& interest, IterativeQuery& iq)
-{
-  std::cout<<"[* !! *] timeout Interest "<<interest.getName().toUri()<<" timeouts"<<std::endl;
-
-  iq.doTimeout();
-  return;
-}
-
-void
-NameCachingResolver::resolve(IterativeQuery& iq) {
-
-  Interest interest = iq.toLatestInterest();
-
-  //must be set before express interest,since the call will back call iq
-  //if set after, then the iq in call of onData will return nothing
-  //be very careful here,  as a new guy to c++
-
-  interest.setInterestLifetime(this->getInterestLifetime());
-  iq.setLastInterest(interest);
-  try {
-    m_face.expressInterest(interest,
-            boost::bind(&NameCachingResolver::onData, this, _1, _2, iq),
-            boost::bind(&NameCachingResolver::onTimeout, this, _1, iq)
-            );
-  }catch(std::exception& e) {
-    std::cerr << "ERROR: " << e.what() << std::endl;
-  }
-
-
-  std::cout<<"[* <- *] send Interest: "<<interest.getName().toUri()<<std::endl;
-  std::cout<<iq<<std::endl;
-}
-
-} /* namespace ndns */
-} /* namespace ndn */
diff --git a/src/app/name-caching-resolver.hpp b/src/app/name-caching-resolver.hpp
index 5f4fe53..d1047d3 100644
--- a/src/app/name-caching-resolver.hpp
+++ b/src/app/name-caching-resolver.hpp
@@ -33,6 +33,7 @@
 #include "response.hpp"
 #include "rr.hpp"
 #include "iterative-query.hpp"
+#include "iterative-query-with-forwarding-hint.hpp"
 #include "ndn-app.hpp"
 
 using namespace std;
@@ -40,45 +41,215 @@
 namespace ndn {
 namespace ndns {
 
-
-class NameCachingResolver : public NDNApp{
-enum ResolverType
+template <class IQStrategy> //IQ stands for iterative Query Strategy
+class NameCachingResolver: public NDNApp
 {
-  StubResolver,
-  CachingResolver
-};
 
 public:
 
-NameCachingResolver(const char *programName, const char *prefix);
+  NameCachingResolver(const char *programName, const char *prefix);
 
+  void
+  resolve(IQStrategy& iq);
 
-void
-resolve(IterativeQuery& iq);
+  using NDNApp::onData;
+  void
+  onData(const Interest& interest, Data &data, IQStrategy& iq);
 
-void
-answerRespNack(IterativeQuery& iq);
+  void
+  onInterest(const Name &name, const Interest &interest);
 
-using NDNApp::onData;
-void
-onData(const Interest& interest, Data &data, IterativeQuery& iq);
+  using NDNApp::onTimeout;
+  void
+  onTimeout(const Interest& interest, IQStrategy& iq);
 
-void
-onInterest(const Name &name, const Interest &interest);
+  void
+  run();
 
-using NDNApp::onTimeout;
+  const Name& getRootZoneFowardingHint() const
+  {
+    return m_rootZoneFowardingHint;
+  }
 
-void
-onTimeout(const Interest& interest, IterativeQuery& iq);
-
-void
-run();
+  void setRootZoneFowardingHint(const Name& rootZoneFowardingHint)
+  {
+    m_rootZoneFowardingHint = rootZoneFowardingHint;
+  }
 
 private:
-  //ResolverType m_resolverType;
+  /**
+   * 0 means disable forwarding hint,
+   * 1 means enable forwarding hint
+   * todo: 2, retrieve name and hint of the name server as a optimization way
+   */
+
+  Name m_rootZoneFowardingHint;
 
 };
 
+
+template <typename IQStrategy>
+NameCachingResolver<IQStrategy>::NameCachingResolver(const char *programName,
+    const char *prefix)
+  : NDNApp(programName, prefix)
+  , m_rootZoneFowardingHint("/")
+{
+  this->setInterestLifetime(time::milliseconds(2000));
+}
+
+template <class IQStrategy> void
+NameCachingResolver<IQStrategy>::run()
+{
+  boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
+  signalSet.async_wait(boost::bind(&NDNApp::signalHandler, this));
+  // boost::bind(&NdnTlvPingServer::signalHandler, this)
+
+  Name name(m_prefix);
+  name.append(Query::toString(Query::QUERY_DNS_R));
+
+  m_face.setInterestFilter(name,
+      bind(&NameCachingResolver::onInterest, this, _1, _2),
+      bind(&NDNApp::onRegisterFailed, this, _1, _2));
+
+  std::cout << "\n=== NDNS Resolver " << m_programName
+      << " with routeble prefix " << name.toUri() << " starts";
+
+  if (this->m_enableForwardingHint > 0) {
+    std::cout<<" & Root Zone ForwardingHint "<<this->m_rootZoneFowardingHint.toUri();
+  }
+  std::cout<<"==="<< std::endl;
+
+  try {
+    m_face.processEvents();
+  } catch (std::exception& e) {
+    std::cerr << "ERROR: " << e.what() << std::endl;
+    m_hasError = true;
+    m_ioService.stop();
+  }
+}
+template <class IQStrategy> void
+NameCachingResolver<IQStrategy>::onData(const Interest& interest, Data &data, IQStrategy& iq)
+{
+  /*
+  if (interest.getName() != iq.getLastInterest().getName()) {
+    std::cout << iq << std::endl;
+    std::cout << "waiting for " << iq.getLastInterest().getName().toUri()
+        << std::endl;
+    std::cout << "coming data " << data.getName().toUri() << std::endl;
+    return;
+  }*/
+
+  iq.doData(data);
+
+  if (iq.getStep() == IterativeQuery::AnswerStub) {
+    Data data = iq.getLastResponse().toData();
+    Name name = iq.getQuery().getAuthorityZone();
+    name.append(Query::toString(iq.getQuery().getQueryType()));
+    name.append(iq.getQuery().getRrLabel());
+    name.append(RR::toString(iq.getQuery().getRrType()));
+    name.appendVersion();
+    data.setName(name);
+    data.setFreshnessPeriod(iq.getLastResponse().getFreshness());
+
+    m_keyChain.sign(data);
+    m_face.put(data);
+    std::cout << "[* <- *] answer Response ("
+        << Response::toString(iq.getLastResponse().getResponseType())
+        << ") to stub:" << std::endl;
+    std::cout << iq.getLastResponse() << std::endl;
+    for (int i = 0; i < 15; i++) {
+      std::cout << "----";
+    }
+    std::cout << std::endl << std::endl;
+
+    //iq.setStep(IterativeQuery::FinishedSuccessfully);
+
+  } else if (iq.getStep() == IterativeQuery::NSQuery) {
+    resolve(iq);
+  } else if (iq.getStep() == IterativeQuery::RRQuery) {
+    resolve(iq);
+  } else if (iq.getStep() == IterativeQuery::Abort) {
+    return;
+  } else if (iq.getStep() == IterativeQuery::FHQuery) {
+    resolve(iq);
+  }
+  else {
+    std::cout << "let me see the current step="
+        << IterativeQuery::toString(iq.getStep()) << std::endl;
+    std::cout << iq;
+    std::cout<<std::endl;
+  }
+
+}
+
+template <class IQStrategy> void
+NameCachingResolver<IQStrategy>::onInterest(const Name &name, const Interest &interest)
+{
+  Query query;
+  query.fromInterest(interest);
+  std::cout << "[* -> *] receive Interest: " << interest.getName().toUri()
+      << std::endl;
+  if (query.getQueryType() == Query::QUERY_DNS) {
+    cout << m_programName << " is not in charge of Query_DNS" << endl;
+  }
+
+  IQStrategy iq(query);
+
+  if (this->m_enableForwardingHint == 0) {
+
+  } else if (this->m_enableForwardingHint > 0) {
+    //std::cout<<"--------------------create a Forwarding Hint"<<std::endl;
+    IterativeQueryWithFowardingHint& iqfh =dynamic_cast<IterativeQueryWithFowardingHint&>(iq);
+    iqfh.setForwardingHint(this->m_rootZoneFowardingHint);
+    iqfh.setLastForwardingHint(this->m_rootZoneFowardingHint);
+  }
+  resolve(iq);
+}
+
+template <class IQStrategy> void
+NameCachingResolver<IQStrategy>::onTimeout(const Interest& interest, IQStrategy& iq)
+{
+  std::cout << "[* !! *] timeout Interest " << interest.getName().toUri()
+      << " timeouts" << std::endl;
+
+  iq.doTimeout();
+}
+
+template <class IQStrategy>
+void NameCachingResolver<IQStrategy>::resolve(IQStrategy& iq)
+{
+
+  Interest interest = iq.toLatestInterest();
+
+  //must be set before express interest,since the call will back call iq
+  //if set after, then the iq in call of onData will return nothing
+  //be very careful here,  as a new guy to c++
+
+  interest.setInterestLifetime(this->getInterestLifetime());
+  iq.setLastInterest(interest);
+  /*
+  if (this->m_enableForwardingHint > 0)
+  {
+    //iq = (IterativeQueryWithFowardingHint)iq;
+    iq = dynamic_cast<IterativeQueryWithFowardingHint>iq;
+  }
+  */
+  std::cout<<"lastInterest="<<iq.getLastInterest()<<std::endl;
+
+  try {
+    m_face.expressInterest(interest,
+        boost::bind(&NameCachingResolver::onData, this, _1, _2, iq),
+        boost::bind(&NameCachingResolver::onTimeout, this, _1,  iq));
+        //boost::bind(&NameCachingResolver::onData, this, _1, _2, ndn::ref(iq)),
+        //boost::bind(&NameCachingResolver::onTimeout, this, _1, iq));
+  } catch (std::exception& e) {
+    std::cerr << "ERROR: " << e.what() << std::endl;
+  }
+
+  std::cout << "[* <- *] send Interest: " << interest.getName().toUri()
+      << std::endl;
+  std::cout << iq << std::endl;
+}
 } /* namespace ndns */
 } /* namespace ndn */
 
diff --git a/src/app/name-dig.cpp b/src/app/name-dig.cpp
index 6e64e31..a95a0d0 100644
--- a/src/app/name-dig.cpp
+++ b/src/app/name-dig.cpp
@@ -22,45 +22,43 @@
 namespace ndns {
 
 NameDig::NameDig(const char *programName, const char *prefix)
-: NDNApp(programName, prefix)
-, m_resolverName(Name("/"))
-, m_dstLabel(Name(prefix)){
+  : NDNApp(programName, prefix)
+  , m_resolverName(Name("/"))
+  , m_dstLabel(Name(prefix))
+  , m_rrType(RR::TXT)
+{
   //prefix in this app is the m_dstLabel
   this->setInterestLifetime(time::milliseconds(10000));
 }
 
-NameDig::~NameDig() {
+NameDig::~NameDig()
+{
   // TODO Auto-generated destructor stub
 }
 
-void
-NameDig::onData(const Interest& interest, Data& data)
+void NameDig::onData(const Interest& interest, Data& data)
 {
   Response re;
   re.fromData(data);
-  cout<<"get data:->"<<data.getName()<<endl;
-  cout<<"get response:->"<<re<<endl;
+  cout << "get data:->" << data.getName() << endl;
+  cout << "get response:->" << re << endl;
 
-
+  response = re;
 
   m_rrs = re.getRrs();
 
-
-
   vector<RR>::iterator iter = m_rrs.begin();
 
-  while (iter != m_rrs.end())
-  {
+  while (iter != m_rrs.end()) {
     RR rr = *iter;
-    cout<<rr<<endl;
-    iter ++;
+    cout << rr << endl;
+    iter++;
   }
 
   this->stop();
 }
 
-void
-NameDig::sendQuery()
+void NameDig::sendQuery()
 {
   Query q;
   q.setAuthorityZone(this->m_resolverName);
@@ -72,46 +70,39 @@
   interest.setInterestLifetime(this->m_interestLifetime);
   try {
     m_face.expressInterest(interest,
-            boost::bind(&NameDig::onData, this, _1, _2),
-            boost::bind(&NameDig::onTimeout, this, _1)
-            );
-    std::cout<<"[* <- *] send Interest: "<<interest.getName().toUri()<<std::endl;
-  }catch(std::exception& e) {
+        boost::bind(&NameDig::onData, this, _1, _2),
+        boost::bind(&NameDig::onTimeout, this, _1));
+    std::cout << "[* <- *] send Interest: " << interest.getName().toUri()
+        << std::endl;
+  } catch (std::exception& e) {
     m_hasError = true;
     m_error = e.what();
   }
   m_interestTriedNum += 1;
 }
 
-void
-NameDig::onTimeout(const Interest& interest)
+void NameDig::onTimeout(const Interest& interest)
 {
-  std::cout<<"[* !! *] timeout Interest"<<interest.getName()<<std::endl;
+  std::cout << "[* !! *] timeout Interest" << interest.getName() << std::endl;
 
-  if (m_interestTriedNum >= m_interestTriedMax)
-  {
+  if (m_interestTriedNum >= m_interestTriedMax) {
     m_error = "All Interests timeout";
     m_hasError = true;
     this->stop();
-  } else
-  {
+  } else {
     sendQuery();
   }
 
 }
 
-void
-NameDig::run()
+void NameDig::run()
 {
 
   this->sendQuery();
 
-  try
-  {
+  try {
     m_face.processEvents();
-  }
-  catch (std::exception& e)
-  {
+  } catch (std::exception& e) {
     m_error = e.what();
     m_hasError = true;
     this->stop();
diff --git a/src/app/name-dig.hpp b/src/app/name-dig.hpp
index 475cf26..3f07a1e 100644
--- a/src/app/name-dig.hpp
+++ b/src/app/name-dig.hpp
@@ -27,7 +27,8 @@
 namespace ndn {
 namespace ndns {
 
-class NameDig: public NDNApp {
+class NameDig: public NDNApp
+{
 public:
   NameDig(const char *programName, const char *prefix);
   virtual ~NameDig();
@@ -35,7 +36,6 @@
   void
   onData(const ndn::Interest& interest, Data& data);
 
-
   void
   onTimeout(const ndn::Interest& interest);
 
@@ -45,45 +45,63 @@
   void
   run();
 
-  const vector<RR>& getRrs() const {
+  const vector<RR>& getRrs() const
+  {
     return m_rrs;
   }
 
-  void setRrs(const vector<RR>& rrs) {
+  void setRrs(const vector<RR>& rrs)
+  {
     m_rrs = rrs;
   }
 
-  const Name& getResolverName() const {
+  const Name& getResolverName() const
+  {
     return m_resolverName;
   }
 
-  void setResolverName(const Name& resolverName) {
+  void setResolverName(const Name& resolverName)
+  {
     m_resolverName = resolverName;
   }
 
-
-
-  const Name& getDstLabel() const {
+  const Name& getDstLabel() const
+  {
     return m_dstLabel;
   }
 
-  void setDstLabel(const Name& dstLabel) {
+  void setDstLabel(const Name& dstLabel)
+  {
     m_dstLabel = dstLabel;
   }
 
-  RR::RRType getRrType() const {
+  RR::RRType getRrType() const
+  {
     return m_rrType;
   }
 
-  void setRrType(RR::RRType rrType) {
+  void setRrType(RR::RRType rrType)
+  {
     m_rrType = rrType;
   }
 
+  const Response& getResponse() const
+  {
+    return response;
+  }
+
+  void setResponse(const Response& response)
+  {
+    this->response = response;
+  }
+
 private:
   Name m_resolverName;
   Name m_dstLabel;
   RR::RRType m_rrType;
   vector<RR> m_rrs;
+
+  Response response;
 };
 
 } /* namespace ndns */
diff --git a/src/app/name-server.cpp b/src/app/name-server.cpp
index 6e6428d..99ceb19 100644
--- a/src/app/name-server.cpp
+++ b/src/app/name-server.cpp
@@ -18,39 +18,38 @@
  */
 #include "name-server.hpp"
 
-
-namespace ndn{
-namespace ndns{
-NameServer::NameServer(const char *programName, const char *prefix, const char *nameZone)
-: NDNApp(programName, prefix)
-, m_zone(Name(nameZone))
-, m_zoneMgr(m_zone)
+namespace ndn {
+namespace ndns {
+NameServer::NameServer(const char *programName, const char *prefix,
+    const char *nameZone, const string dbfile)
+  : NDNApp(programName, prefix)
+  , m_zone(Name(nameZone))
+  , m_zoneMgr(m_zone)
 {
+  m_zoneMgr.setDbfile(dbfile);
   //m_zoneMgr.lookupId();
-}//NameServer Construction
+} //NameServer Construction
 
-
-void
-NameServer::onInterest(const Name &name, const Interest &interest)
+void NameServer::onInterest(const Name &name, const Interest &interest)
 {
 
-  cout<<"[* -> *] receive Interest: "<<interest.getName().toUri()<<std::endl;
+  cout << "[* -> *] receive Interest: " << interest.getName().toUri()
+      << std::endl;
   Query query;
-  if (!query.fromInterest(interest))
-  {
-    cout<<"can resolve the Query from Interest: "<<endl;
+  if (!query.fromInterest(interest)) {
+    cout << "can resolve the Query from Interest: " << endl;
     return;
   }
 
   /*
    * query.getAuthorityZone is routable name, not the zone's service name
-  if (query.getAuthorityZone() != m_zoneMgr.getZone().getAuthorizedName())
-  {
-    cout<<"Query is intent to zone: "<<query.getAuthorityZone()
-        <<". This is "<<m_zoneMgr.getZone().getAuthorizedName()<<endl;
-    return;
-  }
-  */
+   if (query.getAuthorityZone() != m_zoneMgr.getZone().getAuthorizedName())
+   {
+   cout<<"Query is intent to zone: "<<query.getAuthorityZone()
+   <<". This is "<<m_zoneMgr.getZone().getAuthorizedName()<<endl;
+   return;
+   }
+   */
 
   Response response;
   Name name2 = interest.getName();
@@ -58,28 +57,23 @@
   response.setQueryName(name2);
   RRMgr mgr(m_zone, query, response);
 
-
-  if (mgr.lookup()<0)
-  {
-    cout<<"[* !! *] lookup error, then exit: "<<mgr.getErr()<<endl;
+  if (mgr.lookup() < 0) {
+    cout << "[* !! *] lookup error, then exit: " << mgr.getErr() << endl;
     return;
   }
 
-  if (response.getRrs().size() >0)
-  {
+  if (response.getRrs().size() > 0) {
     response.setResponseType(Response::NDNS_Resp);
   } else {
 
     if (query.getRrType() == RR::NS) {
       int count = mgr.count();
-      if (count < 0)
-      {
-        cout<<"[* !! *] lookup error, then exit: "<<mgr.getErr()<<endl;
+      if (count < 0) {
+        cout << "[* !! *] lookup error, then exit: " << mgr.getErr() << endl;
         return;
-      } else if (count > 0)
-      {
+      } else if (count > 0) {
         response.setResponseType(Response::NDNS_Auth);
-      } else{
+      } else {
         response.setResponseType(Response::NDNS_Nack);
       }
     } else {
@@ -87,56 +81,63 @@
     }
   }
 
-
   Data data = response.toData();
   data.setFreshnessPeriod(response.getFreshness());
 
   m_keyChain.sign(data);
   m_face.put(data);
-  cout<<"[* <- *] send response: "<<response<<": "<<data<<endl;
-}//onInterest
+  cout << "[* <- *] send response: " << response << ": " << data << endl;
+} //onInterest
 
-
-void
-NameServer::run()
+void NameServer::run()
 {
   //m_zoneMgr.lookupId();
-  if (m_zoneMgr.getZone().getId() == 0)
-  {
+  if (m_zoneMgr.getZone().getId() == 0) {
     m_hasError = true;
-    m_error = "cannot get Zone.id from database for name="+m_zone.getAuthorizedName().toUri();
+    m_error = "cannot get Zone.id from database for name="
+        + m_zone.getAuthorizedName().toUri();
     stop();
   }
 
   boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
   signalSet.async_wait(boost::bind(&NDNApp::signalHandler, this));
- // boost::bind(&NdnTlvPingServer::signalHandler, this)
+  // boost::bind(&NdnTlvPingServer::signalHandler, this)
   Name name;
   name.set(m_prefix);
   name.append(Query::toString(Query::QUERY_DNS));
 
-  m_face.setInterestFilter(name,
-               bind(&NameServer::onInterest,
-                  this, _1, _2),
-               bind(&NDNApp::onRegisterFailed,
-                  this, _1,_2));
+  std::cout<<"========= NDNS Name Server for Zone "
+            <<m_zoneMgr.getZone().getAuthorizedName().toUri()
+            <<" Starts with Prefix "<<m_prefix;
+  if (m_enableForwardingHint > 0) {
+    std::cout<<" & ForwardingHint "<<m_forwardingHint.toUri();
+  }
+    std::cout<<"============="<<std::endl;
 
-  std::cout << "\n=== NDNS Server for Zone "
-            << m_zoneMgr.getZone().getAuthorizedName().toUri()
-            <<" with routable prefix "<< name.toUri()
-            << " starts===\n" << std::endl;
+  m_face.setInterestFilter(name, bind(&NameServer::onInterest, this, _1, _2),
+      bind(&NDNApp::onRegisterFailed, this, _1, _2));
+ std::cout<<"Name Server Register Name Prefix: "<<name<<std::endl;
+
+  if (m_enableForwardingHint > 0) {
+    Name name2 = Name(m_forwardingHint);
+    name2.append(ndn::ndns::label::ForwardingHintLabel);
+    name2.append(name);
+    m_face.setInterestFilter(name2, bind(&NameServer::onInterest, this, _1, _2),
+        bind(&NDNApp::onRegisterFailed, this, _1, _2));
+    std::cout<<"Name Server Register Name Prefix: "<<name2<<std::endl;
+  }
+
 
   try {
     m_face.processEvents();
-  }
-  catch (std::exception& e) {
+  } catch (std::exception& e) {
     m_hasError = true;
     m_error = "ERROR: ";
     m_error += e.what();
     stop();
   }
 
-}//run
+} //run
 
 } //namespace ndns
 } /* namespace ndn */
diff --git a/src/app/name-server.hpp b/src/app/name-server.hpp
index 9d6f5cd..5c2f109 100644
--- a/src/app/name-server.hpp
+++ b/src/app/name-server.hpp
@@ -38,29 +38,28 @@
 using namespace std;
 using namespace ndn;
 
-
-namespace ndn{
-namespace ndns{
-class NameServer : public NDNApp
+namespace ndn {
+namespace ndns {
+class NameServer: public NDNApp
 {
 
 public:
-explicit
-NameServer(const char *programName, const char *prefix, const char *nameZone);
+  explicit
+  NameServer(const char *programName, const char *prefix, const char *nameZone,
+      const string dbfile = "src/db/ndns-local.db");
 
-void
-onInterest(const Name &name, const Interest &interest);
+  void
+  onInterest(const Name &name, const Interest &interest);
 
-
-void
-run();
+  void
+  run();
 
 public:
   /*
    * the name used by the server to provide routeable accessory.
 
-  Name m_name;
-  */
+   Name m_name;
+   */
   /*
    * the zone the server is in charge of
    */
@@ -71,7 +70,8 @@
    */
   ZoneMgr m_zoneMgr;
 
-};//clcass NameServer
+};
+//clcass NameServer
 }//namespace ndns
-}//namespace ndn
+} //namespace ndn
 #endif /* NAME_SERVER_HPP_ */
diff --git a/src/app/ndn-app.cpp b/src/app/ndn-app.cpp
index b8f123a..f7804f2 100644
--- a/src/app/ndn-app.cpp
+++ b/src/app/ndn-app.cpp
@@ -30,6 +30,8 @@
   , m_interestTriedMax(2)
   , m_interestTriedNum(0)
   , m_face(m_ioService)
+  , m_enableForwardingHint(0)
+  , m_forwardingHint("/")
 {
 }
 
@@ -39,9 +41,5 @@
   m_prefix = 0;
 }
 
-
-
-
-
 } //namespace ndns
 } /* namespace ndn */
diff --git a/src/app/ndn-app.hpp b/src/app/ndn-app.hpp
index 00595ea..13130e2 100644
--- a/src/app/ndn-app.hpp
+++ b/src/app/ndn-app.hpp
@@ -28,28 +28,29 @@
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/noncopyable.hpp>
 
+#include "ndns-label.hpp"
+
 using namespace std;
 
 namespace ndn {
-namespace ndns{
+namespace ndns {
 
-class NDNApp {
+class NDNApp
+{
 public:
   NDNApp(const char *programName, const char *prefix);
   virtual ~NDNApp();
 
-  virtual void
-  onData(const ndn::Interest& interest, Data& data)
+  virtual void onData(const ndn::Interest& interest, Data& data)
   {
   }
-  virtual void
-  onTimeout(const ndn::Interest& interest)
+  virtual void onTimeout(const ndn::Interest& interest)
   {
-    std::cout<<"!- Interest Timeout"<<interest.getName()<<std::endl;
+    std::cout << "!- Interest Timeout" << interest.getName() << std::endl;
   }
 
-  virtual void
-  onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
+  virtual void onRegisterFailed(const ndn::Name& prefix,
+      const std::string& reason)
   {
     m_error = "ERROR: Failed to register prefix in local hub's daemon";
     m_error += " due to: ";
@@ -58,95 +59,120 @@
     this->stop();
   }
 
-
-  virtual void
-  onInterest(const Name &name, const Interest& interest)
+  virtual void onInterest(const Name &name, const Interest& interest)
   {
 
   }
 
-  virtual void
-  signalHandler()
+  virtual void signalHandler()
   {
     this->stop();
     exit(1);
   }
 
-
-  virtual void
-  stop()
+  virtual void stop()
   {
-    std::cout<<m_programName<<" stops"<<std::endl;
+    std::cout << m_programName << " stops" << std::endl;
     m_ioService.stop();
     m_face.shutdown();
-    if (hasError())
-    {
-      cout<<m_error<<endl;
+    if (hasError()) {
+      cout << m_error << endl;
     }
   }
 
-
-
-  bool hasError() const {
+  bool hasError() const
+  {
     return m_hasError;
   }
 
-  void setHasError(bool hasError) {
+  void setHasError(bool hasError)
+  {
     m_hasError = hasError;
   }
 
-  const char* getPrefix() const {
+  const char* getPrefix() const
+  {
     return m_prefix;
   }
 
-  void setPrefix(char* prefix) {
+  void setPrefix(char* prefix)
+  {
     m_prefix = prefix;
   }
 
-  const char* getProgramName() const {
+  const char* getProgramName() const
+  {
     return m_programName;
   }
 
-  void setProgramName(char* programName) {
+  void setProgramName(char* programName)
+  {
     m_programName = programName;
   }
 
-  const string& getErr() const {
+  const string& getErr() const
+  {
     return m_error;
   }
 
-  void setErr(const string& err) {
+  void setErr(const string& err)
+  {
     m_error = err;
   }
 
-  uint32_t getInterestTriedMax() const {
+  uint32_t getInterestTriedMax() const
+  {
     return m_interestTriedMax;
   }
 
-  void setInterestTriedMax(uint32_t interestTriedMax) {
+  void setInterestTriedMax(uint32_t interestTriedMax)
+  {
     m_interestTriedMax = interestTriedMax;
   }
 
-  time::milliseconds getContentFreshness() const {
+  time::milliseconds getContentFreshness() const
+  {
     return m_contentFreshness;
   }
 
-  void setContentFreshness(time::milliseconds contentFreshness) {
+  void setContentFreshness(time::milliseconds contentFreshness)
+  {
     m_contentFreshness = contentFreshness;
   }
 
-  time::milliseconds getInterestLifetime() const {
+  time::milliseconds getInterestLifetime() const
+  {
     return m_interestLifetime;
   }
 
-  void setInterestLifetime(time::milliseconds interestLifetime) {
+  void setInterestLifetime(time::milliseconds interestLifetime)
+  {
     m_interestLifetime = interestLifetime;
   }
 
-public:
+  const Name& getForwardingHint() const
+  {
+    return m_forwardingHint;
+  }
+
+  void setForwardingHint(const Name& forwardingHint)
+  {
+    m_forwardingHint = forwardingHint;
+  }
+
+  unsigned short getEnableForwardingHint() const
+  {
+    return m_enableForwardingHint;
+  }
+
+  void setEnableForwardingHint(unsigned short enableForwardingHint)
+  {
+    m_enableForwardingHint = enableForwardingHint;
+  }
+
+protected:
   const char* m_programName;
-  const char* m_prefix;
-  bool m_hasError;
+  const char* m_prefix;bool m_hasError;
   string m_error;
   time::milliseconds m_contentFreshness;
   time::milliseconds m_interestLifetime;
@@ -159,9 +185,14 @@
   //Zone m_zone;
   //ZoneMgr m_zoneMgr;
 
-
   Face m_face;
   KeyChain m_keyChain;
+
+  /**
+   * forwarding hint
+   */
+  unsigned short m_enableForwardingHint;
+  Name m_forwardingHint;
 };
 
 } //namespace ndns