limits: one more update and small interface changes
diff --git a/helper/ndn-global-routing-helper.cc b/helper/ndn-global-routing-helper.cc
index 7acf7d6..3d18042 100644
--- a/helper/ndn-global-routing-helper.cc
+++ b/helper/ndn-global-routing-helper.cc
@@ -288,7 +288,7 @@
                         limitsFactory.SetTypeId (limits->GetInstanceTypeId ());
 
                         Ptr<Limits> entryLimits = limitsFactory.Create<Limits> ();
-                        entryLimits->SetMaxLimit (limits->GetMaxLimit ());
+                        entryLimits->SetLimits (limits->GetMaxRate (), limits->GetMaxDelay ());
 
                         entry->AggregateObject (entryLimits);
                       }
diff --git a/helper/ndn-stack-helper.cc b/helper/ndn-stack-helper.cc
index 9c29bf9..5dade78 100644
--- a/helper/ndn-stack-helper.cc
+++ b/helper/ndn-stack-helper.cc
@@ -279,7 +279,7 @@
               NS_LOG_INFO ("MaxLimit: " << (int)(m_avgRtt.ToDouble (Time::S) * maxInterestPackets));
 
               // Set max to BDP
-              limits->SetMaxLimit (m_avgRtt.ToDouble (Time::S) * maxInterestPackets);
+              limits->SetLimits (maxInterestPackets, m_avgRtt.ToDouble (Time::S));
             }
         }
         
diff --git a/model/fw/simple-window-limits.h b/model/fw/simple-window-limits.h
index 69fcd19..7e844ba 100644
--- a/model/fw/simple-window-limits.h
+++ b/model/fw/simple-window-limits.h
@@ -26,11 +26,11 @@
 #include "ns3/ndn-pit.h"
 #include "ns3/ndn-pit-entry.h"
 #include "ns3/simulator.h"
+#include "ns3/string.h"
 
 #include "ns3/ndn-forwarding-strategy.h"
 
-#include "../../utils/ndn-limits-window.h"
-
+#include "ns3/ndn-limits.h"
 
 namespace ns3 {
 namespace ndn {
@@ -63,7 +63,8 @@
   virtual void
   AddFace (Ptr<Face> face)
   {
-    Ptr<Limits> limits = CreateObject<LimitsWindow> ();
+    ObjectFactory factory (m_limitType);
+    Ptr<Limits> limits = factory.template Create<Limits> ();
     face->AggregateObject (limits);
 
     super::AddFace (face);
@@ -81,6 +82,8 @@
   WillSatisfyPendingInterest (Ptr<Face> inFace,
                               Ptr<pit::Entry> pitEntry);
 
+private:
+  std::string m_limitType;
 };
 
 template<class Parent>
@@ -91,6 +94,11 @@
     .SetGroupName ("Ndn")
     .template SetParent <super> ()
     .template AddConstructor <SimpleWindowLimits> ()
+
+    .template AddAttribute ("Limit", "Limit type to be used (e.g., ns3::ndn::Limits::Window or ns3::ndn::Limits::Rate)",
+                            StringValue ("ns3::ndn::Limits::Window"),
+                            MakeStringAccessor (&SimpleWindowLimits<Parent>::m_limitType),
+                            MakeStringChecker ())    
     ;
   return tid;
 }
@@ -115,8 +123,10 @@
       return false;
     }
 
-  if (outFace->template GetObject<LimitsWindow> ()->IsBelowLimit ())
+  Ptr<Limits> faceLimits = outFace->template GetObject<Limits> ();
+  if (faceLimits->IsBelowLimit ())
     {
+      faceLimits->BorrowLimit ();
       pitEntry->AddOutgoing (outFace);
 
       //transmission
@@ -144,7 +154,8 @@
        face != pitEntry->GetOutgoing ().end ();
        face ++)
     {
-      face->m_face->GetObject<LimitsWindow> ()->RemoveOutstanding ();
+      Ptr<Limits> faceLimits = face->m_face->GetObject<Limits> ();
+      faceLimits->ReturnLimit ();
     }
 
   super::WillEraseTimedOutPendingInterest (pitEntry);
@@ -162,7 +173,8 @@
        face != pitEntry->GetOutgoing ().end ();
        face ++)
     {
-      face->m_face->GetObject<LimitsWindow> ()->RemoveOutstanding ();
+      Ptr<Limits> faceLimits = face->m_face->GetObject<Limits> ();
+      faceLimits->ReturnLimit ();
     }
   
   super::WillSatisfyPendingInterest (inFace, pitEntry);
