model+ndn.cxx+test: Finishing implementation of ApiFace (now timeouts are working as well)

Also, adding a basic test case to test ApiFace

Refs #1005 (http://redmine.named-data.net/)
diff --git a/ndn.cxx/detail/filter-entry.h b/ndn.cxx/detail/filter-entry.h
deleted file mode 100644
index 97b9a14..0000000
--- a/ndn.cxx/detail/filter-entry.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2013, Regents of the University of California
- *                     Alexander Afanasyev
- *
- * GNU v3.0 license, See the LICENSE file for more information
- *
- * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- */
-
-#ifndef NDN_NDNCXX_DETAIL_FILTER_ENTRY_H
-#define NDN_NDNCXX_DETAIL_FILTER_ENTRY_H
-
-#include <ns3/ndnSIM/utils/trie/trie-with-policy.h>
-#include <ns3/ndnSIM/utils/trie/counting-policy.h>
-
-namespace ns3 {
-namespace ndn {
-
-template<class Callback, class Payload>
-struct FilterEntry : public ns3::SimpleRefCount< FilterEntry<Callback, Payload> >
-{
-public:
-  FilterEntry (Ptr<const Payload> payload)
-    : m_payload (payload)
-  { }
-  
-  void
-  AddCallback (Callback callback)
-  { 
-    m_callback = callback;
-  }
-
-  void
-  ClearCallback ()
-  {
-    m_callback = Callback ();
-  }
-
-  Ptr<const Payload>
-  GetPayload () const
-  {
-    return m_payload;
-  }
-  
-public:
-  Callback m_callback;
-  Ptr<const Payload> m_payload;
-};
-
-
-template<class Callback, class Payload>
-struct FilterEntryContainer :
-    public ns3::ndn::ndnSIM::trie_with_policy<ns3::ndn::Name,
-                                              ns3::ndn::ndnSIM::smart_pointer_payload_traits< FilterEntry<Callback, Payload> >,
-                                              ns3::ndn::ndnSIM::counting_policy_traits>
-{
-};
-
-} // ndn
-} // ns3
-
-#endif // NDN_NDNCXX_DETAIL_FILTER_ENTRY_H
diff --git a/ndn.cxx/detail/pending-interests-container.h b/ndn.cxx/detail/pending-interests-container.h
new file mode 100644
index 0000000..4d96ed4
--- /dev/null
+++ b/ndn.cxx/detail/pending-interests-container.h
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * GNU v3.0 license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_NDNCXX_DETAIL_PENDING_INTEREST_CONTAINER_H
+#define NDN_NDNCXX_DETAIL_PENDING_INTEREST_CONTAINER_H
+
+#include <ns3/ndnSIM/utils/trie/trie-with-policy.h>
+#include "timeouts-policy.h"
+
+namespace ns3 {
+namespace ndn {
+namespace detail {
+
+struct PendingInterestEntry : public SimpleRefCount< PendingInterestEntry >
+{
+public:
+  PendingInterestEntry (Ptr<const Interest> interest)
+    : m_interest (interest)
+  { }
+  
+  void
+  AddCallbacks (ApiFace::DataCallback onData, ApiFace::TimeoutCallback onTimeout)
+  { 
+    m_dataCallback = onData;
+    m_timeoutCallback = onTimeout;
+  }
+
+  void
+  ClearCallbacks ()
+  {
+    m_dataCallback = ApiFace::DataCallback ();
+    m_timeoutCallback = ApiFace::TimeoutCallback ();
+  }
+
+  Ptr<const Interest>
+  GetInterest () const
+  {
+    return m_interest;
+  }
+  
+public:
+  ApiFace::DataCallback m_dataCallback;
+  ApiFace::TimeoutCallback m_timeoutCallback;
+  Ptr<const Interest> m_interest;
+};
+
+
+struct PendingInterestContainer :
+    public ndnSIM::trie_with_policy<Name,
+                                    ndnSIM::smart_pointer_payload_traits< PendingInterestEntry >,
+                                    timeouts_policy_traits>
+{
+};
+
+} // detail
+} // ndn
+} // ns3
+
+#endif // NDN_NDNCXX_DETAIL_PENDING_INTEREST_CONTAINER_H
diff --git a/ndn.cxx/detail/registered-prefix-container.h b/ndn.cxx/detail/registered-prefix-container.h
new file mode 100644
index 0000000..2e6c151
--- /dev/null
+++ b/ndn.cxx/detail/registered-prefix-container.h
@@ -0,0 +1,63 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * GNU v3.0 license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_NDNCXX_DETAIL_REGISTERED_PREFIX_CONTAINER_H
+#define NDN_NDNCXX_DETAIL_REGISTERED_PREFIX_CONTAINER_H
+
+#include <ns3/ndnSIM/utils/trie/trie-with-policy.h>
+#include <ns3/ndnSIM/utils/trie/counting-policy.h>
+
+namespace ns3 {
+namespace ndn {
+namespace detail {
+
+struct RegisteredPrefixEntry : public SimpleRefCount< RegisteredPrefixEntry >
+{
+public:
+  RegisteredPrefixEntry (Ptr<const Name> prefix)
+    : m_prefix (prefix)
+  { }
+  
+  void
+  AddCallback (ApiFace::InterestCallback callback)
+  { 
+    m_callback = callback;
+  }
+
+  void
+  ClearCallback ()
+  {
+    m_callback = ApiFace::InterestCallback ();
+  }
+
+  Ptr<const Name>
+  GetPrefix () const
+  {
+    return m_prefix;
+  }
+  
+public:
+  ApiFace::InterestCallback m_callback;
+  Ptr<const Name> m_prefix;
+};
+
+
+struct RegisteredPrefixContainer :
+    public ndnSIM::trie_with_policy<Name,
+                                    ndnSIM::smart_pointer_payload_traits< RegisteredPrefixEntry >,
+                                    ndnSIM::counting_policy_traits>
+{
+};
+
+} // detail
+} // ndn
+} // ns3
+
+#endif // NDN_NDNCXX_DETAIL_REGISTERED_PREFIX_CONTAINER_H
diff --git a/ndn.cxx/detail/timeouts-policy.h b/ndn.cxx/detail/timeouts-policy.h
new file mode 100644
index 0000000..7398d44
--- /dev/null
+++ b/ndn.cxx/detail/timeouts-policy.h
@@ -0,0 +1,167 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * GNU v3.0 license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_NDNCXX_DETAIL_TIMEOUTS_POLICY_H_
+#define NDN_NDNCXX_DETAIL_TIMEOUTS_POLICY_H_
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+
+#include <ns3/nstime.h>
+#include <ns3/simulator.h>
+
+namespace ns3 {
+namespace ndn {
+namespace detail {
+
+/**
+ * @brief Traits for timeouts policy
+ */
+struct timeouts_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (for NS-3 object model and logging)
+  static std::string GetName () { return "Timeouts"; }
+
+  struct policy_hook_type : public boost::intrusive::set_member_hook<> { Time timeWhenShouldExpire; };
+
+  template<class Container>
+  struct container_hook
+  {
+    typedef boost::intrusive::member_hook< Container,
+                                           policy_hook_type,
+                                           &Container::policy_hook_ > type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy
+  {
+    static Time& get_timeout (typename Container::iterator item)
+    {
+      return static_cast<typename policy_container::value_traits::hook_type*>
+        (policy_container::value_traits::to_node_ptr(*item))->timeWhenShouldExpire;
+    }
+
+    static const Time& get_timeout (typename Container::const_iterator item)
+    {
+      return static_cast<const typename policy_container::value_traits::hook_type*>
+        (policy_container::value_traits::to_node_ptr(*item))->timeWhenShouldExpire;
+    }
+
+    template<class Key>
+    struct MemberHookLess
+    {
+      bool operator () (const Key &a, const Key &b) const
+      {
+        return get_timeout (&a) < get_timeout (&b);
+      }
+    };
+
+    typedef boost::intrusive::multiset< Container,
+                                        boost::intrusive::compare< MemberHookLess< Container > >,
+                                        Hook > policy_container;
+
+
+    class type : public policy_container
+    {
+    public:
+      typedef policy policy_base; // to get access to get_timeout methods from outside
+      typedef Container parent_trie;
+
+      type (Base &base)
+        : m_base (base)
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        // do nothing
+      }
+
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        Time timeout = item->payload ()->GetInterest ()->GetInterestLifetime ();
+        if (timeout.IsZero ()) timeout = Seconds (4.0);
+        
+        get_timeout (item) = Simulator::Now () + timeout;
+        policy_container::insert (*item);
+
+        if (policy_container::s_iterator_to (*item) == policy_container::begin ())
+          {
+            if (m_timeoutEvent.IsRunning ())
+              {
+                Simulator::Remove (m_timeoutEvent); // just canceling would not clean up list of events
+              }
+
+            m_timeoutEvent = Simulator::Schedule (timeout, &type::ProcessTimeoutEntry, this, item);
+          }
+        
+        return true;
+      }
+
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        // do nothing. it's random policy
+      }
+
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        if (policy_container::s_iterator_to (*item) == policy_container::begin ())
+          {
+            if (m_timeoutEvent.IsRunning ())
+              {
+                Simulator::Remove (m_timeoutEvent); // just canceling would not clean up list of events
+              }
+          }
+
+        // erase only if freshness is non zero (otherwise an item is not in the policy
+        policy_container::erase (policy_container::s_iterator_to (*item));
+
+        if (!policy_container::empty ())
+          {
+            Time timeout = get_timeout (&*policy_container::begin ()) - Simulator::Now ();
+            m_timeoutEvent = Simulator::Schedule (timeout, &type::ProcessTimeoutEntry, this, &*policy_container::begin ());
+          }
+      }
+
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+      inline void
+      ProcessTimeoutEntry (typename parent_trie::iterator item)
+      {
+        item->payload ()->m_timeoutCallback (item->payload ()->GetInterest ());
+
+        m_base.erase (item);
+      }
+
+    private:
+      type () : m_base (*((Base*)0)) { };
+
+    private:
+      Base &m_base;
+      EventId m_timeoutEvent;
+    };
+  };
+};
+
+} // detail
+} // ndn
+} // ns3
+
+#endif // NDN_NDNCXX_DETAIL_TIMEOUTS_STATS_POLICY_H