Enabling TCP window tracing (there is a trick to do it with
Config::Connect, see examples/congestion-pop.cc)

There was a bug with InFlight interest calculation
diff --git a/apps/ccnx-consumer-window.cc b/apps/ccnx-consumer-window.cc
index d244061..77f258c 100644
--- a/apps/ccnx-consumer-window.cc
+++ b/apps/ccnx-consumer-window.cc
@@ -43,13 +43,16 @@
     .AddConstructor<CcnxConsumerWindow> ()
 
     .AddAttribute ("Window", "Initial size of the window",
-                   StringValue ("1000"),
+                   StringValue ("1"),
                    MakeUintegerAccessor (&CcnxConsumerWindow::GetWindow, &CcnxConsumerWindow::SetWindow),
                    MakeUintegerChecker<uint32_t> ())
 
     .AddTraceSource ("WindowTrace",
                      "Window that controls how many outstanding interests are allowed",
                      MakeTraceSourceAccessor (&CcnxConsumerWindow::m_window))
+    .AddTraceSource ("InFlight",
+                     "Current number of outstanding interests",
+                     MakeTraceSourceAccessor (&CcnxConsumerWindow::m_window))
     ;
 
   return tid;
@@ -83,9 +86,11 @@
     }
   
   // std::cout << "Window: " << m_window << ", InFlight: " << m_inFlight << "\n";
-  m_inFlight++;
   if (!m_sendEvent.IsRunning ())
-    m_sendEvent = Simulator::ScheduleNow (&CcnxConsumer::SendPacket, this);
+    {
+      m_inFlight++;
+      m_sendEvent = Simulator::ScheduleNow (&CcnxConsumer::SendPacket, this);
+    }
 }
 
 ///////////////////////////////////////////////////
@@ -99,8 +104,8 @@
   CcnxConsumer::OnContentObject (contentObject, payload);
 
   m_window = m_window + 1;
-  
-  if (m_inFlight > 0) m_inFlight--;
+
+  if (m_inFlight > static_cast<uint32_t> (0)) m_inFlight--;
   ScheduleNextPacket ();
 }
 
@@ -108,7 +113,7 @@
 CcnxConsumerWindow::OnNack (const Ptr<const CcnxInterestHeader> &interest)
 {
   CcnxConsumer::OnNack (interest);
-  if (m_inFlight > 0) m_inFlight--;
+  if (m_inFlight > static_cast<uint32_t> (0)) m_inFlight--;
 
   if (m_window > static_cast<uint32_t> (0))
     {
@@ -120,7 +125,7 @@
 void
 CcnxConsumerWindow::OnTimeout (uint32_t sequenceNumber)
 {
-  if (m_inFlight > 0) m_inFlight--;
+  if (m_inFlight > static_cast<uint32_t> (0)) m_inFlight--;
   CcnxConsumer::OnTimeout (sequenceNumber);
 }
 
diff --git a/apps/ccnx-consumer-window.h b/apps/ccnx-consumer-window.h
index 716608d..c3b0ddf 100644
--- a/apps/ccnx-consumer-window.h
+++ b/apps/ccnx-consumer-window.h
@@ -72,7 +72,7 @@
   
 protected:
   TracedValue<uint32_t> m_window;
-  uint32_t m_inFlight;
+  TracedValue<uint32_t> m_inFlight;
 };
 
 } // namespace ns3
diff --git a/examples/congestion-pop.cc b/examples/congestion-pop.cc
index 0a512cb..fcfcc99 100644
--- a/examples/congestion-pop.cc
+++ b/examples/congestion-pop.cc
@@ -299,8 +299,8 @@
 
         for (uint32_t i = 0; i < apps.GetN () / 2; i++) 
           {
-            apps.Get (i*2)->SetStartTime (Seconds (i));
-            apps.Get (i*2 + 1)->SetStartTime (Seconds (i));
+            apps.Get (i*2)->SetStartTime (Seconds (1+i));
+            apps.Get (i*2 + 1)->SetStartTime (Seconds (1+i));
           }
 
         CcnxTraceHelper traceHelper;
@@ -320,14 +320,24 @@
         experiment.InstallIpStack ();
         ApplicationContainer apps = experiment.AddTcpApplications ();
 
-        for (uint32_t i = 0; i < apps.GetN () / 2; i++) 
-          {
-            apps.Get (i*2)->SetStartTime (Seconds (i));
-            apps.Get (i*2 + 1)->SetStartTime (Seconds (i));
-          }
-
         CcnxTraceHelper traceHelper;
         traceHelper.EnableIpv4SeqsAppAll (prefix + "tcp-consumers-seqs.log");