diff --git a/utils/ndn-limits-rate.cc b/utils/ndn-limits-rate.cc
new file mode 100644
index 0000000..215250e
--- /dev/null
+++ b/utils/ndn-limits-rate.cc
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ndn-limits-rate.h"
+
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/random-variable.h"
+
+NS_LOG_COMPONENT_DEFINE ("ndn.Limits.Rate");
+
+namespace ns3 {
+namespace ndn {
+
+NS_OBJECT_ENSURE_REGISTERED (LimitsRate);
+
+TypeId
+LimitsRate::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::ndn::Limits::Rate")
+    .SetGroupName ("Ndn")
+    .SetParent <Limits> () 
+    .AddConstructor <LimitsRate> ()
+    
+    ;
+  return tid;
+}
+
+void
+LimitsRate::UpdateCurrentLimit (double limit)
+{
+  NS_ASSERT_MSG (limit >= 0.0, "Limit should be greater or equal to zero");
+  
+  m_bucketLeak = std::min (limit, GetMaxRate ());
+  m_bucketMax  = m_bucketLeak * GetMaxDelay ();
+}
+
+bool
+LimitsRate::IsBelowLimit ()
+{
+  if (!IsEnabled ()) return true;
+
+  return (m_bucketMax - m_bucket >= 1.0);
+}
+
+void
+LimitsRate::BorrowLimit ()
+{
+  if (!IsEnabled ()) return; 
+
+  NS_ASSERT_MSG (m_bucketMax - m_bucket >= 1.0, "Should not be possible, unless we IsBelowLimit was not checked correctly");
+  m_bucket += 1; 
+}
+
+void
+LimitsRate::ReturnLimit ()
+{
+  // do nothing
+}
+
+void
+LimitsRate::LeakBucket (double interval)
+{
+  const double leak = m_bucketLeak * interval;
+
+  m_bucket = std::max (0.0, m_bucket - leak);
+}
+
+} // namespace ndn
+} // namespace ns3
diff --git a/utils/ndn-limits-rate.h b/utils/ndn-limits-rate.h
new file mode 100644
index 0000000..4050bb2
--- /dev/null
+++ b/utils/ndn-limits-rate.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef _NDN_LIMITS_RATE_H_
+#define	_NDN_LIMITS_RATE_H_
+
+#include "ndn-limits.h"
+
+namespace ns3 {
+namespace ndn {
+
+/**
+ * \ingroup ndn
+ * \brief Structure to manage limits for outstanding interests
+ */
+class LimitsRate :
+    public Limits
+{
+public:
+  typedef Limits super;
+  
+  static TypeId
+  GetTypeId ();
+  
+  /**
+   * \brief Constructor
+   * \param prefix smart pointer to the prefix for the FIB entry
+   */
+  LimitsRate ()
+    : m_bucketMax (0)
+    , m_bucketLeak (0)
+    , m_bucket (0)
+  { }
+
+  virtual
+  ~LimitsRate () { }
+
+  virtual void
+  SetLimits (double rate, double delay)
+  {
+    super::SetLimits (rate, delay);
+
+    // maximum allowed burst
+    m_bucketMax = GetMaxRate () * GetMaxDelay ();
+
+    // amount of packets allowed every second (leak rate)
+    m_bucketLeak = GetMaxRate ();
+  }
+
+  /**
+   * @brief Check if Interest limit is reached (token bucket is not empty)
+   */
+  virtual bool
+  IsBelowLimit ();
+
+  /**
+   * @brief Get token from the bucket
+   */
+  virtual void
+  BorrowLimit ();
+
+  /**
+   * @brief Does nothing (token bucket leakage is time-dependent only)
+   */
+  virtual void
+  ReturnLimit ();
+
+  /**
+   * @brief Update current leak ratio and maximum burst
+   */
+  virtual void
+  UpdateCurrentLimit (double limit);
+
+  /**
+   */
+  virtual double
+  GetCurrentLimit () const
+  {
+    return m_bucketLeak;
+  }
+
+private:
+  /**
+   * @brief Leak bucket, assuming `interval' seconds between leakages
+   *
+   * @param interval Time interval for leakage. Used to calculate size of the leak
+   */
+  void
+  LeakBucket (double interval);
+
+private:
+  double m_bucketMax;   ///< \brief Maximum Interest allowance for this face (maximum tokens that can be issued at the same time)
+  double m_bucketLeak;  ///< \brief Normalized amount that should be leaked every second (token bucket leak rate)
+  double m_bucket;      ///< \brief Value representing current size of the Interest allowance for this face (current size of token bucket)
+};
+  
+
+} // namespace ndn
+} // namespace ns3
+
+#endif // _NDN_LIMITS_RATE_H_
diff --git a/utils/ndn-limits-window.cc b/utils/ndn-limits-window.cc
index 6f371b4..95c221b 100644
--- a/utils/ndn-limits-window.cc
+++ b/utils/ndn-limits-window.cc
@@ -21,15 +21,13 @@
 #include "ndn-limits-window.h"
 
 #include "ns3/log.h"
