node+face-management-protocol: Adding StatusResponse to the Tlv::FaceManagement

Change-Id: I23b2478e3b27cf7fb8b263704c1835d70d3b606d
diff --git a/include/ndn-cpp/node.hpp b/include/ndn-cpp/node.hpp
index 3c43480..b880c06 100644
--- a/include/ndn-cpp/node.hpp
+++ b/include/ndn-cpp/node.hpp
@@ -265,6 +265,18 @@
     (uint64_t registeredPrefixId, const ptr_lib::shared_ptr<const Name>& prefix, const OnInterest& onInterest, 
      const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags);
 
+  /**
+   * @brief Final stage of prefix registration, invoked when registration succeeded
+   *
+   * This method actually sets entry in a local interest filter table
+   */
+  void
+  registerPrefixFinal(uint64_t registeredPrefixId,
+                      const ptr_lib::shared_ptr<const Name>& prefix,
+                      const OnInterest& onInterest,
+                      const OnRegisterFailed& onRegisterFailed,
+                      const ptr_lib::shared_ptr<const Interest>&, const ptr_lib::shared_ptr<Data>&);
+  
   void
   checkPitExpire();
   
diff --git a/include/ndn-cpp/status-response.hpp b/include/ndn-cpp/status-response.hpp
new file mode 100644
index 0000000..a222951
--- /dev/null
+++ b/include/ndn-cpp/status-response.hpp
@@ -0,0 +1,124 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_STATUS_RESPONSE_HPP
+#define NDN_STATUS_RESPONSE_HPP
+
+#include "encoding/block.hpp"
+#include "encoding/tlv-face-management.hpp"
+
+namespace ndn {
+
+class StatusResponse {
+public:
+  StatusResponse()
+    : code_(0)
+  {
+  }
+
+  StatusResponse(uint32_t code, const std::string &info)
+    : code_(code)
+    , info_(info)
+  {
+  }
+  
+  inline uint32_t
+  getCode() const;
+
+  inline void
+  setCode(uint32_t code);
+
+  inline const std::string &
+  getInfo() const;
+
+  inline void
+  setInfo(const std::string &info);
+
+  inline const Block&
+  wireEncode() const;
+
+  inline void
+  wireDecode(const Block &block);
+  
+private:
+  uint32_t code_;
+  std::string info_;
+
+  mutable Block wire_;
+};
+
+inline uint32_t
+StatusResponse::getCode() const
+{
+  return code_;
+}
+
+inline void
+StatusResponse::setCode(uint32_t code)
+{
+  code_ = code;
+  wire_.reset();
+}
+
+inline const std::string &
+StatusResponse::getInfo() const
+{
+  return info_;
+}
+
+inline void
+StatusResponse::setInfo(const std::string &info)
+{
+  info_ = info;
+  wire_.reset();
+}
+
+
+inline const Block&
+StatusResponse::wireEncode() const
+{
+  if (wire_.hasWire())
+    return wire_;
+
+  wire_ = Block(Tlv::FaceManagement::StatusResponse);
+  wire_.push_back
+    (nonNegativeIntegerBlock(Tlv::FaceManagement::StatusCode, code_));
+
+  if (!info_.empty())
+    {
+      wire_.push_back
+        (dataBlock(Tlv::FaceManagement::StatusText, info_.c_str(), info_.size()));
+    }
+  
+  wire_.encode();  
+  return wire_;
+}
+
+inline void
+StatusResponse::wireDecode(const Block &wire)
+{
+  wire_ = wire;
+  wire_.parse();
+
+  code_ = readNonNegativeInteger(wire_.get(Tlv::FaceManagement::StatusCode));
+
+  Block::element_iterator val = wire_.find(Tlv::FaceManagement::StatusText);
+  if (val != wire_.getAll().end())
+    {
+      info_.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+    }
+}
+
+inline std::ostream&
+operator << (std::ostream &os, const StatusResponse &status)
+{
+  os << status.getCode() << " " << status.getInfo();
+  return os;
+}
+
+}
+
+#endif // NDN_STATUS_RESPONSE_HPP
diff --git a/src/node.cpp b/src/node.cpp
index 3276e62..b766718 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -14,6 +14,8 @@
 #include "util/ndnd-id-fetcher.hpp"
 #include "security/signature/signature-sha256-with-rsa.hpp"
 
+#include "status-response.hpp"
+
 using namespace std;
 
 namespace ndn {
@@ -119,20 +121,73 @@
 
   // Create an interest where the name has the encoded Data packet.
   Name interestName;
-  const uint8_t component0[] = "ndnx";
-  const uint8_t component2[] = "selfreg";
-  interestName.append(component0, sizeof(component0) - 1);
+  interestName.append("ndnx");
   interestName.append(ndndId_);
-  interestName.append(component2, sizeof(component2) - 1);
+  interestName.append("selfreg");
   interestName.append(data.wireEncode());
-                    
+
   Interest interest(interestName);
   interest.setScope(1);
+  interest.setInterestLifetime(1000);
+
+  expressInterest(interest,
+                  func_lib::bind(&Node::registerPrefixFinal, this,
+                                 registeredPrefixId, prefix, onInterest, onRegisterFailed, _1, _2),
+                  func_lib::bind(onRegisterFailed, prefix));
+}
+
+void
+Node::registerPrefixFinal(uint64_t registeredPrefixId,
+                          const ptr_lib::shared_ptr<const Name>& prefix,
+                          const OnInterest& onInterest,
+                          const OnRegisterFailed& onRegisterFailed,
+                          const ptr_lib::shared_ptr<const Interest>&, const ptr_lib::shared_ptr<Data>&data)
+{
+  Block content = data->getContent();
+  content.parse();
+
+  if (content.getAll().empty())
+    {
+      onRegisterFailed(prefix);
+      return;
+    }
+
+  switch(content.getAll().begin()->type())
+    {
+    case Tlv::FaceManagement::ForwardingEntry:
+      {
+        // succeeded
+        break;
+      }
+    case Tlv::FaceManagement::StatusResponse:
+      {
+        // failed :(
+        StatusResponse resp;
+        resp.wireDecode(*content.getAll().begin());
+
+        std::cerr << "StatusReponse: " << resp << std::endl;
+      
+        onRegisterFailed(prefix);
+        return;
+      
+        break;
+      }
+    default:
+      {
+        // failed :(
+      
+        onRegisterFailed(prefix);
+        return;
+        break;
+      }
+    }
+
+     
   
   // Save the onInterest callback and send the registration interest.
   registeredPrefixTable_.push_back(ptr_lib::make_shared<RegisteredPrefix>(registeredPrefixId, prefix, onInterest));
-  
-  transport_->send(interest.wireEncode());
+
+  /// @todo Notify user about successful registration
 }
 
 void