+        traceHelper.EnableWindowsTcpAll (prefix + "tcp-windows.log");
+
+        for (uint32_t i = 0; i < apps.GetN () / 2; i++) 
+          {
+            apps.Get (i*2)->SetStartTime (Seconds (1+i));
+
+            apps.Get (i*2 + 1)->SetStartTime (Seconds (1+i));
+
+            // cout << "Node: " << apps.Get (i*2 + 1)->GetNode ()->GetId () << "\n";
+            // care only about BulkSender
+            Simulator::Schedule (Seconds (1+i+0.01),
+                                 &CcnxTraceHelper::TcpConnect, &traceHelper, apps.Get (i*2)->GetNode ());
+
+            Simulator::Schedule (Seconds (1+i+0.01),
+                                 &CcnxTraceHelper::TcpConnect, &traceHelper, apps.Get (i*2 + 1)->GetNode ());
+          }
 
         experiment.Run (Seconds (200.0));
       }
diff --git a/helper/ccnx-trace-helper.cc b/helper/ccnx-trace-helper.cc
index 92c20f7..a7f8014 100644
--- a/helper/ccnx-trace-helper.cc
+++ b/helper/ccnx-trace-helper.cc
@@ -31,6 +31,7 @@
 #include "ns3/object-vector.h"
 #include "ns3/simulator.h"
 #include "ns3/names.h"
+#include "ns3/tcp-l4-protocol.h"
 
 #include <boost/ref.hpp>
 #include <boost/lexical_cast.hpp>
@@ -59,6 +60,7 @@
   , m_appSeqsTrace (0)
   , m_ipv4AppSeqsTrace (0)
   , m_windowsTrace (0)
+  , m_windowsTcpTrace (0)
 {
 }
 
@@ -69,6 +71,7 @@
   if (m_appSeqsTrace != 0) delete m_appSeqsTrace;
   if (m_ipv4AppSeqsTrace != 0) delete m_ipv4AppSeqsTrace;
   if (m_windowsTrace != 0) delete m_windowsTrace;
+  if (m_windowsTcpTrace != 0) delete m_windowsTcpTrace;
   
   if (m_apps.size () > 0)
     {
@@ -327,5 +330,34 @@
     }
 }
 
+void
+CcnxTraceHelper::TcpConnect (Ptr<Node> node)
+{
+  ObjectVectorValue sockets;
+  node->GetObject<TcpL4Protocol> ()->GetAttribute ("SocketList", sockets);
+  
+  uint32_t sockId = 0;      
+  for (ObjectVectorValue::Iterator socket = sockets.Begin ();
+       socket != sockets.End ();
+       socket++, sockId++)
+    {
+      // std::cout << "Node: " << node->GetId () << ", Socket " << sockId << "\n";
+          
+      Ptr<TcpCongestionWindowTracer> trace = Create<TcpCongestionWindowTracer> (boost::ref(*m_windowsTcpTrace),
+                                                                                node,
+                                                                                lexical_cast<string> (sockId));
+      m_windowsTcp.push_back (trace);
+    }
+}
+
+void
+CcnxTraceHelper::EnableWindowsTcpAll (const std::string &windowTrace)
+{
+  NS_LOG_FUNCTION (this);
+  m_windowsTcpTrace = new ofstream (windowTrace.c_str (), ios::trunc);
+
+  WindowTracer::PrintHeader (*m_windowsTcpTrace);
+  *m_windowsTcpTrace << "\n";
+}
 
 } // namespace ns3
