TLV encoding to replace JSON format message
diff --git a/src/ca-module.cpp b/src/ca-module.cpp
index be44e11..275e1f8 100644
--- a/src/ca-module.cpp
+++ b/src/ca-module.cpp
@@ -22,7 +22,10 @@
 #include "challenge-module.hpp"
 #include "logging.hpp"
 #include "crypto-support/enc-tlv.hpp"
-#include "tlv.hpp"
+#include "protocol-detail/info.hpp"
+#include "protocol-detail/probe.hpp"
+#include "protocol-detail/new.hpp"
+#include "protocol-detail/challenge.hpp"
 #include <ndn-cxx/util/io.hpp>
 #include <ndn-cxx/security/verification-helpers.hpp>
 #include <ndn-cxx/security/signing-helpers.hpp>
@@ -120,7 +123,11 @@
 CaModule::onInfo(const Interest& request)
 {
   _LOG_TRACE("Received INFO request");
-  Block contentTLV = genInfoResponseTLV();
+
+  const auto& pib = m_keyChain.getPib();
+  const auto& identity = pib.getIdentity(m_config.m_caName);
+  const auto& cert = identity.getDefaultKey().getDefaultCertificate();
+  Block contentTLV = INFO::encodeContentFromCAConfig(m_config, cert);
   Data result;
 
   result.setName(request.getName());
@@ -138,19 +145,19 @@
 {
   // PROBE Naming Convention: /<CA-Prefix>/CA/PROBE/[ParametersSha256DigestComponent]
   _LOG_TRACE("Received PROBE request");
-  JsonSection contentJson;
 
   // process PROBE requests: find an available name
   std::string availableId;
-  const auto& parameterJson = jsonFromBlock(request.getApplicationParameters());
-  if (parameterJson.empty()) {
-    _LOG_ERROR("Empty JSON obtained from the Interest parameter.");
+  const auto& parameterTLV = request.getApplicationParameters();
+  if (!parameterTLV.hasValue()) {
+    _LOG_ERROR("Empty TLV obtained from the Interest parameter.");
     return;
   }
   //std::string probeInfoStr = parameterJson.get(JSON_CLIENT_PROBE_INFO, "");
+  // TODO: m_probeHandler is never set
   if (m_config.m_probeHandler) {
     try {
-      availableId = m_config.m_probeHandler(parameterJson);
+      availableId = m_config.m_probeHandler(parameterTLV);
     }
     catch (const std::exception& e) {
       _LOG_TRACE("Cannot find PROBE input from PROBE parameters: " << e.what());
@@ -164,11 +171,11 @@
   Name newIdentityName = m_config.m_caName;
   newIdentityName.append(availableId);
   _LOG_TRACE("Handle PROBE: generate an identity " << newIdentityName);
-  contentJson = genProbeResponseJson(newIdentityName.toUri(), m_config.m_probe, parameterJson);
+  Block contentTLV = PROBE::encodeDataContent(newIdentityName.toUri(), m_config.m_probe, parameterTLV);
 
   Data result;
   result.setName(request.getName());
-  result.setContent(dataContentFromJson(contentJson));
+  result.setContent(contentTLV);
   result.setFreshnessPeriod(DEFAULT_DATA_FRESHNESS_PERIOD);
   m_keyChain.sign(result, signingByIdentity(m_config.m_caName));
   m_face.put(result);
@@ -180,14 +187,16 @@
 {
   // NEW Naming Convention: /<CA-prefix>/CA/NEW/[SignedInterestParameters_Digest]
   // get ECDH pub key and cert request
-  const auto& parameterJson = jsonFromBlock(request.getApplicationParameters());
-  if (parameterJson.empty()) {
-    _LOG_ERROR("Empty JSON obtained from the Interest parameter.");
+  const auto& parameterTLV = request.getApplicationParameters();
+  if (!parameterTLV.hasValue()) {
+    _LOG_ERROR("Empty TLV obtained from the Interest parameter.");
     return;
   }
-  std::string peerKeyBase64 = parameterJson.get(JSON_CLIENT_ECDH, "");
+
+  std::string peerKeyBase64 = readString(parameterTLV.get(tlv_ecdh_pub));
+
   if (peerKeyBase64 == "") {
-    _LOG_ERROR("Empty JSON_CLIENT_ECDH obtained from the Interest parameter.");
+    _LOG_ERROR("Empty ECDH PUB obtained from the Interest parameter.");
     return;
   }
 
@@ -207,11 +216,10 @@
        (uint8_t*)&saltInt, sizeof(saltInt), m_aesKey, sizeof(m_aesKey));
 
   // parse certificate request
-  std::string certRequestStr = parameterJson.get(JSON_CLIENT_CERT_REQ, "");
+  Block cert_req = parameterTLV.get(tlv_cert_request);
   shared_ptr<security::v2::Certificate> clientCert = nullptr;
   try {
-    std::stringstream ss(certRequestStr);
-    clientCert = io::load<security::v2::Certificate>(ss);
+    clientCert->wireDecode(cert_req);
   }
   catch (const std::exception& e) {
     _LOG_ERROR("Unrecognized certificate request: " << e.what());
@@ -230,34 +238,6 @@
     return;
   }
 
-  // parse probe token if any
-  std::string probeTokenStr = parameterJson.get("probe-token", "");
-  shared_ptr<Data> probeToken = nullptr;
-  if (probeTokenStr != "") {
-    try {
-      std::stringstream ss(probeTokenStr);
-      probeToken = io::load<Data>(ss);
-    }
-    catch (const std::exception& e) {
-      _LOG_ERROR("Unrecognized probe token: " << e.what());
-      return;
-    }
-  }
-  if (probeToken == nullptr && m_config.m_probe != "") {
-    // the CA requires PROBE before NEW
-    _LOG_ERROR("CA requires PROBE but no PROBE token is found in NEW Interest.");
-    return;
-  }
-  else if (probeToken != nullptr) {
-    // check whether the carried probe token is a PROBE Data packet
-    Name prefix = m_config.m_caName;
-    prefix.append("CA").append("PROBE");
-    if (!prefix.isPrefixOf(probeToken->getName())) {
-      _LOG_ERROR("Carried PROBE token is not a valid PROBE Data packet.");
-      return;
-    }
-  }
-
   // verify the self-signed certificate, the request, and the token
   if (!m_config.m_caName.isPrefixOf(clientCert->getName()) // under ca prefix
       || !security::v2::Certificate::isValidName(clientCert->getName()) // is valid cert name
@@ -273,22 +253,11 @@
     _LOG_ERROR("Interest with bad signature.");
     return;
   }
-  if (probeToken != nullptr) {
-    const auto& pib = m_keyChain.getPib();
-    const auto& key = pib.getIdentity(m_config.m_caName).getDefaultKey();
-    const auto& caCert = key.getDefaultCertificate();
-    if (!security::verifySignature(*probeToken, caCert)) {
-      _LOG_ERROR("PROBE Token with bad signature.");
-      return;
-    }
-  }
 
   // create new request instance
   std::string requestId = std::to_string(random::generateWord64());
   CertificateRequest certRequest(m_config.m_caName, requestId, STATUS_BEFORE_CHALLENGE, *clientCert);
-  if (probeToken != nullptr) {
-    certRequest.setProbeToken(probeToken);
-  }
+
   try {
     m_storage->addRequest(certRequest);
   }
@@ -300,10 +269,10 @@
   Data result;
   result.setName(request.getName());
   result.setFreshnessPeriod(DEFAULT_DATA_FRESHNESS_PERIOD);
-  result.setContent(dataContentFromJson(genNewResponseJson(myEcdhPubKeyBase64,
-                                                           std::to_string(saltInt),
-                                                           certRequest,
-                                                           m_config.m_supportedChallenges)));
+  result.setContent(NEW::encodeDataContent(myEcdhPubKeyBase64,
+                                      std::to_string(saltInt),
+                                      certRequest,
+                                      m_config.m_supportedChallenges));
   m_keyChain.sign(result, signingByIdentity(m_config.m_caName));
   m_face.put(result);
 
@@ -328,48 +297,45 @@
     return;
   }
   // decrypt the parameters
-  Buffer paramJsonPayload;
+  Buffer paramTLVPayload;
   try {
-    paramJsonPayload = decodeBlockWithAesGcm128(request.getApplicationParameters(), m_aesKey,
+    paramTLVPayload = decodeBlockWithAesGcm128(request.getApplicationParameters(), m_aesKey,
                                                 (uint8_t*)"test", strlen("test"));
   }
   catch (const std::exception& e) {
     _LOG_ERROR("Cannot successfully decrypt the Interest parameters: " << e.what());
     return;
   }
-  if (paramJsonPayload.size() == 0) {
+  if (paramTLVPayload.size() == 0) {
     _LOG_ERROR("Got an empty buffer from content decryption.");
     return;
   }
-  std::string paramJsonStr((const char*)paramJsonPayload.data(), paramJsonPayload.size());
-  std::istringstream ss(paramJsonStr);
-  JsonSection paramJson;
-  try {
-    boost::property_tree::json_parser::read_json(ss, paramJson);
-  }
-  catch (const std::exception& e) {
-    _LOG_ERROR("Cannot read JSON from decrypted content: " << e.what());
-    return;
-  }
+
+  // TODO: any simpler method?
+  bool isSucess;
+  Block paramTLV;
+  std::tie<bool, Block>(isSucess, paramTLV) =  Block::fromBuffer(paramTLVPayload.data(), paramTLVPayload.size());
 
   // load the corresponding challenge module
-  std::string challengeType = paramJson.get(JSON_CLIENT_SELECTED_CHALLENGE, "");
+  std::string challengeType = readString(paramTLV.get(tlv_selected_challenge));
   auto challenge = ChallengeModule::createChallengeModule(challengeType);
-  JsonSection contentJson;
+
+  Block contentTLV;
+
   if (challenge == nullptr) {
     _LOG_TRACE("Unrecognized challenge type " << challengeType);
     certRequest.m_status = STATUS_FAILURE;
     certRequest.m_challengeStatus = CHALLENGE_STATUS_UNKNOWN_CHALLENGE;
-    contentJson = genChallengeResponseJson(certRequest);
+    contentTLV = CHALLENGE::encodeDataPayload(certRequest);
   }
   else {
     _LOG_TRACE("CHALLENGE module to be load: " << challengeType);
     // let challenge module handle the request
-    challenge->handleChallengeRequest(paramJson, certRequest);
+    challenge->handleChallengeRequest(paramTLV, certRequest);
     if (certRequest.m_status == STATUS_FAILURE) {
       // if challenge failed
       m_storage->deleteRequest(certRequest.m_requestId);
-      contentJson = genChallengeResponseJson(certRequest);
+      contentTLV = CHALLENGE::encodeDataPayload(certRequest);
       _LOG_TRACE("Challenge failed");
     }
     else if (certRequest.m_status == STATUS_PENDING) {
@@ -389,9 +355,12 @@
       if (m_config.m_statusUpdateCallback) {
         m_config.m_statusUpdateCallback(certRequest);
       }
-      contentJson = genChallengeResponseJson(certRequest);
-      contentJson.add(JSON_CA_CERT_ID, readString(issuedCert.getName().at(-1)));
-      contentJson.add(JSON_CHALLENGE_ISSUED_CERT_NAME, issuedCert.getName().toUri());
+
+      contentTLV = CHALLENGE::encodeDataPayload(certRequest);
+      contentTLV.push_back(makeNestedBlock(tlv_issued_cert_name, issuedCert.getName()));
+      contentTLV.parse();
+
+      //contentJson.add(JSON_CA_CERT_ID, readString(issuedCert.getName().at(-1)));
       _LOG_TRACE("Challenge succeeded. Certificate has been issued");
     }
     else {
@@ -402,7 +371,7 @@
         _LOG_TRACE("Cannot update request instance: " << e.what());
         return;
       }
-      contentJson = genChallengeResponseJson(certRequest);
+      contentTLV = CHALLENGE::encodeDataPayload(certRequest);
       _LOG_TRACE("No failure no success. Challenge moves on");
     }
   }
@@ -412,11 +381,9 @@
   result.setFreshnessPeriod(DEFAULT_DATA_FRESHNESS_PERIOD);
 
   // encrypt the content
-  std::stringstream ss2;
-  boost::property_tree::write_json(ss2, contentJson);
-  auto payload = ss2.str();
-  auto contentBlock = encodeBlockWithAesGcm128(tlv::Content, m_aesKey, (const uint8_t*)payload.c_str(),
-                                               payload.size(), (uint8_t*)"test", strlen("test"));
+  auto payload = contentTLV.getBuffer();
+  auto contentBlock = encodeBlockWithAesGcm128(tlv::Content, m_aesKey, payload->data(),
+                                               payload->size(), (uint8_t*)"test", strlen("test"));
   result.setContent(contentBlock);
   m_keyChain.sign(result, signingByIdentity(m_config.m_caName));
   m_face.put(result);
@@ -552,46 +519,6 @@
   return root;
 }
 
-Block
-CaModule::genInfoResponseTLV()
-{
-  Block response;
-  // ca-prefix
-  Name caName = m_config.m_caName;
-  // response = makeStringBlock(CAPrefix, caName.toUri());
-  response = makeNestedBlock(CAPrefix, caName);
-
-  // ca-info
-  const auto& pib = m_keyChain.getPib();
-  const auto& identity = pib.getIdentity(m_config.m_caName);
-  const auto& cert = identity.getDefaultKey().getDefaultCertificate();
-  std::string caInfo = "";
-  if (m_config.m_caInfo == "") {
-    caInfo = "Issued by " + cert.getSignature().getKeyLocator().getName().toUri();
-  }
-  else {
-    caInfo = m_config.m_caInfo;
-  }
-
-  response.push_back(makeStringBlock(CAInfo, caInfo));
-
-
-  // parameter-key (Not implemented yet)
-  for() {
-    response.push_back(makeStringBlock(ParameterKey, ""));
-  }
-
-  // TODO: need to convert from days to seconds
-  response.push_back(makeNonNegativeIntegerBlock(MaxValidityPeriod, m_validityPeriod));
-
-  // certificate
-  response.push_back(makeNestedBlock(CACertificate, cert));
-  response.parse();
-
-  return response;
-}
-
-
 JsonSection
 CaModule::genNewResponseJson(const std::string& ecdhKey, const std::string& salt,
                              const CertificateRequest& request,