-#include "ns3/simulator.h"
-#include "ns3/random-variable.h"
 
 NS_LOG_COMPONENT_DEFINE ("ndn.Limits.Window");
 
 namespace ns3 {
 namespace ndn {
 
-NS_OBJECT_ENSURE_REGISTERED (Limits);
+NS_OBJECT_ENSURE_REGISTERED (LimitsWindow);
 
 TypeId
 LimitsWindow::GetTypeId ()
@@ -39,6 +37,10 @@
     .SetParent <Limits> () 
     .AddConstructor <LimitsWindow> ()
     
+    .AddTraceSource ("CurMaxLimit",
+                     "Current maximum limit",
+                     MakeTraceSourceAccessor (&LimitsWindow::m_curMaxLimit))
+
     .AddTraceSource ("Outstanding",
                      "Number of outstanding interests",
                      MakeTraceSourceAccessor (&LimitsWindow::m_outstanding))
@@ -46,35 +48,36 @@
   return tid;
 }
 
+void
+LimitsWindow::UpdateCurrentLimit (double limit)
+{
+  NS_ASSERT_MSG (limit >= 0.0, "Limit should be greater or equal to zero");
+  
+  m_curMaxLimit = std::min (limit, GetMaxRate () * GetMaxDelay ());
+}
+
 bool
 LimitsWindow::IsBelowLimit ()
 {
   if (!IsEnabled ()) return true;
 
-  if (m_curMaxLimit - m_outstanding >= 1.0)
-    {
-      // static UniformVariable acceptanceProbability (0, m_curMaxLimit);
-      // double value = acceptanceProbability.GetValue ();
-      double value = m_outstanding + 1;
-      
-      if (m_outstanding < value)
-        {
-          m_outstanding += 1.0;
-          return true;
-        }
-      else
-        return false;
-    }
-  else
-    return false;
+  return (m_curMaxLimit - m_outstanding >= 1.0);
 }
 
 void
-LimitsWindow::RemoveOutstanding ()
+LimitsWindow::BorrowLimit ()
 {
   if (!IsEnabled ()) return; 
 
-  NS_LOG_DEBUG (m_outstanding);
+  NS_ASSERT_MSG (m_curMaxLimit - m_outstanding >= 1.0, "Should not be possible, unless we IsBelowLimit was not checked correctly");
+  m_outstanding += 1;
+}
+
+void
+LimitsWindow::ReturnLimit ()
+{
+  if (!IsEnabled ()) return; 
+
   NS_ASSERT_MSG (m_outstanding >= (uint32_t)1, "Should not be possible, unless we decreasing this number twice somewhere");
   m_outstanding -= 1;
 }
diff --git a/utils/ndn-limits-window.h b/utils/ndn-limits-window.h
index b1f2208..5b93b6e 100644
--- a/utils/ndn-limits-window.h
+++ b/utils/ndn-limits-window.h
@@ -28,7 +28,7 @@
 
 /**
  * \ingroup ndn
- * \brief Structure to manage limits for outstanding interests
+ * \brief Structure to manage limits for outstanding interests (window-based limiting)
  */
 class LimitsWindow :
     public Limits
@@ -40,40 +40,57 @@
   GetTypeId ();
   
   /**
-   * \brief Constructor
-   * \param prefix smart pointer to the prefix for the FIB entry
+   * @brief Default Constructor
    */
   LimitsWindow ()
   : m_outstanding (0)
   { }
 
+  /**
+   * @brief Virtual destructor
+   */
   virtual
   ~LimitsWindow () { }
 
+  // from ndn::Limits
 
-  // from limits
+  virtual void
+  SetLimits (double rate, double delay)
+  {
+    super::SetLimits (rate, delay);
+
+    m_curMaxLimit = GetMaxRate () * GetMaxDelay ();
+  }
+
+  virtual void
+  UpdateCurrentLimit (double limit);
+  
+  virtual double
+  GetCurrentLimit () const
+  {
+    return m_curMaxLimit;
+  }
+
+  /**
+   * @brief Check if current interest window (number of pending interests) if less than maximum 
+   */
   virtual bool
   IsBelowLimit ();
 
-  ////////////////////////////////////////////////////////////////////////////
-  ////////////////////////////////////////////////////////////////////////////
-  ////////////////////////////////////////////////////////////////////////////
-
-  // specific to window-based limits
-  
   /**
-   * @brief Remove outstanding interests
+   * @brief Increase current window of outstanding interests
    */
-  void
-  RemoveOutstanding ();
+  virtual void
+  BorrowLimit ();
 
-  double
-  GetOutstanding () const
-  {
-    return m_outstanding;
-  }
+  /**
+   * @brief Decrease current window of outstanding interests
+   */
+  virtual void
+  ReturnLimit ();
   
-protected:
+private:
+  TracedValue< double > m_curMaxLimit;
   TracedValue< double > m_outstanding;
 };
   