diff --git a/helper/ccnx-trace-helper.h b/helper/ccnx-trace-helper.h
index 544c887..cfff107 100644
--- a/helper/ccnx-trace-helper.h
+++ b/helper/ccnx-trace-helper.h
@@ -28,10 +28,11 @@
 
 namespace ns3 {
 
+class Node;
 class CcnxAppTracer;
 class CcnxL3Tracer;
 class Ipv4AppTracer;
-class CcnxConsumerWindowTracer;
+class WindowTracer;
 
 class CcnxTraceHelper
 {
@@ -100,7 +101,15 @@
    */
   void
   EnableWindowsAll (const std::string &windowTrace = "windows.log");
-  
+
+  /**
+   * @brief Enable tracing of congestion window changes in TcpNewReno
+   */
+  void
+  EnableWindowsTcpAll (const std::string &windowTrace);
+
+  void TcpConnect (Ptr<Node> node);
+
 private:
   std::string m_appTrace;
   std::list<Ptr<CcnxAppTracer> > m_apps;
@@ -117,8 +126,11 @@
   std::list<Ptr<Ipv4AppTracer> > m_ipv4AppSeqs;
   std::ostream *m_ipv4AppSeqsTrace;
 
-  std::list<Ptr<CcnxConsumerWindowTracer> > m_windows;
+  std::list<Ptr<WindowTracer> > m_windows;
   std::ostream *m_windowsTrace;
+
+  std::list<Ptr<WindowTracer> > m_windowsTcp;
+  std::ostream *m_windowsTcpTrace;
 };
 
 
diff --git a/helper/tracers/ccnx-consumer-window-tracer.cc b/helper/tracers/ccnx-consumer-window-tracer.cc
index e2bf877..eea664a 100644
--- a/helper/tracers/ccnx-consumer-window-tracer.cc
+++ b/helper/tracers/ccnx-consumer-window-tracer.cc
@@ -32,53 +32,55 @@
 using namespace boost;
 
 namespace ns3 {
-    
-CcnxConsumerWindowTracer::CcnxConsumerWindowTracer (std::ostream &os, Ptr<Node> node, const std::string &appId)
+
+void
+CcnxConsumerWindowTracer::Connect ()
+{
+  Config::Connect ("/NodeList/"+m_node+"/ApplicationList/"+m_appId+"/$ns3::CcnxConsumerWindow/WindowTrace",
+                   MakeCallback (&WindowTracer::OnWindowChange, this));
+}
+
+void
+TcpCongestionWindowTracer::Connect ()
+{
+  Config::Connect ("/NodeList/"+m_node+"/$ns3::TcpL4Protocol/SocketList/*/CongestionWindow",
+                   MakeCallback (&WindowTracer::OnWindowChange, this));
+}
+
+
+WindowTracer::WindowTracer (std::ostream &os, Ptr<Node> node, const std::string &appId)
   : m_appId (appId)
   , m_nodePtr (node)
   , m_os (os)
 {
   m_node = boost::lexical_cast<string> (m_nodePtr->GetId ());
 
-  Connect ();
-
   string name = Names::FindName (node);
   if (!name.empty ())
     {
-      m_node = name;
+      m_nodeName = name;
     }
-}
-
-void
-CcnxConsumerWindowTracer::Connect ()
-{
-  Config::Connect ("/NodeList/"+m_node+"/ApplicationList/"+m_appId+"/$ns3::CcnxConsumerWindow/WindowTrace",
-                   MakeCallback (&CcnxConsumerWindowTracer::OnWindowChange, this));
+  else
+    m_nodeName = m_node;
 }
 
 
 void
-CcnxConsumerWindowTracer::PrintHeader (std::ostream &os) const
+WindowTracer::PrintHeader (std::ostream &os)
 {
   os << "Time\t"
      << "Node\t"
      << "AppId\t"
      << "Window";
 }
-  
-void
-CcnxConsumerWindowTracer::Print (std::ostream &os) const
-{
-  // do nothing
-}
 
 void
-CcnxConsumerWindowTracer::OnWindowChange (std::string context,
-                                          uint32_t oldValue, uint32_t newValue)
+WindowTracer::OnWindowChange (std::string context,
+                              uint32_t oldValue, uint32_t newValue)
 {
   m_os                                                             
     << Simulator::Now ().ToDouble (Time::S) << "\t"                   
-    << m_node << "\t"                                                 
+    << m_nodeName << "\t"                                                 
     << m_appId << "\t"
     << newValue << endl;
 }
diff --git a/helper/tracers/ccnx-consumer-window-tracer.h b/helper/tracers/ccnx-consumer-window-tracer.h
index b178ee1..c538931 100644
--- a/helper/tracers/ccnx-consumer-window-tracer.h
+++ b/helper/tracers/ccnx-consumer-window-tracer.h
@@ -28,41 +28,49 @@
 
 class Node;
 
-class CcnxConsumerWindowTracer : public SimpleRefCount<CcnxConsumerWindowTracer>
+class WindowTracer : public SimpleRefCount<WindowTracer>
 {
 public:
-  CcnxConsumerWindowTracer (std::ostream &os, Ptr<Node> node, const std::string &appId = "*");
-  virtual ~CcnxConsumerWindowTracer ()  { };
-
-  void
-  Connect ();
-
-  virtual void
-  PrintHeader (std::ostream &os) const;
+  WindowTracer (std::ostream &os, Ptr<Node> node, const std::string &appId = "*");
+  virtual ~WindowTracer () { };
+                
+  static void
+  PrintHeader (std::ostream &os);
   
   virtual void
-  Print (std::ostream &os) const;
-
-  virtual void
   OnWindowChange (std::string context,
                   uint32_t oldValue, uint32_t newValue);
 
 protected:
   std::string m_appId;
   std::string m_node;
+  std::string m_nodeName;
   Ptr<Node> m_nodePtr;
   std::ostream& m_os;
 };
 
-inline std::ostream&
-operator << (std::ostream &os, const CcnxConsumerWindowTracer &tracer)
+class CcnxConsumerWindowTracer : public WindowTracer
 {
-  os << "# ";
-  tracer.PrintHeader (os);
-  os << "\n";
-  tracer.Print (os);
-  return os;
-}
+public:
+  CcnxConsumerWindowTracer (std::ostream &os, Ptr<Node> node, const std::string &appId = "*")
+    : WindowTracer (os, node, appId)
+  { Connect (); }
+
+  void
+  Connect ();
+};
+
+class TcpCongestionWindowTracer : public WindowTracer
+{
+public:
+  TcpCongestionWindowTracer (std::ostream &os, Ptr<Node> node, const std::string &appId = "*")
+    : WindowTracer (os, node, appId)
+  { Connect (); }
+
+  void
+  Connect ();
+};
+
 
 } // namespace ns3