diff --git a/src/clients/response.cpp b/src/clients/response.cpp
new file mode 100644
index 0000000..8aba4ba
--- /dev/null
+++ b/src/clients/response.cpp
@@ -0,0 +1,237 @@
+/* -*- 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 "response.hpp"
+#include "logger.hpp"
+
+namespace ndn {
+namespace ndns {
+
+Response::Response()
+  : m_ndnsType(NDNS_RAW)
+  , m_freshnessPeriod(DEFAULT_RR_FRESHNESS_PERIOD)
+  , m_appContent(dataBlock(ndn::tlv::Content, reinterpret_cast<const uint8_t*>(0), 0))
+{
+}
+
+Response::Response(const Name& zone, const name::Component& queryType)
+  : m_zone(zone)
+  , m_queryType(queryType)
+  , m_ndnsType(NDNS_RAW)
+  , m_freshnessPeriod(DEFAULT_RR_FRESHNESS_PERIOD)
+  , m_appContent(dataBlock(ndn::tlv::Content, reinterpret_cast<const uint8_t*>(0), 0))
+{
+}
+
+template<bool T>
+inline size_t
+Response::wireEncode(EncodingImpl<T>& block) const
+{
+  if (m_ndnsType == NDNS_RAW) {
+    // Raw application content
+    return prependBlock(block, m_appContent);
+  }
+
+  // Content :: = CONTENT-TYPE TLV-LENGTH
+  //              Block*
+
+  size_t totalLength = 0;
+  for (std::vector<Block>::const_reverse_iterator iter = m_rrs.rbegin();
+       iter != m_rrs.rend(); ++iter) {
+    totalLength += prependBlock(block, *iter);
+  }
+
+  totalLength += block.prependVarNumber(totalLength);
+  totalLength += block.prependVarNumber(::ndn::tlv::Content);
+
+  return totalLength;
+}
+
+const Block
+Response::wireEncode() const
+{
+  if (m_ndnsType == NDNS_RAW) {
+    return m_appContent;
+  }
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+  return buffer.block();
+}
+
+void
+Response::wireDecode(const Block& wire)
+{
+  if (m_ndnsType == NDNS_RAW) {
+    m_appContent = wire;
+    return;
+  }
+
+  wire.parse();
+
+  Block::element_const_iterator iter = wire.elements().begin();
+  for (; iter != wire.elements().end(); ++iter) {
+    m_rrs.push_back(*iter);
+  }
+}
+
+bool
+Response::fromData(const Name& hint, const Name& zone, const Data& data)
+{
+  label::MatchResult re;
+  if (!matchName(data, hint, zone, re))
+    return false;
+
+  m_rrLabel = re.rrLabel;
+  m_rrType = re.rrType;
+  m_version = re.version;
+
+  m_zone = zone;
+  size_t len = zone.size();
+  if (!hint.empty())
+    len += hint.size() + 1;
+  m_queryType = data.getName().get(len);
+
+  MetaInfo info = data.getMetaInfo();
+
+  m_freshnessPeriod = time::duration_cast<time::seconds>(info.getFreshnessPeriod());
+  const Block* block = info.findAppMetaInfo(tlv::NdnsType);
+  if (block != 0)
+    m_ndnsType = static_cast<NdnsType>(readNonNegativeInteger(*block));
+
+  wireDecode(data.getContent());
+  return true;
+}
+
+
+shared_ptr<Data>
+Response::toData()
+{
+  Name name;
+  name.append(m_zone)
+      .append(m_queryType)
+      .append(m_rrLabel)
+      .append(m_rrType);
+
+  if (m_version.empty()) {
+    name.appendVersion();
+    m_version = name.get(-1);
+  }
+  else {
+    name.append(m_version);
+  }
+
+  shared_ptr<Data> data = make_shared<Data>(name);
+
+  MetaInfo info;
+  info.setFreshnessPeriod(m_freshnessPeriod);
+
+  if (m_ndnsType != NDNS_RAW) {
+    info.addAppMetaInfo(nonNegativeIntegerBlock(ndns::tlv::NdnsType, m_ndnsType));
+    data->setContent(this->wireEncode());
+  }
+  else {
+    data->setContent(m_appContent);
+  }
+  data->setMetaInfo(info);
+
+  return data;
+}
+
+
+Response&
+Response::addRr(const Block& rr)
+{
+  this->m_rrs.push_back(rr);
+  return *this;
+}
+
+Response&
+Response::addRr(const std::string& rr)
+{
+  return this->addRr(dataBlock(ndns::tlv::RrData, rr.c_str(), rr.size()));
+}
+
+bool
+Response::removeRr(const Block& rr)
+{
+  for (std::vector<Block>::iterator iter = m_rrs.begin(); iter != m_rrs.end(); ++iter) {
+    if (*iter == rr) {
+      m_rrs.erase(iter);
+      return true;
+    }
+  }
+  return false;
+}
+
+void
+Response::setAppContent(const Block& block)
+{
+  if (block.type() != ndn::tlv::Content) {
+    m_appContent = Block(ndn::tlv::Content, block);
+  } else
+    m_appContent = block;
+
+  m_appContent.encode(); // this is a must
+}
+
+
+bool
+Response::operator==(const Response& other) const
+{
+  bool tmp = (getZone() == other.getZone() &&
+              getQueryType() == other.getQueryType() && getRrLabel() == other.getRrLabel() &&
+              getRrType() == other.getRrType() && getVersion() == other.getVersion() &&
+              getNdnsType() == other.getNdnsType());
+
+  if (tmp == false)
+    return tmp;
+
+  if (m_ndnsType == NDNS_RAW) {
+    return tmp && (getAppContent() == other.getAppContent());
+  }
+  else
+    return tmp && getRrs() == other.getRrs();
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Response& response)
+{
+  os << "Response: zone=" << response.getZone()
+     << " queryType=" << response.getQueryType()
+     << " rrLabel=" << response.getRrLabel()
+     << " rrType=" << response.getRrType()
+     << " version=" << response.getVersion()
+     << " freshnessPeriod=" << response.getFreshnessPeriod()
+     << " ndnsType=" << response.getNdnsType();
+  if (response.getNdnsType() == NDNS_RAW) {
+    if (response.getAppContent().empty())
+      os << " appContent=NULL";
+    else
+      os << " appContentSize=" << response.getAppContent().size();
+  }
+  else {
+    os << " rrs.size=" << response.getRrs().size();
+  }
+  return os;
+}
+} // namespace ndns
+} // namespace ndn