diff --git a/utils/ndn-limits.cc b/utils/ndn-limits.cc
index 4e5f48f..338d195 100644
--- a/utils/ndn-limits.cc
+++ b/utils/ndn-limits.cc
@@ -36,21 +36,9 @@
     .SetGroupName ("Ndn")
     .SetParent <Object> ()
     
-    .AddTraceSource ("CurMaxLimit",
-                     "Current maximum limit",
-                     MakeTraceSourceAccessor (&Limits::m_curMaxLimit))
-                     
     ;
   return tid;
 }
 
-void
-Limits::UpdateCurrentLimit (double limit)
-{
-  NS_ASSERT_MSG (limit >= 0.0, "Limit should be greater or equal to zero");
-  
-  m_curMaxLimit = std::min (limit, m_maxLimit);
-}
-
 } // namespace ndn
 } // namespace ns3
diff --git a/utils/ndn-limits.h b/utils/ndn-limits.h
index 14aec50..cf5c039 100644
--- a/utils/ndn-limits.h
+++ b/utils/ndn-limits.h
@@ -30,7 +30,7 @@
 
 /**
  * \ingroup ndn
- * \brief Structure to manage limits for outstanding interests
+ * \brief Abstract class to manage Interest limits 
  */
 class Limits :
     public Object
@@ -39,31 +39,48 @@
   static TypeId
   GetTypeId ();
 
+  /**
+   * @brief Default constructor
+   */
   Limits ()
-  : m_maxLimit (-1)
-  , m_curMaxLimit (0)
+  : m_maxRate (-1)
+  , m_maxDelay (1.0)
   { }
 
+  /**
+   * @brief Virtual destructor
+   */
   virtual
   ~Limits () {}
   
   /**
    * @brief Set limit for the number of outstanding interests
+   * @param rate   Maximum rate that needs to be enforced
+   * @param delay  Maximum delay for BDP product for window-based limits
    */
   virtual void
-  SetMaxLimit (double max)
+  SetLimits (double rate, double delay)
   {
-    m_maxLimit = max;
-    m_curMaxLimit = max;
+    m_maxRate = rate;
+    m_maxDelay = delay;
   }    
 
   /**
-   * @brief Get limit for the number of outstanding interests
+   * @brief Get maximum rate that needs to be enforced
    */
   virtual double
-  GetMaxLimit () const
+  GetMaxRate () const
   {
-    return m_maxLimit;
+    return m_maxRate;
+  }
+
+  /**
+   * @brief Get maximum delay for BDP product for window-based limits
+   */
+  virtual double
+  GetMaxDelay () const
+  {
+    return m_maxDelay;
   }
 
   /**
@@ -72,37 +89,56 @@
   virtual inline bool
   IsEnabled () const
   {
-    return m_maxLimit > 0.0;
+    return m_maxRate > 0.0;
   }
 
   /**
    * @brief Update a current value of the limit
+   * @param limit Value of current limit.
    *
-   * If limit is larger than previously set value of maximum limit (SetMaxLimit), then the current limit will
-   * be limited to that maximum value
+   * Note that interpretation of this value may be different in different ndn::Limit realizations
+   *
+   * All realizations will try to guarantee that if limit is larger than previously set value of maximum limit,
+   * then the current limit will be limited to that maximum value
    */
-  void
-  UpdateCurrentLimit (double limit);
+  virtual void
+  UpdateCurrentLimit (double limit) = 0;
 
-  double
-  GetCurrentLimit () const
-  {
-    return m_curMaxLimit;
-  }
-  
-  ////////////////////////////////////////////////////////////////////////////
-  ////////////////////////////////////////////////////////////////////////////
-  ////////////////////////////////////////////////////////////////////////////
-  
   /**
-   * @brief Check if new interest can be send out, if yes, number of outstanding will be increased
+   * @brief Get value of the current limit
+   *
+   * Note that interpretation of this value may be different in different ndn::Limit realizations
+   */
+  virtual double
+  GetCurrentLimit () const = 0;
+  
+  ////////////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Realization-specific method called to check availability of the limit
    */
   virtual bool
   IsBelowLimit () = 0;
+
+  /**
+   * @brief "Borrow" limit
+   *
+   * IsBelowLimit **must** be true, otherwise assert fail
+   */
+  virtual void
+  BorrowLimit () = 0;
+
+  /**
+   * @brief "Return" limit
+   */
+  virtual void
+  ReturnLimit () = 0;
   
-protected:
-  double m_maxLimit;
-  TracedValue< double > m_curMaxLimit;
+private:
+  double m_maxRate;
+  double m_maxDelay;
 };