Added in ns-3-tcp (second try)
authorRaj Bhattacharjea <raj.b@gatech.edu>
Fri, 25 Jan 2008 13:57:38 -0500
changeset 2224 6f97d21a99c2
parent 2222 09b00ef2f4f3
child 2225 a740e5826e69
Added in ns-3-tcp (second try)
examples/tcp-large-transfer-errors.cc
examples/tcp-large-transfer.cc
examples/tcp-nonlistening-server.cc
examples/tcp-small-transfer-oneloss.cc
examples/tcp-small-transfer.cc
examples/wscript
src/applications/packet-sink/packet-sink.cc
src/applications/packet-sink/packet-sink.h
src/internet-node/internet-node.cc
src/internet-node/pending-data.cc
src/internet-node/pending-data.h
src/internet-node/rtt-estimator.cc
src/internet-node/rtt-estimator.h
src/internet-node/sequence-number.cc
src/internet-node/sequence-number.h
src/internet-node/tcp-header.cc
src/internet-node/tcp-header.h
src/internet-node/tcp-impl.cc
src/internet-node/tcp-impl.h
src/internet-node/tcp-l4-protocol.cc
src/internet-node/tcp-l4-protocol.h
src/internet-node/tcp-socket.cc
src/internet-node/tcp-socket.h
src/internet-node/tcp-typedefs.h
src/internet-node/wscript
src/node/socket.cc
src/node/socket.h
src/node/tcp.cc
src/node/tcp.h
src/node/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-large-transfer-errors.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,240 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+//           10Mb/s, 10ms       10Mb/s, 10ms
+//       n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file 
+//   "tcp-large-transfer-errors.tr"
+// - pcap traces also generated in the following files
+//   "tcp-large-transfer-errors.pcap-$n-$i" where n and i represent node and interface numbers respectively
+//  Usage (e.g.): ./waf --run tcp-large-transfer-errors
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpLargeTransferErrors");
+
+void 
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+  const Address &addr)
+{
+  if (!g_log.IsNoneEnabled ()) {
+    if (InetSocketAddress::IsMatchingType (addr) )
+      {
+      InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+        std::cout << "PacketSink received size " << 
+        packet->GetSize () << " at time " << 
+        Simulator::Now ().GetSeconds () << " from address: " << 
+        address.GetIpv4 () << std::endl;
+        char buf[2000]; 
+        memcpy(buf, packet->PeekData (), packet->GetSize ());
+        for (uint32_t i=0; i < packet->GetSize (); i++)
+          {
+            std::cout << buf[i];
+            if (i && i % 60 == 0) 
+              std::cout << std::endl; 
+          }
+        std::cout << std::endl << std::endl;
+    }
+  }
+}
+
+void CloseConnection (Ptr<Socket> localSocket)
+{
+  //localSocket->Close ();
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes, 
+  uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " <<  Simulator::Now ().GetSeconds ());
+  localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
+  localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
+                                   Callback<void, Ptr<Socket> > (),
+                                   Callback<void, Ptr<Socket> > ());
+  //we want to close as soon as the connection is established
+  //the tcp state machine and outgoing buffer will assure that
+  //all of the data is delivered
+
+  // Perform series of 1040 byte writes (this is a multiple of 26 since
+  // we want to detect data splicing in the output stream)
+  uint32_t writeSize = 1040;
+  uint8_t data[writeSize];
+  while (nBytes > 0) {
+    uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
+    for(uint32_t i = 0; i < curSize; ++i)
+    {
+      char m = toascii (97 + i % 26);
+      data[i] = m;
+    }
+    localSocket->Send (data, curSize);
+    nBytes -= curSize;
+  }
+}
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+//  LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+//  LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+//  LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+  //LogComponentEnable("TcpLargeTransferErrors", LOG_LEVEL_ALL);
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create three nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+    n0, n1, DataRate(10000000), MilliSeconds(10));
+  
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address("10.1.3.1"),
+      n1, Ipv4Address("10.1.3.2"));
+
+  Ptr<PointToPointChannel> channel1 = 
+      PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate(10000000), MilliSeconds(10));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address("10.1.2.1"),
+      n2, Ipv4Address("10.1.2.2"));
+  
+  // Finally, we add static routes.  These three steps (Channel and
+  // NetDevice creation, IP Address assignment, and routing) are 
+  // separated because there may be a need to postpone IP Address
+  // assignment (emulation) or modify to use dynamic routing
+  PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+  PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+  Ptr<Ipv4> ipv4;
+  ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+  ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Simulation 1
+  // 
+  // Send 2000000 bytes over a connection to server port 50000 at time 0
+  // Should observe SYN exchange, a lot of data segments, and FIN exchange
+  //
+  ///////////////////////////////////////////////////////////////////////////
+
+  int nBytes = 2000000;
+  uint16_t servPort = 50000;
+
+  Ptr<SocketFactory> socketFactory = 
+    n0->QueryInterface<SocketFactory> (Tcp::iid);
+  Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+  localSocket->Bind ();
+
+  // Create a packet sink to receive these packets
+  Ptr<PacketSink> sink = Create<PacketSink> (
+    n2,
+    InetSocketAddress (Ipv4Address::GetAny (), servPort),
+    "Tcp");
+  sink->Start (Seconds (0.0));
+  sink->Stop (Seconds (10000.0));
+
+ //
+  // Error models
+  //
+  // We want to add an error model to node 2's NetDevice
+  // We can obtain a handle to the NetDevice via the channel and node 
+  // pointers
+  Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
+    (n2, channel1);
+  Ptr<RateErrorModel> rem = Create<RateErrorModel> ();
+  // The first data segment for this flow is packet uid=4
+  rem->SetRandomVariable (UniformVariable ());
+  rem->SetUnit (EU_PKT);
+  rem->SetRate (0.05);
+  nd2->AddReceiveErrorModel (rem);
+
+  Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+    servPort);
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-examples.tr file
+  AsciiTrace asciitrace ("tcp-large-transfer-errors.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-examples.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("tcp-large-transfer-errors.pcap");
+  pcaptrace.TraceAllIp ();
+
+  NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+  Simulator::StopAt (Seconds(10000));
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-large-transfer.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,225 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+//           10Mb/s, 10ms       10Mb/s, 10ms
+//       n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file 
+//   "tcp-large-transfer.tr"
+// - pcap traces also generated in the following files
+//   "tcp-large-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
+//  Usage (e.g.): ./waf --run tcp-large-transfer
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
+
+void 
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+  const Address &addr)
+{
+  if (!g_log.IsNoneEnabled ()) {
+    if (InetSocketAddress::IsMatchingType (addr) )
+      {
+      InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+        std::cout << "PacketSink received size " << 
+        packet->GetSize () << " at time " << 
+        Simulator::Now ().GetSeconds () << " from address: " << 
+        address.GetIpv4 () << std::endl;
+        char buf[2000]; 
+        memcpy(buf, packet->PeekData (), packet->GetSize ());
+        for (uint32_t i=0; i < packet->GetSize (); i++)
+          {
+            std::cout << buf[i];
+            if (i && i % 60 == 0) 
+              std::cout << std::endl; 
+          }
+        std::cout << std::endl << std::endl;
+    }
+  }
+}
+
+void CloseConnection (Ptr<Socket> localSocket)
+{
+  //localSocket->Close ();
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes, 
+  uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " <<  Simulator::Now ().GetSeconds ());
+  localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
+  localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
+                                   Callback<void, Ptr<Socket> > (),
+                                   Callback<void, Ptr<Socket> > ());
+  //we want to close as soon as the connection is established
+  //the tcp state machine and outgoing buffer will assure that
+  //all of the data is delivered
+
+  // Perform series of 1040 byte writes (this is a multiple of 26 since
+  // we want to detect data splicing in the output stream)
+  uint32_t writeSize = 1040;
+  uint8_t data[writeSize];
+  while (nBytes > 0) {
+    uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
+    for(uint32_t i = 0; i < curSize; ++i)
+    {
+      char m = toascii (97 + i % 26);
+      data[i] = m;
+    }
+    localSocket->Send (data, curSize);
+    nBytes -= curSize;
+  }
+}
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+//  LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+//  LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+//  LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+  //LogComponentEnable("TcpLargeTransfer", LOG_LEVEL_ALL);
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create three nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+    n0, n1, DataRate(10000000), MilliSeconds(10));
+  
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address("10.1.3.1"),
+      n1, Ipv4Address("10.1.3.2"));
+
+  Ptr<PointToPointChannel> channel1 = 
+      PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate(10000000), MilliSeconds(10));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address("10.1.2.1"),
+      n2, Ipv4Address("10.1.2.2"));
+  
+  // Finally, we add static routes.  These three steps (Channel and
+  // NetDevice creation, IP Address assignment, and routing) are 
+  // separated because there may be a need to postpone IP Address
+  // assignment (emulation) or modify to use dynamic routing
+  PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+  PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+  Ptr<Ipv4> ipv4;
+  ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+  ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Simulation 1
+  // 
+  // Send 2000000 bytes over a connection to server port 50000 at time 0
+  // Should observe SYN exchange, a lot of data segments, and FIN exchange
+  //
+  ///////////////////////////////////////////////////////////////////////////
+
+  int nBytes = 2000000;
+  uint16_t servPort = 50000;
+
+  Ptr<SocketFactory> socketFactory = 
+    n0->QueryInterface<SocketFactory> (Tcp::iid);
+  Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+  localSocket->Bind ();
+
+  // Create a packet sink to receive these packets
+  Ptr<PacketSink> sink = Create<PacketSink> (
+    n2,
+    InetSocketAddress (Ipv4Address::GetAny (), servPort),
+    "Tcp");
+  sink->Start (Seconds (0.0));
+  sink->Stop (Seconds (100.0));
+
+  Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+    servPort);
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-examples.tr file
+  AsciiTrace asciitrace ("tcp-large-transfer.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-examples.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("tcp-large-transfer.pcap");
+  pcaptrace.TraceAllIp ();
+
+  NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+  Simulator::StopAt (Seconds(1000));
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-nonlistening-server.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,191 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+//           100Kb/s, 10ms       1Mb/s, 10ms
+//       n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file 
+//   "tcp-nonlistening-server.tr"
+// - pcap traces also generated in the following files
+//   "tcp-nonlistening-server.pcap-$n-$i" where n and i represent node and interface numbers respectively
+//  Usage (e.g.): ./waf --run tcp-nonlistening-server
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpNonListeningServer");
+
+void ConnectionSucceededCallback (Ptr<Socket> localSocket) 
+{
+  uint32_t nBytes = 2000;
+  uint8_t data[nBytes];
+  for(uint32_t i = 0; i < nBytes; ++i)
+  {
+    char m = 'A';
+    data[i] = m;
+  } //put something interesting in the packets ABCDEF...
+  localSocket->Send (data, nBytes);
+}
+
+void ConnectionFailedCallback (Ptr<Socket> localSocket) 
+{
+  NS_LOG_ERROR("Connection failed at time " << Simulator::Now ().GetSeconds ());
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint16_t servPort)
+{
+  NS_LOG_LOGIC(std::endl << "Connection attempt at time " <<  
+    Simulator::Now ().GetSeconds () << std::endl);
+  localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
+  localSocket->SetConnectCallback (
+    MakeCallback (&ConnectionSucceededCallback),
+    MakeCallback (&ConnectionFailedCallback), 
+    MakeNullCallback<void, Ptr<Socket> > () );
+}
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+  //LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+  //LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+  LogComponentEnable("TcpNonListeningServer", LOG_LEVEL_ALL);
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create three nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+    n0, n1, DataRate(1000000), MilliSeconds(10));
+  
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address("10.1.3.1"),
+      n1, Ipv4Address("10.1.3.2"));
+
+  Ptr<PointToPointChannel> channel1 = 
+      PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate(100000), MilliSeconds(10));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address("10.1.2.1"),
+      n2, Ipv4Address("10.1.2.2"));
+  
+  // Finally, we add static routes.  These three steps (Channel and
+  // NetDevice creation, IP Address assignment, and routing) are 
+  // separated because there may be a need to postpone IP Address
+  // assignment (emulation) or modify to use dynamic routing
+  PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+  PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+  Ptr<Ipv4> ipv4;
+  ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+  ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Simulation 1
+  // 
+  // Send 2000 bytes over a connection to server port 500 at time 0
+  // Should observe SYN exchange, two data segments, and FIN exchange
+  //
+  ///////////////////////////////////////////////////////////////////////////
+
+  uint16_t servPort = 500;
+
+  Ptr<SocketFactory> socketFactory = 
+    n0->QueryInterface<SocketFactory> (Tcp::iid);
+  Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+  localSocket->Bind ();
+
+#ifdef NOTFORTHISSCRIPT
+  // Create an optional packet sink to receive these packets
+  Ptr<PacketSink> sink = Create<PacketSink> (
+    n2,
+    InetSocketAddress (Ipv4Address::GetAny (), servPort),
+    "Tcp");
+  // Start the sink
+  sink->Start (Seconds (0.0));
+  sink->Stop (Seconds (10.0));
+#endif
+
+  Simulator::Schedule(Seconds(0), &StartFlow, localSocket, servPort);
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-examples.tr file
+  AsciiTrace asciitrace ("tcp-nonlistening-server.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-examples.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("tcp-nonlistening-server.pcap");
+  pcaptrace.TraceAllIp ();
+
+
+  Simulator::StopAt (Seconds(1000));
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-small-transfer-oneloss.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,222 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+//           100Kb/s, 10ms       1Mb/s, 10ms
+//       n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file 
+//   "tcp-small-transfer-oneloss.tr"
+// - pcap traces also generated in the following files
+//   "tcp-small-transfer-oneloss.pcap-$n-$i" where n and i represent node and interface numbers respectively
+//  Usage (e.g.): ./waf --run tcp-small-transfer-oneloss
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpSmallTransferOneloss");
+
+void 
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+  const Address &addr)
+{
+  if (!g_log.IsNoneEnabled ()) {
+    if (InetSocketAddress::IsMatchingType (addr) )
+      {
+      InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+        std::cout << "PacketSink received size " << 
+        packet->GetSize () << " at time " << 
+        Simulator::Now ().GetSeconds () << " from address: " << 
+        address.GetIpv4 () << std::endl;
+        char buf[2000]; 
+        memcpy(buf, packet->PeekData (), packet->GetSize ());
+        for (uint32_t i=0; i < packet->GetSize (); i++)
+          {
+            std::cout << buf[i];
+            if (i && i % 60 == 0) 
+              std::cout << std::endl; 
+          }
+        std::cout << std::endl << std::endl;
+    }
+  }
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes, 
+  uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " <<  Simulator::Now ().GetSeconds ());
+  localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
+  uint8_t data[nBytes];
+  for(uint32_t i = 0; i < nBytes; ++i)
+  {
+    char m = toascii (97 + i % 26);
+    data[i] = m;
+  } 
+  localSocket->Send (data, nBytes);
+}
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+ LogComponentEnable("TcpSmallTransferOneloss", LOG_LEVEL_ALL);
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create three nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+    n0, n1, DataRate(1000000), MilliSeconds(10));
+  
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address("10.1.3.1"),
+      n1, Ipv4Address("10.1.3.2"));
+
+  Ptr<PointToPointChannel> channel1 = 
+      PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate(100000), MilliSeconds(10));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address("10.1.2.1"),
+      n2, Ipv4Address("10.1.2.2"));
+  
+  // Finally, we add static routes.  These three steps (Channel and
+  // NetDevice creation, IP Address assignment, and routing) are 
+  // separated because there may be a need to postpone IP Address
+  // assignment (emulation) or modify to use dynamic routing
+  PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+  PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+  Ptr<Ipv4> ipv4;
+  ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+  ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Simulation 1
+  // 
+  // Send 2000 bytes over a connection to server port 500 at time 0
+  // Should observe SYN exchange, two data segments, and FIN exchange
+  // Force the loss of the first data segment
+  //
+  ///////////////////////////////////////////////////////////////////////////
+
+  int nBytes = 2000;
+  uint16_t servPort = 500;
+
+  Ptr<SocketFactory> socketFactory = 
+    n0->QueryInterface<SocketFactory> (Tcp::iid);
+  Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+  localSocket->Bind ();
+
+  // Create a packet sink to receive these packets
+  Ptr<PacketSink> sink = Create<PacketSink> (
+    n2,
+    InetSocketAddress (Ipv4Address::GetAny (), servPort),
+    "Tcp");
+  sink->Start (Seconds (0.0));
+  sink->Stop (Seconds (100.0));
+
+  //
+  // Error models
+  //
+  // We want to add an error model to node 2's NetDevice
+  // We can obtain a handle to the NetDevice via the channel and node 
+  // pointers
+  Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
+    (n2, channel1);
+  Ptr<ListErrorModel> pem = Create<ListErrorModel> ();
+  std::list<uint32_t> sampleList;
+  // The first data segment for this flow is packet uid=4
+  sampleList.push_back (4);
+  pem->SetList (sampleList);
+  nd2->AddReceiveErrorModel (pem);
+
+  Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+    servPort);
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-examples.tr file
+  AsciiTrace asciitrace ("tcp-small-transfer-oneloss.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-examples.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("tcp-small-transfer-oneloss.pcap");
+  pcaptrace.TraceAllIp ();
+
+  NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+  Simulator::StopAt (Seconds(1000));
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-small-transfer.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,217 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+//           100Kb/s, 10ms       1Mb/s, 10ms
+//       n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file 
+//   "tcp-small-transfer.tr"
+// - pcap traces also generated in the following files
+//   "tcp-small-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
+//  Usage (e.g.): ./waf --run tcp-small-transfer
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpSmallTransfer");
+
+void 
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+  const Address &addr)
+{
+  if (!g_log.IsNoneEnabled ()) {
+    if (InetSocketAddress::IsMatchingType (addr) )
+      {
+      InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+        std::cout << "PacketSink received size " << 
+        packet->GetSize () << " at time " << 
+        Simulator::Now ().GetSeconds () << " from address: " << 
+        address.GetIpv4 () << std::endl;
+        char buf[2000]; 
+        memcpy(buf, packet->PeekData (), packet->GetSize ());
+        for (uint32_t i=0; i < packet->GetSize (); i++)
+          {
+            std::cout << buf[i];
+            if (i && i % 60 == 0) 
+              std::cout << std::endl; 
+          }
+        std::cout << std::endl << std::endl;
+    }
+  }
+}
+
+void CloseConnection (Ptr<Socket> localSocket)
+{
+  localSocket->Close ();
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes, 
+  uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " <<  Simulator::Now ().GetSeconds ());
+  localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
+  localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
+                                   MakeNullCallback<void, Ptr<Socket> > (),
+                                   MakeNullCallback<void, Ptr<Socket> > ());
+  //we want to close as soon as the connection is established
+  //the tcp state machine and outgoing buffer will assure that
+  //all of the data is delivered
+  uint8_t data[nBytes];
+  for(uint32_t i = 0; i < nBytes; ++i)
+  {
+    char m = toascii (97 + i % 26);
+    data[i] = m;
+  }
+  localSocket->Send (data, nBytes);
+}
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+//  LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+  // LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+//  LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+  LogComponentEnable("TcpSmallTransfer", LOG_LEVEL_ALL);
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create three nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+    n0, n1, DataRate(1000000), MilliSeconds(10));
+  
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address("10.1.3.1"),
+      n1, Ipv4Address("10.1.3.2"));
+
+  Ptr<PointToPointChannel> channel1 = 
+      PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate(100000), MilliSeconds(10));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address("10.1.2.1"),
+      n2, Ipv4Address("10.1.2.2"));
+  
+  // Finally, we add static routes.  These three steps (Channel and
+  // NetDevice creation, IP Address assignment, and routing) are 
+  // separated because there may be a need to postpone IP Address
+  // assignment (emulation) or modify to use dynamic routing
+  PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+  PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+  Ptr<Ipv4> ipv4;
+  ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+  ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Simulation 1
+  // 
+  // Send 2000 bytes over a connection to server port 500 at time 0
+  // Should observe SYN exchange, two data segments, and FIN exchange
+  //
+  ///////////////////////////////////////////////////////////////////////////
+
+  int nBytes = 2000;
+  uint16_t servPort = 500;
+
+  Ptr<SocketFactory> socketFactory = 
+    n0->QueryInterface<SocketFactory> (Tcp::iid);
+  Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+  localSocket->Bind ();
+
+  // Create a packet sink to receive these packets
+  Ptr<PacketSink> sink = Create<PacketSink> (
+    n2,
+    InetSocketAddress (Ipv4Address::GetAny (), servPort),
+    "Tcp");
+  sink->Start (Seconds (0.0));
+  sink->Stop (Seconds (100.0));
+
+  Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+    servPort);
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-examples.tr file
+  AsciiTrace asciitrace ("tcp-small-transfer.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-examples.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("tcp-small-transfer.pcap");
+  pcaptrace.TraceAllIp ();
+
+  NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+  Simulator::StopAt (Seconds(1000));
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
--- a/examples/wscript	Sat Jan 19 21:03:18 2008 -0800
+++ b/examples/wscript	Fri Jan 25 13:57:38 2008 -0500
@@ -45,3 +45,25 @@
     obj = bld.create_ns3_program('simple-point-to-point-olsr',
         ['point-to-point', 'internet-node', 'olsr'])
     obj.source = 'simple-point-to-point-olsr.cc'
+
+    obj = bld.create_ns3_program('tcp-large-transfer',
+        ['point-to-point', 'internet-node'])
+    obj.source = 'tcp-large-transfer.cc'
+
+    obj = bld.create_ns3_program('tcp-large-transfer-errors',
+        ['point-to-point', 'internet-node'])
+    obj.source = 'tcp-large-transfer-errors.cc'
+
+    obj = bld.create_ns3_program('tcp-nonlistening-server',
+        ['point-to-point', 'internet-node'])
+    obj.source = 'tcp-nonlistening-server.cc'
+
+    obj = bld.create_ns3_program('tcp-small-transfer',
+        ['point-to-point', 'internet-node'])
+    obj.source = 'tcp-small-transfer.cc'
+
+    obj = bld.create_ns3_program('tcp-small-transfer-oneloss',
+        ['point-to-point', 'internet-node'])
+    obj.source = 'tcp-small-transfer-oneloss.cc'
+
+
--- a/src/applications/packet-sink/packet-sink.cc	Sat Jan 19 21:03:18 2008 -0800
+++ b/src/applications/packet-sink/packet-sink.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -78,9 +78,14 @@
         GetNode ()->QueryInterface<SocketFactory> (iid);
       m_socket = socketFactory->CreateSocket ();
       m_socket->Bind (m_local);
+      m_socket->Listen (0);
     }
 
   m_socket->SetRecvCallback (MakeCallback(&PacketSink::Receive, this));
+  m_socket->SetAcceptCallback (
+            MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
+            MakeNullCallback<void, Ptr<Socket>, const Address&> (),
+            MakeCallback(&PacketSink::CloseConnection, this) );
 }
 
 void PacketSink::StopApplication()     // Called at time specified by Stop
@@ -106,6 +111,11 @@
   m_rxTrace (packet, from);
 }
 
+void PacketSink::CloseConnection (Ptr<Socket> socket)
+{
+  socket->Close ();
+}
+
 Ptr<TraceResolver> 
 PacketSink::GetTraceResolver (void) const
 {
--- a/src/applications/packet-sink/packet-sink.h	Sat Jan 19 21:03:18 2008 -0800
+++ b/src/applications/packet-sink/packet-sink.h	Fri Jan 25 13:57:38 2008 -0500
@@ -78,6 +78,7 @@
                   std::string iid);
 
   virtual void Receive (Ptr<Socket> socket, Ptr<Packet> packet, const Address& from);
+  virtual void CloseConnection (Ptr<Socket> socket);
 
   Ptr<Socket>     m_socket;       // Associated socket
   Address         m_local;        // Local address to bind to
--- a/src/internet-node/internet-node.cc	Sat Jan 19 21:03:18 2008 -0800
+++ b/src/internet-node/internet-node.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -28,9 +28,11 @@
 #include "ipv4-l4-demux.h"
 #include "internet-node.h"
 #include "udp-l4-protocol.h"
+#include "tcp-l4-protocol.h"
 #include "ipv4-l3-protocol.h"
 #include "arp-l3-protocol.h"
 #include "udp-impl.h"
+#include "tcp-impl.h"
 #include "ipv4-impl.h"
 
 namespace ns3 {
@@ -62,15 +64,20 @@
 
   Ptr<Ipv4L4Demux> ipv4L4Demux = Create<Ipv4L4Demux> (this);
   Ptr<UdpL4Protocol> udp = Create<UdpL4Protocol> (this);
+  Ptr<TcpL4Protocol> tcp = Create<TcpL4Protocol> (this);
+
   ipv4L4Demux->Insert (udp);
+  ipv4L4Demux->Insert (tcp);
 
   Ptr<UdpImpl> udpImpl = Create<UdpImpl> (udp);
+  Ptr<TcpImpl> tcpImpl = Create<TcpImpl> (tcp);
   Ptr<Ipv4Impl> ipv4Impl = Create<Ipv4Impl> (ipv4);
 
   Object::AddInterface (ipv4);
   Object::AddInterface (arp);
   Object::AddInterface (ipv4Impl);
   Object::AddInterface (udpImpl);
+  Object::AddInterface (tcpImpl);
   Object::AddInterface (ipv4L4Demux);
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/pending-data.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,222 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// This is a port of Data PDU Headers from:
+// Georgia Tech Network Simulator
+// George F. Riley.  Georgia Tech, Spring 2002
+
+#include <iostream>
+#include <algorithm>
+
+#include <string.h>
+
+#include "pending-data.h"
+#include "ns3/packet.h"
+#include "ns3/fatal-error.h"
+namespace ns3
+{
+
+namespace Serializable
+{
+  uint8_t* GetSize (uint8_t* b, uint32_t& r, uint32_t& s)
+  { // Get the size of the next size field
+    if (sizeof(s) > r)
+    {
+      NS_FATAL_ERROR ("Serialization error; remaining " << r
+           << " thissize " << sizeof(s) << std::endl);
+    }
+    r -= sizeof (s); // Reduce remaining for next time
+    memcpy (&s, b, sizeof(s));
+    return b + sizeof (s);
+  }
+}
+
+PendingData::PendingData () : size (0), data (0),
+               msgSize (0), responseSize (0)
+{
+}
+
+PendingData::PendingData (uint32_t s, uint8_t* d, uint32_t msg, uint32_t resp)
+  : size (s), data (0), msgSize (msg), responseSize (resp)
+{ // Make a copy of the data
+  if (d)
+    {
+      data = new uint8_t[s];
+      memcpy (data, d, s);
+    }
+}
+
+PendingData::PendingData(const std::string& s) 
+  : size (s.length () + 1), data ((uint8_t*)strdup(s.c_str ())),
+    msgSize (0), responseSize (0)
+{
+}
+
+PendingData::PendingData(const PendingData& c)
+  : size (c.Size ()), data (0),
+    msgSize (c.msgSize), responseSize (c.responseSize)
+{ // Copy constructor
+  if (c.Contents())
+    { // Has data
+      data = new uint8_t[Size ()];
+      memcpy(data, c.Contents (), Size ());
+    }
+}
+
+PendingData::~PendingData()
+{ // destructor
+  if (data)
+    {
+	  delete [] data;
+    }
+}
+
+PendingData* PendingData::Copy () const
+{
+  return new PendingData (*this);
+};
+
+PendingData* PendingData::CopyS (uint32_t s)
+{ // Copy, but with new size (assumes no associated data);
+  return new PendingData (s, 0, msgSize, responseSize);
+}
+
+PendingData* PendingData::CopySD (uint32_t s, uint8_t* d)
+{ // Copy, but with new size (assumes no associated data);
+  return new PendingData (s, d, msgSize, responseSize);
+}
+
+void PendingData::Clear ()
+{ // Remove all pending data
+  if (data)
+    {
+      delete [] data; // Free memory if used
+    }
+  data = 0;
+  size = 0;
+}
+
+void PendingData::Add (uint32_t s, const uint8_t* d)
+{
+  if (data)
+    { // PendingData exists, realloc and copy
+      uint8_t* n = new uint8_t[Size () + s];
+      memcpy(n, data, Size ());
+      if (d)
+        { // New data specified
+          memcpy(n + Size (), d, s); // Append the new data
+        }
+      else
+        {
+          memset(n + Size (), 0, s); // Apend zeros
+        }
+      delete [] data;           // Delete the old data
+      data = n;                 // Points to new one
+    }
+  else
+    { // No existing data, see if new data
+      if (d)
+        {
+          data = new uint8_t[s];
+          memcpy (data, d, s);
+        }
+    }
+  size += s;
+}
+
+void PendingData::Remove(uint32_t s)
+{
+  uint32_t r = s > Size () ? Size () : s;
+
+  size -= r;          // Reduce size from current
+  if (data)
+    { // data actually exists, realloc and copy
+      if (size)
+        {
+          uint8_t* d = new uint8_t[Size ()];
+          memcpy(d, data, Size ());
+          delete [] data;
+          data = d;
+        }
+      else
+        { // Zero size, so don't need the data anymore
+          delete [] data;
+          data = NULL;
+        }
+    }
+}
+
+uint32_t PendingData::SizeFromSeq (const SequenceNumber& f, const SequenceNumber& o)
+{
+  uint32_t o1 = OffsetFromSeq (f,o); // Offset to start of unused data
+  return SizeFromOffset (o1);      // Amount of data after offset
+}
+
+uint32_t PendingData::SizeFromOffset (uint32_t o)
+{ // Find out how much data is available from offset
+  if (o > size) return 0;     // No data at requested offset
+  return size - o;            // Available data after offset
+}
+
+uint32_t PendingData::OffsetFromSeq (const SequenceNumber& f, const SequenceNumber& o)
+{ // f is the first sequence number in this data, o is offset sequence
+  if (o < f) 
+    {
+      return 0; // HuH?  Shouldn't happen
+    }
+  return o - f;
+}
+
+PendingData* PendingData::CopyFromOffset (uint32_t s, uint32_t o)
+{ // Make a copy of data from starting position "o" for "s" bytes
+  // Return NULL if results in zero length data
+  uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data
+  if (s1 == 0)
+    {
+      return NULL;   // No data requested
+    }
+  if (data)
+    { // Actual data exists, make copy and return it
+      uint8_t* d1 = new uint8_t[s1];  // Allocate memory for the copy
+      memcpy (d1, &data[o], s1); // Copy the data
+      PendingData* d = new PendingData (s1, d1, msgSize, responseSize);  // Return copy
+      return d;
+    }
+  else
+    { // No actual data, just return non-data pdu of correct size
+      return new PendingData (s1, 0, msgSize, responseSize);
+    }
+}
+
+PendingData* PendingData::CopyFromSeq (uint32_t s, const SequenceNumber& f, const SequenceNumber& o)
+{
+  PendingData* d = CopyFromOffset (s, OffsetFromSeq(f,o));
+  return d;
+}
+
+}//namepsace ns3      
+  
+  
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/pending-data.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,73 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Georgia Tech Network Simulator - Data Descriptors
+// George F. Riley.  Georgia Tech, Spring 2002
+
+#ifndef __datapdu_h__
+#define __datapdu_h__
+
+#include "pending-data.h"
+#include "sequence-number.h"
+namespace ns3
+{
+class Packet;
+//Doc:ClassXRef
+class PendingData {
+public:
+  PendingData ();
+  PendingData (uint32_t s, uint8_t* d = NULL, uint32_t msg = 0, uint32_t resp = 0);
+  PendingData (const std::string&); // Construct from string
+  PendingData (uint8_t*, uint32_t&, Packet*); // Construct from serialized buffer
+  PendingData (const PendingData&);   // Copy constructor
+  virtual ~PendingData ();     // Destructor
+  uint32_t Size () const { return size;}
+  // Serialization
+  uint32_t SSize ();                   // Size needed for serialization
+  uint8_t*  Serialize (uint8_t*, uint32_t&); // Serialize to a buffer
+  uint8_t*  Construct (uint8_t*, uint32_t&); // Construct from buffer
+  virtual void Clear ();// Remove all associated data
+  virtual void Add (uint32_t s, const uint8_t* d = 0);// Add some data to end
+  virtual void Remove (uint32_t);      // Remove data from head
+  // Inquire available data from (f,o) sequence pair
+  virtual uint32_t SizeFromSeq (const SequenceNumber&, const SequenceNumber&);
+  // Inquire available data from offset
+  virtual uint32_t SizeFromOffset (uint32_t);
+  // Available size from sequence difference 
+  virtual uint32_t OffsetFromSeq (const SequenceNumber&, const SequenceNumber&);
+  virtual PendingData* CopyFromOffset (uint32_t, uint32_t);  // Size, offset, ret pointer
+  // Copy data, size, offset specified by sequence difference
+  virtual PendingData* CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&);
+  PendingData*   Copy () const;          // Create a copy of this header
+  PendingData*   CopyS (uint32_t);         // Copy with new size
+  PendingData*   CopySD (uint32_t, uint8_t*); // Copy with new size, new data
+  virtual uint8_t* Contents() const { return data;}
+public:
+  uint32_t size;        // Number of data bytes
+  uint8_t* data;         // Corresponding data (may be null)
+  // The next two fields allow simulated applications to exchange some info
+  uint32_t msgSize;     // Total size of message
+  uint32_t responseSize;// Size of response requested
+};
+
+}//namepsace ns3
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/rtt-estimator.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,233 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// Ported from:
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley.  Georgia Tech, Spring 2002
+
+// Implements several variations of round trip time estimators
+
+#include <iostream>
+
+#include "rtt-estimator.h"
+#include "ns3/simulator.h"
+
+namespace ns3{
+
+//RttEstimator iid
+const InterfaceId RttEstimator::iid = MakeInterfaceId ("RttEstimator",
+    Object::iid);
+
+//Default values
+ClassIdDefaultValue RttEstimator::defaultCid ("RttEstimator",
+                                        "Tahoe round trip time estimation",
+                                        RttEstimator::iid, "RttMeanDeviation");
+NumericDefaultValue<double> RttEstimator::defaultMaxMultiplier ("RttMaxMultiplier","",64.0);
+
+// RttEstimator Static Member variables
+Time        RttEstimator::initialEstimate = Seconds (1.0); // Default initial estimate
+
+//RttHistory methods
+RttHistory::RttHistory (SequenceNumber s, uint32_t c, Time t)
+  : seq (s), count (c), time (t), retx (false)
+  {
+  }
+
+RttHistory::RttHistory (const RttHistory& h)
+  : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
+  {
+  }
+
+// Base class methods
+
+RttEstimator::RttEstimator () : next (1), history (), est (initialEstimate),
+    nSamples (0), multiplier (1.0) 
+{ 
+  //note next=1 everywhere since first segment will have sequence 1
+  SetInterfaceId (RttEstimator::iid);
+}
+
+RttEstimator::RttEstimator (Time e) : next (1), history (), est (e),
+    nSamples (0), multiplier (1.0) 
+{ 
+  SetInterfaceId (RttEstimator::iid);
+}
+
+RttEstimator::RttEstimator(const RttEstimator& c)
+  : next(c.next), history(c.history), est(c.est), nSamples(c.nSamples),
+    multiplier(c.multiplier)
+{
+  SetInterfaceId (RttEstimator::iid);
+}
+
+RttEstimator::~RttEstimator ()
+{
+}
+
+void RttEstimator::SentSeq (SequenceNumber s, uint32_t c)
+{ // Note that a particular sequence has been sent
+  if (s == next)
+    { // This is the next expected one, just log at end
+      history.push_back (RttHistory (s, c, Simulator::Now () ));
+      next = s + SequenceNumber (c); // Update next expected
+    }
+  else
+    { // This is a retransmit, find in list and mark as re-tx
+      for (RttHistory_t::iterator i = history.begin (); i != history.end (); ++i)
+        {
+          if ((s >= i->seq) && (s < (i->seq + SequenceNumber (i->count))))
+            { // Found it
+              i->retx = true;
+              // One final test..be sure this re-tx does not extend "next"
+              if ((s + SequenceNumber (c)) > next)
+                {
+                  next = s + SequenceNumber (c);
+                  i->count = ((s + SequenceNumber (c)) - i->seq); // And update count in hist
+                }
+              break;
+            }
+        }
+    }
+}
+
+Time RttEstimator::AckSeq (SequenceNumber a)
+{ // An ack has been received, calculate rtt and log this measurement
+  // Note we use a linear search (O(n)) for this since for the common
+  // case the ack'ed packet will be at the head of the list
+  Time m = Seconds (0.0);
+  if (history.size () == 0) return (m);    // No pending history, just exit
+  RttHistory& h = history.front ();
+  if (!h.retx && a >= (h.seq + SequenceNumber (h.count)))
+    { // Ok to use this sample
+      m = Simulator::Now () - h.time; // Elapsed time
+      Measurement(m);                // Log the measurement
+      ResetMultiplier();             // Reset multiplier on valid measurement
+    }
+  // Now delete all ack history with seq <= ack
+  while(history.size() > 0)
+    {
+      RttHistory& h = history.front ();
+      if ((h.seq + SequenceNumber(h.count)) > a) break;                // Done removing
+      history.pop_front (); // Remove
+    }
+  return m;
+}
+
+void RttEstimator::ClearSent ()
+{ // Clear all history entries
+  next = 1;
+  history.clear ();
+}
+
+void RttEstimator::IncreaseMultiplier ()
+{
+  multiplier = std::min (multiplier * 2.0, defaultMaxMultiplier.GetValue ());
+}
+
+void RttEstimator::ResetMultiplier ()
+{
+  multiplier = 1.0;
+}
+
+void RttEstimator::Reset ()
+{ // Reset to initial state
+  next = 1;
+  est = initialEstimate;
+  history.clear ();         // Remove all info from the history
+  nSamples = 0;
+  ResetMultiplier ();
+}
+
+// Base class, static methods
+void RttEstimator::InitialEstimate (Time e)
+{ // Set a new default initial estimate
+  initialEstimate = e;
+}
+
+Ptr<RttEstimator> RttEstimator::CreateDefault ()
+{
+  ClassId classId = defaultCid.GetValue ();
+  Ptr<RttEstimator> rtte = ComponentManager::Create<RttEstimator> (
+      classId, RttEstimator::iid, 0.1, initialEstimate
+                                                                  );
+  return rtte;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Mean-Deviation Estimator
+const ClassId RttMeanDeviation::cid = 
+    MakeClassId<RttMeanDeviation, double, Time> ("RttMeanDeviation",
+                                                 RttEstimator::iid);
+
+RttMeanDeviation::RttMeanDeviation(double g) :
+  gain (g), variance (ns3::Seconds(0)) 
+{ 
+}
+
+RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
+  : RttEstimator (c), gain (c.gain), variance (c.variance)
+{
+}
+
+RttMeanDeviation::RttMeanDeviation (double g, Time e) : 
+  RttEstimator (e), gain (g), variance (ns3::Seconds(0)) 
+{ 
+}
+
+void RttMeanDeviation::Measurement (Time m)
+{
+  if (nSamples)
+    { // Not first
+      Time err = m - est;
+      est = est + Scalar (gain) * err;         // estimated rtt
+      err = Abs (err);        // absolute value of error
+      variance = variance + Scalar (gain) * (err - variance); // variance of rtt
+    }
+  else
+    { // First sample
+      est = m;                        // Set estimate to current
+      //variance = m / 2;               // And variance to current / 2
+      variance = m; // try this
+    }
+  nSamples++;
+}
+
+Time RttMeanDeviation::RetransmitTimeout ()
+{
+  // If not enough samples, justjust return 2 times estimate   
+  //if (nSamples < 2) return est * 2;
+  if (variance < est / Scalar (4.0))
+    return est * Scalar (2 * multiplier);            // At least twice current est
+  return (est + Scalar (4) * variance) * Scalar (multiplier); // As suggested by Jacobson
+}
+
+RttEstimator* RttMeanDeviation::Copy () const
+{
+  return new RttMeanDeviation (*this);
+}
+
+void RttMeanDeviation::Reset ()
+{ // Reset to initial state
+  variance = Seconds (0.0);
+  RttEstimator::Reset ();
+}
+}//namepsace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/rtt-estimator.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley.  Georgia Tech, Spring 2002
+
+// Implements several variations of round trip time estimators
+
+#ifndef __rtt_estimator_h__
+#define __rtt_estimator_h__
+
+#include <deque>
+#include "sequence-number.h"
+#include "ns3/nstime.h"
+#include "ns3/object.h"
+#include "ns3/component-manager.h"
+
+namespace ns3 {
+
+class RttHistory {
+public:
+  RttHistory (SequenceNumber s, uint32_t c, Time t);
+  RttHistory (const RttHistory& h); // Copy constructor
+public:
+  SequenceNumber  seq;    // First sequence number in packet sent
+  uint32_t        count;  // Number of bytes sent
+  Time            time;   // Time this one was sent
+  bool            retx;   // True if this has been retransmitted
+};
+
+typedef std::deque<RttHistory> RttHistory_t;
+
+class RttEstimator : public Object {  //  Base class for all RTT Estimators
+public:
+  static const InterfaceId iid;
+
+  RttEstimator();
+  RttEstimator(Time e);
+  RttEstimator(const RttEstimator&); // Copy constructor
+  virtual ~RttEstimator();
+
+  virtual void SentSeq(SequenceNumber, uint32_t);
+  virtual Time AckSeq(SequenceNumber);
+  virtual void ClearSent();
+  virtual void   Measurement(Time t) = 0;
+  virtual Time Estimate() = 0;
+  virtual Time RetransmitTimeout() = 0;
+  void Init(SequenceNumber s) { next = s;}
+  virtual RttEstimator* Copy() const = 0;
+  virtual void IncreaseMultiplier();
+  virtual void ResetMultiplier();
+  virtual void Reset();
+
+private:
+  SequenceNumber        next;    // Next expected sequence to be sent
+  RttHistory_t history; // List of sent packet
+public:
+  Time       est;     // Current estimate
+  uint32_t      nSamples;// Number of samples
+  double       multiplier;   // RTO Multiplier
+public:
+  static void InitialEstimate(Time);
+  static Ptr<RttEstimator> CreateDefault();      // Retrieve current default
+
+  static ClassIdDefaultValue defaultCid;
+  static NumericDefaultValue<double> defaultMaxMultiplier;
+
+private:
+  static Time initialEstimate;       // Default initial estimate
+};
+
+// The "Mean-Deviation" estimator, as discussed by Van Jacobson
+// "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
+
+  //Doc:Class Class {\tt RttMeanDeviation} implements the "Mean--Deviation" estimator
+  //Doc:Class as described by Van Jacobson 
+  //Doc:Class "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
+class RttMeanDeviation : public RttEstimator {
+public :
+  static const ClassId cid;
+
+    //Doc:Desc Constructor for {\tt RttMeanDeviation} specifying the gain factor for the
+    //Doc:Desc estimator.
+    //Doc:Arg1 Gain factor.
+  RttMeanDeviation (double g);
+
+    //Doc:Desc Constructor for {\tt RttMeanDeviation} specifying the gain factor
+    //Doc:Desc and the initial estimate.
+    //Doc:Arg1 Gain factor.
+    //Doc:Arg2 Initial estimate.
+  RttMeanDeviation (double g, Time e);
+
+  //Doc:Method
+  RttMeanDeviation (const RttMeanDeviation&); // Copy constructor
+    //Doc:Desc Copy constructor.
+    //Doc:Arg1 {\tt RttMeanDeviation} object to copy.
+
+  void Measurement (Time);
+  Time Estimate () { return est;}
+  Time Variance () { return variance;}
+  Time RetransmitTimeout ();
+  RttEstimator* Copy () const;
+  void Reset ();
+  void Gain (double g) { gain = g;}
+
+public:
+  double       gain;       // Filter gain
+  Time       variance;   // Current variance
+};
+}//namespace ns3
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/sequence-number.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// Ported from:
+// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
+// George F. Riley.  Georgia Tech, Spring 2002
+
+// Class to manage arithmetic operations on sequence numbers (mod 2^32)
+
+#include "sequence-number.h"
+
+bool operator< (const SequenceNumber l, const SequenceNumber r) 
+{ // Account for 32 bit rollover
+  if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
+  return l.seq < r.seq;
+}
+
+bool operator<= (const SequenceNumber l, const SequenceNumber r) 
+{ // Account for 32 bit rollover
+  if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
+  return l.seq <= r.seq;
+}
+
+bool operator> (const SequenceNumber l, const SequenceNumber r) 
+{ // Account for 32 bit rollover
+  if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
+  return l.seq > r.seq;
+}
+
+bool operator>= (const SequenceNumber l, const SequenceNumber r) 
+{ // Account for 32 bit rollover
+  if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
+  return l.seq >= r.seq;
+}
+
+// Non-Member Arithmetic operators
+SequenceNumber  operator+ (const SequenceNumber l, const SequenceNumber r)
+{
+  return SequenceNumber (l.seq + r.seq);
+}
+
+SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r)
+{ // This assumes l is always bigger than r (allows for rollover)
+  if (l.seq >= r.seq) return SequenceNumber (l.seq-r.seq);
+  return SequenceNumber ((MAX_SEQ - r.seq) + l.seq + 1);  // Adjust for rollover
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/sequence-number.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Ported from:
+// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
+// George F. Riley.  Georgia Tech, Spring 2002
+
+// Class to manage arithmetic operations on sequence numbers (mod 2^32)
+
+#ifndef __seq_h__
+#define __seq_h__
+
+#include <stdint.h>
+
+#define MAX_SEQ ((uint32_t)0xffffffff)
+
+class SequenceNumber {
+public:
+  SequenceNumber () : seq(0) { }
+  SequenceNumber (const uint32_t s) : seq (s) { }
+
+  operator uint32_t () const { return seq;}
+
+  SequenceNumber& operator= (const uint32_t s) { seq = s; return *this;}
+
+  SequenceNumber& operator+= (const uint32_t s) { seq += s; return *this;}
+  SequenceNumber  operator++ ()              { seq++; return *this;}
+  SequenceNumber  operator++ (int)           { SequenceNumber ss (seq); seq++; return ss;}
+  SequenceNumber& operator-= (const uint32_t s) { seq -= s; return *this;}
+  SequenceNumber  operator-- ()              { seq--; return *this;}
+  SequenceNumber  operator-- (int)           { SequenceNumber ss (seq); seq--; return ss;}
+public:
+  uint32_t seq;
+};
+
+// Comparison operators
+
+bool operator< (const SequenceNumber l, const SequenceNumber r);
+bool operator<= (const SequenceNumber l, const SequenceNumber r); 
+bool operator> (const SequenceNumber l, const SequenceNumber r);
+bool operator>= (const SequenceNumber l, const SequenceNumber r);
+
+// Non-member arithmetic operators
+SequenceNumber  operator+ (const SequenceNumber l, const SequenceNumber r);
+SequenceNumber  operator- (const SequenceNumber l, const SequenceNumber r);
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-header.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,187 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#include <stdint.h>
+#include <iostream>
+#include "tcp-socket.h"
+#include "tcp-header.h"
+#include "ns3/buffer.h"
+
+namespace ns3 {
+
+NS_HEADER_ENSURE_REGISTERED (TcpHeader);
+
+bool TcpHeader::m_calcChecksum = false;
+
+uint32_t
+TcpHeader::GetUid (void)
+{
+  static uint32_t uid = AllocateUid<TcpHeader> ("TcpHeader.ns3");
+  return uid;
+}
+
+TcpHeader::TcpHeader ()
+  : m_sourcePort (0),
+    m_destinationPort (0),
+    m_sequenceNumber (0),
+    m_ackNumber (0),
+    m_length (5),
+    m_flags (0),
+    m_windowSize (Tcp::defaultAdvWin.GetValue ()),
+    m_checksum (0),
+    m_urgentPointer (0)
+{
+}
+
+TcpHeader::~TcpHeader ()
+{}
+
+void
+TcpHeader::EnableChecksums (void)
+{
+  m_calcChecksum = true;
+}
+
+void TcpHeader::SetSourcePort (uint16_t port)
+{
+  m_sourcePort = port;
+}
+void TcpHeader::SetDestinationPort (uint16_t port)
+{
+  m_destinationPort = port;
+}
+void TcpHeader::SetSequenceNumber (SequenceNumber sequenceNumber)
+{
+  m_sequenceNumber = sequenceNumber;
+}
+void TcpHeader::SetAckNumber (SequenceNumber ackNumber)
+{
+  m_ackNumber = ackNumber;
+}
+void TcpHeader::SetLength (uint8_t length)
+{
+  m_length = length;
+}
+void TcpHeader::SetFlags (uint8_t flags)
+{
+  m_flags = flags;
+}
+void TcpHeader::SetWindowSize (uint16_t windowSize)
+{
+  m_windowSize = windowSize;
+}
+void TcpHeader::SetChecksum (uint16_t checksum)
+{
+  m_checksum = checksum;
+}
+void TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
+{
+  m_urgentPointer = urgentPointer;
+}
+
+uint16_t TcpHeader::GetSourcePort () const
+{
+  return m_sourcePort;
+}
+uint16_t TcpHeader::GetDestinationPort () const
+{
+  return m_destinationPort;
+}
+SequenceNumber TcpHeader::GetSequenceNumber () const
+{
+  return m_sequenceNumber;
+}
+SequenceNumber TcpHeader::GetAckNumber () const
+{
+  return m_ackNumber;
+}
+uint8_t  TcpHeader::GetLength () const
+{
+  return m_length;
+}
+uint8_t  TcpHeader::GetFlags () const
+{
+  return m_flags;
+}
+uint16_t TcpHeader::GetWindowSize () const
+{
+  return m_windowSize;
+}
+uint16_t TcpHeader::GetChecksum () const
+{
+  return m_checksum;
+}
+uint16_t TcpHeader::GetUrgentPointer () const
+{
+  return m_urgentPointer;
+}
+
+void 
+TcpHeader::InitializeChecksum (Ipv4Address source, 
+                                   Ipv4Address destination,
+                                   uint8_t protocol)
+{
+  m_checksum = 0;
+//XXX requires peeking into IP to get length of the TCP segment
+}
+
+std::string 
+TcpHeader::GetName (void) const
+{
+  return "TCP";
+}
+
+void TcpHeader::Print (std::ostream &os)  const
+{
+  //XXX
+}
+uint32_t TcpHeader::GetSerializedSize (void)  const
+{
+  return 20;  //tcp headers are 20 bytes
+}
+void TcpHeader::Serialize (Buffer::Iterator start)  const
+{
+  start.WriteHtonU16 (m_sourcePort);
+  start.WriteHtonU16 (m_destinationPort);
+  start.WriteHtonU32 (m_sequenceNumber);
+  start.WriteHtonU32 (m_ackNumber);
+  start.WriteHtonU16 (m_length << 12 | m_flags); //reserved bits are all zero
+  start.WriteHtonU16 (m_windowSize);
+  //XXX calculate checksum here
+  start.WriteHtonU16 (m_checksum);
+  start.WriteHtonU16 (m_urgentPointer);
+}
+uint32_t TcpHeader::Deserialize (Buffer::Iterator start)
+{
+  m_sourcePort = start.ReadNtohU16 ();
+  m_destinationPort = start.ReadNtohU16 ();
+  m_sequenceNumber = start.ReadNtohU32 ();
+  m_ackNumber = start.ReadNtohU32 ();
+  uint16_t field = start.ReadNtohU16 ();
+  m_flags = field & 0x3F;
+  m_length = field>>12;
+  m_windowSize = start.ReadNtohU16 ();
+  m_checksum = start.ReadNtohU16 ();
+  m_urgentPointer = start.ReadNtohU16 ();
+  return GetSerializedSize ();
+}
+
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-header.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,161 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#ifndef TCP_HEADER_H
+#define TCP_HEADER_H
+
+#include <stdint.h>
+#include "ns3/header.h"
+#include "ns3/buffer.h"
+#include "ns3/tcp.h"
+#include "ns3/ipv4-address.h"
+#include "sequence-number.h"
+
+namespace ns3 {
+
+class TcpHeader : public Header {
+public:
+  static uint32_t GetUid (void);
+
+  TcpHeader ();
+  virtual ~TcpHeader ();
+
+  /**
+   * \brief Enable checksum calculation for TCP (XXX currently has no effect)
+   */
+  static void EnableChecksums (void);
+//Setters
+  /**
+   * \param port The source port for this TcpHeader
+   */
+  void SetSourcePort (uint16_t port);
+  /**
+   * \param port the destination port for this TcpHeader
+   */
+  void SetDestinationPort (uint16_t port);
+  /**
+   * \param sequenceNumber the sequence number for this TcpHeader
+   */
+  void SetSequenceNumber (SequenceNumber sequenceNumber);
+  /**
+   * \param ackNumber the ACK number for this TcpHeader
+   */
+  void SetAckNumber (SequenceNumber ackNumber);
+  /**
+   * \param length the length of this TcpHeader
+   */
+  void SetLength (uint8_t length);
+  /**
+   * \param flags the flags for this TcpHeader
+   */
+  void SetFlags (uint8_t flags);
+  /**
+   * \param windowSize the window size for this TcpHeader
+   */
+  void SetWindowSize (uint16_t windowSize);
+  /**
+   * \param checksum the checksum for this TcpHeader
+   */
+  void SetChecksum (uint16_t checksum);
+  /**
+   * \param urgentPointer the urgent pointer for this TcpHeader
+   */
+  void SetUrgentPointer (uint16_t urgentPointer);
+
+
+//Getters
+  /**
+   * \return The source port for this TcpHeader
+   */
+  uint16_t GetSourcePort () const;
+  /**
+   * \return the destination port for this TcpHeader
+   */
+  uint16_t GetDestinationPort () const;
+  /**
+   * \return the sequence number for this TcpHeader
+   */
+  SequenceNumber GetSequenceNumber () const;
+  /**
+   * \return the ACK number for this TcpHeader
+   */
+  SequenceNumber GetAckNumber () const;
+  /**
+   * \return the length of this TcpHeader
+   */
+  uint8_t  GetLength () const;
+  /**
+   * \return the flags for this TcpHeader
+   */
+  uint8_t  GetFlags () const;
+  /**
+   * \return the window size for this TcpHeader
+   */
+  uint16_t GetWindowSize () const;
+  /**
+   * \return the checksum for this TcpHeader
+   */
+  uint16_t GetChecksum () const;
+  /**
+   * \return the urgent pointer for this TcpHeader
+   */
+  uint16_t GetUrgentPointer () const;
+
+  /**
+   * \param source the ip source to use in the underlying
+   *        ip packet.
+   * \param destination the ip destination to use in the
+   *        underlying ip packet.
+   * \param protocol the protocol number to use in the underlying
+   *        ip packet.
+   *
+   * If you want to use tcp checksums, you should call this
+   * method prior to adding the header to a packet.
+   */
+  void InitializeChecksum (Ipv4Address source, 
+                           Ipv4Address destination,
+                           uint8_t protocol);
+
+  typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16, 
+    URG = 32} Flags_t;
+
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+  uint16_t m_sourcePort;
+  uint16_t m_destinationPort;
+  uint32_t m_sequenceNumber;
+  uint32_t m_ackNumber;
+  uint8_t m_length; // really a uint4_t
+  uint8_t m_flags;      // really a uint6_t
+  uint16_t m_windowSize;
+  uint16_t m_checksum;
+  uint16_t m_urgentPointer;
+
+  static bool m_calcChecksum;
+};
+
+}; // namespace ns3
+
+#endif /* TCP_HEADER */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-impl.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,48 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#include "tcp-impl.h"
+#include "tcp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+TcpImpl::TcpImpl (Ptr<TcpL4Protocol> tcp)
+  : m_tcp (tcp)
+{}
+TcpImpl::~TcpImpl ()
+{
+  NS_ASSERT (m_tcp == 0);
+}
+
+Ptr<Socket>
+TcpImpl::CreateSocket (void)
+{
+  return m_tcp->CreateSocket ();
+}
+
+void 
+TcpImpl::DoDispose (void)
+{
+  m_tcp = 0;
+  Tcp::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-impl.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_IMPL_H
+#define TCP_IMPL_H
+
+#include "ns3/tcp.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class TcpL4Protocol;
+
+/**
+ * \ingroup InternetNode
+ * \defgroup Tcp Tcp
+ *
+ * \section Tcp Overview
+ *
+ * The TCP code in ns3::InternetNode is ported from the  
+ * <a href="http://www.ece.gatech.edu/research/labs/MANIACS/GTNetS/">
+ * Georgia Tech Network Simulator (GTNetS)</a>.
+ * 
+ * Most of the logic is in class ns3::TcpSocket.
+ */
+class TcpImpl : public Tcp
+{
+public:
+  TcpImpl (Ptr<TcpL4Protocol> tcp);
+  virtual ~TcpImpl ();
+
+  virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+  virtual void DoDispose (void);
+private:
+  Ptr<TcpL4Protocol> m_tcp;
+};
+
+} // namespace ns3
+
+#endif /* TCP_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-l4-protocol.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,485 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "ns3/packet.h"
+#include "ns3/node.h"
+
+#include "tcp-l4-protocol.h"
+#include "tcp-header.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l3-protocol.h"
+#include "tcp-socket.h"
+
+#include "tcp-typedefs.h"
+
+#include <vector>
+#include <sstream>
+
+NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol");
+
+namespace ns3 {
+
+//State Machine things --------------------------------------------------------
+TcpStateMachine::TcpStateMachine() 
+  : aT (LAST_STATE, StateActionVec_t(LAST_EVENT)),
+       eV (MAX_FLAGS)
+{ 
+  NS_LOG_FUNCTION;
+
+  // Create the state table
+  // Closed state
+  aT[CLOSED][APP_LISTEN]  = SA (LISTEN,   NO_ACT);
+  aT[CLOSED][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+  aT[CLOSED][APP_SEND]    = SA (CLOSED,   RST_TX);
+  aT[CLOSED][SEQ_RECV]    = SA (CLOSED,   NO_ACT);
+  aT[CLOSED][APP_CLOSE]   = SA (CLOSED,   NO_ACT);
+  aT[CLOSED][TIMEOUT]     = SA (CLOSED,   RST_TX);
+  aT[CLOSED][ACK_RX]      = SA (CLOSED,   RST_TX);
+  aT[CLOSED][SYN_RX]      = SA (CLOSED,   RST_TX);
+  aT[CLOSED][SYN_ACK_RX]  = SA (CLOSED,   RST_TX);
+  aT[CLOSED][FIN_RX]      = SA (CLOSED,   RST_TX);
+  aT[CLOSED][FIN_ACK_RX]  = SA (CLOSED,   RST_TX);
+  aT[CLOSED][RST_RX]      = SA (CLOSED,   CANCEL_TM);
+  aT[CLOSED][BAD_FLAGS]   = SA (CLOSED,   RST_TX);
+
+  // Listen State
+  // For the listen state, anything other than CONNECT or SEND
+  // is simply ignored....this likely indicates the child TCP
+  // has finished and issued unbind call, but the remote end
+  // has not yet  closed.
+  aT[LISTEN][APP_LISTEN]  = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+  aT[LISTEN][APP_SEND]    = SA (SYN_SENT, SYN_TX);
+  aT[LISTEN][SEQ_RECV]    = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][APP_CLOSE]   = SA (CLOSED,   NO_ACT);
+  aT[LISTEN][TIMEOUT]     = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][ACK_RX]      = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][SYN_RX]      = SA (SYN_RCVD,   SYN_ACK_TX);  //XXX hacked for now, should stay in listen and replicate
+  aT[LISTEN][SYN_ACK_RX]  = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][FIN_RX]      = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][FIN_ACK_RX]  = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][RST_RX]      = SA (LISTEN,   NO_ACT);
+  aT[LISTEN][BAD_FLAGS]   = SA (LISTEN,   NO_ACT);
+
+  // Syn Sent State
+  aT[SYN_SENT][APP_LISTEN]  = SA (CLOSED,      RST_TX);
+  aT[SYN_SENT][APP_CONNECT] = SA (SYN_SENT,    SYN_TX);
+  aT[SYN_SENT][APP_SEND]    = SA (SYN_SENT,    NO_ACT);
+  aT[SYN_SENT][SEQ_RECV]    = SA (ESTABLISHED, NEW_SEQ_RX);
+  aT[SYN_SENT][APP_CLOSE]   = SA (CLOSED,      RST_TX);
+  aT[SYN_SENT][TIMEOUT]     = SA (CLOSED,      NO_ACT);
+  aT[SYN_SENT][ACK_RX]      = SA (SYN_SENT,    NO_ACT);
+  aT[SYN_SENT][SYN_RX]      = SA (SYN_RCVD,    SYN_ACK_TX);
+  aT[SYN_SENT][SYN_ACK_RX]  = SA (ESTABLISHED, ACK_TX_1);
+  aT[SYN_SENT][FIN_RX]      = SA (CLOSED,      RST_TX);
+  aT[SYN_SENT][FIN_ACK_RX]  = SA (CLOSED,      RST_TX);
+  aT[SYN_SENT][RST_RX]      = SA (CLOSED,      APP_NOTIFY);
+  aT[SYN_SENT][BAD_FLAGS]   = SA (CLOSED,      RST_TX);
+
+  // Syn Recvd State
+  aT[SYN_RCVD][APP_LISTEN]  = SA (CLOSED,      RST_TX);
+  aT[SYN_RCVD][APP_CONNECT] = SA (CLOSED,      RST_TX);
+  aT[SYN_RCVD][APP_SEND]    = SA (CLOSED,      RST_TX);
+  aT[SYN_RCVD][SEQ_RECV]    = SA (ESTABLISHED, NEW_SEQ_RX);
+  aT[SYN_RCVD][APP_CLOSE]   = SA (FIN_WAIT_1,  FIN_TX);
+  aT[SYN_RCVD][TIMEOUT]     = SA (CLOSED,      RST_TX);
+  aT[SYN_RCVD][ACK_RX]      = SA (ESTABLISHED, SERV_NOTIFY);
+  aT[SYN_RCVD][SYN_RX]      = SA (SYN_RCVD,    SYN_ACK_TX);
+  aT[SYN_RCVD][SYN_ACK_RX]  = SA (CLOSED,      RST_TX);
+  aT[SYN_RCVD][FIN_RX]      = SA (CLOSED,      RST_TX);
+  aT[SYN_RCVD][FIN_ACK_RX]  = SA (CLOSE_WAIT,  PEER_CLOSE);
+  aT[SYN_RCVD][RST_RX]      = SA (CLOSED,      CANCEL_TM);
+  aT[SYN_RCVD][BAD_FLAGS]   = SA (CLOSED,      RST_TX);
+
+  // Established State
+  aT[ESTABLISHED][APP_LISTEN] = SA (CLOSED,     RST_TX);
+  aT[ESTABLISHED][APP_CONNECT]= SA (CLOSED,     RST_TX);
+  aT[ESTABLISHED][APP_SEND]   = SA (ESTABLISHED,TX_DATA);
+  aT[ESTABLISHED][SEQ_RECV]   = SA (ESTABLISHED,NEW_SEQ_RX);
+  aT[ESTABLISHED][APP_CLOSE]  = SA (FIN_WAIT_1, FIN_TX);
+  aT[ESTABLISHED][TIMEOUT]    = SA (ESTABLISHED,RETX);
+  aT[ESTABLISHED][ACK_RX]     = SA (ESTABLISHED,NEW_ACK);
+  aT[ESTABLISHED][SYN_RX]     = SA (SYN_RCVD,   SYN_ACK_TX);
+  aT[ESTABLISHED][SYN_ACK_RX] = SA (ESTABLISHED,NO_ACT);
+  aT[ESTABLISHED][FIN_RX]     = SA (CLOSE_WAIT, PEER_CLOSE);
+  aT[ESTABLISHED][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
+  aT[ESTABLISHED][RST_RX]     = SA (CLOSED,     CANCEL_TM);
+  aT[ESTABLISHED][BAD_FLAGS]  = SA (CLOSED,     RST_TX);
+
+  // Close Wait State
+  aT[CLOSE_WAIT][APP_LISTEN]  = SA (CLOSED,     RST_TX);
+  aT[CLOSE_WAIT][APP_CONNECT] = SA (SYN_SENT,   SYN_TX);
+  aT[CLOSE_WAIT][APP_SEND]    = SA (CLOSE_WAIT, TX_DATA);
+  aT[CLOSE_WAIT][SEQ_RECV]    = SA (CLOSE_WAIT, NEW_SEQ_RX);
+  aT[CLOSE_WAIT][APP_CLOSE]   = SA (LAST_ACK,   FIN_ACK_TX);
+  aT[CLOSE_WAIT][TIMEOUT]     = SA (CLOSE_WAIT, NO_ACT);
+  aT[CLOSE_WAIT][ACK_RX]      = SA (CLOSE_WAIT, NO_ACT);
+  aT[CLOSE_WAIT][SYN_RX]      = SA (CLOSED,     RST_TX);
+  aT[CLOSE_WAIT][SYN_ACK_RX]  = SA (CLOSED,     RST_TX);
+  aT[CLOSE_WAIT][FIN_RX]      = SA (CLOSE_WAIT, ACK_TX);
+  aT[CLOSE_WAIT][FIN_ACK_RX]  = SA (CLOSE_WAIT, ACK_TX);
+  aT[CLOSE_WAIT][RST_RX]      = SA (CLOSED,     CANCEL_TM);
+  aT[CLOSE_WAIT][BAD_FLAGS]   = SA (CLOSED,     RST_TX);
+
+  // Close Last Ack State
+  aT[LAST_ACK][APP_LISTEN]  = SA (CLOSED,      RST_TX);
+  aT[LAST_ACK][APP_CONNECT] = SA (SYN_SENT,    SYN_TX);
+  aT[LAST_ACK][APP_SEND]    = SA (CLOSED,      RST_TX);
+  aT[LAST_ACK][SEQ_RECV]    = SA (LAST_ACK,    NEW_SEQ_RX);
+  aT[LAST_ACK][APP_CLOSE]   = SA (CLOSED,      NO_ACT);
+  aT[LAST_ACK][TIMEOUT]     = SA (CLOSED,      NO_ACT);
+  aT[LAST_ACK][ACK_RX]      = SA (CLOSED,      APP_CLOSED);
+  aT[LAST_ACK][SYN_RX]      = SA (CLOSED,      RST_TX);
+  aT[LAST_ACK][SYN_ACK_RX]  = SA (CLOSED,      RST_TX);
+  aT[LAST_ACK][FIN_RX]      = SA (LAST_ACK,    FIN_ACK_TX);
+  aT[LAST_ACK][FIN_ACK_RX]  = SA (CLOSED,      NO_ACT);
+  aT[LAST_ACK][RST_RX]      = SA (CLOSED,      CANCEL_TM);
+  aT[LAST_ACK][BAD_FLAGS]   = SA (CLOSED,      RST_TX);
+
+  // FIN_WAIT_1 state
+  aT[FIN_WAIT_1][APP_LISTEN]  = SA (CLOSED,     RST_TX);
+  aT[FIN_WAIT_1][APP_CONNECT] = SA (CLOSED,     RST_TX);
+  aT[FIN_WAIT_1][APP_SEND]    = SA (CLOSED,     RST_TX);
+  aT[FIN_WAIT_1][SEQ_RECV]    = SA (FIN_WAIT_1, NEW_SEQ_RX);
+  aT[FIN_WAIT_1][APP_CLOSE]   = SA (FIN_WAIT_1, NO_ACT);
+  aT[FIN_WAIT_1][TIMEOUT]     = SA (FIN_WAIT_1, NO_ACT);
+  aT[FIN_WAIT_1][ACK_RX]      = SA (FIN_WAIT_2, NEW_ACK);
+  aT[FIN_WAIT_1][SYN_RX]      = SA (CLOSED,     RST_TX);
+  aT[FIN_WAIT_1][SYN_ACK_RX]  = SA (CLOSED,     RST_TX);
+  aT[FIN_WAIT_1][FIN_RX]      = SA (CLOSING,    ACK_TX);
+  aT[FIN_WAIT_1][FIN_ACK_RX]  = SA (TIMED_WAIT, ACK_TX);
+  aT[FIN_WAIT_1][RST_RX]      = SA (CLOSED,     CANCEL_TM);
+  aT[FIN_WAIT_1][BAD_FLAGS]   = SA (CLOSED,     RST_TX);
+
+  // FIN_WAIT_2 state
+  aT[FIN_WAIT_2][APP_LISTEN]  = SA (CLOSED,      RST_TX);
+  aT[FIN_WAIT_2][APP_CONNECT] = SA (CLOSED,      RST_TX);
+  aT[FIN_WAIT_2][APP_SEND]    = SA (CLOSED,      RST_TX);
+  aT[FIN_WAIT_2][SEQ_RECV]    = SA (FIN_WAIT_2,  NO_ACT);
+  aT[FIN_WAIT_2][APP_CLOSE]   = SA (FIN_WAIT_2,  NO_ACT);
+  aT[FIN_WAIT_2][TIMEOUT]     = SA (FIN_WAIT_2,  NO_ACT);
+  aT[FIN_WAIT_2][ACK_RX]      = SA (FIN_WAIT_2,  NEW_ACK);
+  aT[FIN_WAIT_2][SYN_RX]      = SA (CLOSED,      RST_TX);
+  aT[FIN_WAIT_2][SYN_ACK_RX]  = SA (CLOSED,      RST_TX);
+  aT[FIN_WAIT_2][FIN_RX]      = SA (TIMED_WAIT,  ACK_TX);
+  aT[FIN_WAIT_2][FIN_ACK_RX]  = SA (TIMED_WAIT,  ACK_TX);
+  aT[FIN_WAIT_2][RST_RX]      = SA (CLOSED,      CANCEL_TM);
+  aT[FIN_WAIT_2][BAD_FLAGS]   = SA (CLOSED,      RST_TX);
+
+  // CLOSING state
+  aT[CLOSING][APP_LISTEN]  = SA (CLOSED,      RST_TX);
+  aT[CLOSING][APP_CONNECT] = SA (CLOSED,      RST_TX);
+  aT[CLOSING][APP_SEND]    = SA (CLOSED,      RST_TX);
+  aT[CLOSING][SEQ_RECV]    = SA (CLOSED,      RST_TX);
+  aT[CLOSING][APP_CLOSE]   = SA (CLOSED,      RST_TX);
+  aT[CLOSING][TIMEOUT]     = SA (CLOSING,     NO_ACT);
+  aT[CLOSING][ACK_RX]      = SA (TIMED_WAIT,  NO_ACT);
+  aT[CLOSING][SYN_RX]      = SA (CLOSED,      RST_TX);
+  aT[CLOSING][SYN_ACK_RX]  = SA (CLOSED,      RST_TX);
+  aT[CLOSING][FIN_RX]      = SA (CLOSED,      ACK_TX);
+  aT[CLOSING][FIN_ACK_RX]  = SA (CLOSED,      ACK_TX);
+  aT[CLOSING][RST_RX]      = SA (CLOSED,      CANCEL_TM);
+  aT[CLOSING][BAD_FLAGS]   = SA (CLOSED,      RST_TX);
+
+  // TIMED_WAIT state
+  aT[TIMED_WAIT][APP_LISTEN]  = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][APP_CONNECT] = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][APP_SEND]    = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][SEQ_RECV]    = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][APP_CLOSE]   = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][TIMEOUT]     = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][ACK_RX]      = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][SYN_RX]      = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][SYN_ACK_RX]  = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][FIN_RX]      = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][FIN_ACK_RX]  = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][RST_RX]      = SA (TIMED_WAIT, NO_ACT);
+  aT[TIMED_WAIT][BAD_FLAGS]   = SA (TIMED_WAIT, NO_ACT);
+
+  // Create the flags lookup table
+  eV[ 0x00] = SEQ_RECV;  // No flags
+  eV[ 0x01] = FIN_RX;    // Fin
+  eV[ 0x02] = SYN_RX;    // Syn
+  eV[ 0x03] = BAD_FLAGS; // Illegal
+  eV[ 0x04] = RST_RX;    // Rst
+  eV[ 0x05] = BAD_FLAGS; // Illegal
+  eV[ 0x06] = BAD_FLAGS; // Illegal
+  eV[ 0x07] = BAD_FLAGS; // Illegal
+  eV[ 0x08] = SEQ_RECV;  // Psh flag is not used
+  eV[ 0x09] = FIN_RX;    // Fin
+  eV[ 0x0a] = SYN_RX;    // Syn
+  eV[ 0x0b] = BAD_FLAGS; // Illegal
+  eV[ 0x0c] = RST_RX;    // Rst
+  eV[ 0x0d] = BAD_FLAGS; // Illegal
+  eV[ 0x0e] = BAD_FLAGS; // Illegal
+  eV[ 0x0f] = BAD_FLAGS; // Illegal
+  eV[ 0x10] = ACK_RX;    // Ack
+  eV[ 0x11] = FIN_ACK_RX;// Fin/Ack
+  eV[ 0x12] = SYN_ACK_RX;// Syn/Ack
+  eV[ 0x13] = BAD_FLAGS; // Illegal
+  eV[ 0x14] = RST_RX;    // Rst
+  eV[ 0x15] = BAD_FLAGS; // Illegal
+  eV[ 0x16] = BAD_FLAGS; // Illegal
+  eV[ 0x17] = BAD_FLAGS; // Illegal
+  eV[ 0x18] = ACK_RX;    // Ack
+  eV[ 0x19] = FIN_ACK_RX;// Fin/Ack
+  eV[ 0x1a] = SYN_ACK_RX;// Syn/Ack
+  eV[ 0x1b] = BAD_FLAGS; // Illegal
+  eV[ 0x1c] = RST_RX;    // Rst
+  eV[ 0x1d] = BAD_FLAGS; // Illegal
+  eV[ 0x1e] = BAD_FLAGS; // Illegal
+  eV[ 0x1f] = BAD_FLAGS; // Illegal
+  eV[ 0x20] = SEQ_RECV;  // No flags (Urgent not presently used)
+  eV[ 0x21] = FIN_RX;    // Fin
+  eV[ 0x22] = SYN_RX;    // Syn
+  eV[ 0x23] = BAD_FLAGS; // Illegal
+  eV[ 0x24] = RST_RX;    // Rst
+  eV[ 0x25] = BAD_FLAGS; // Illegal
+  eV[ 0x26] = BAD_FLAGS; // Illegal
+  eV[ 0x27] = BAD_FLAGS; // Illegal
+  eV[ 0x28] = SEQ_RECV;  // Psh flag is not used
+  eV[ 0x29] = FIN_RX;    // Fin
+  eV[ 0x2a] = SYN_RX;    // Syn
+  eV[ 0x2b] = BAD_FLAGS; // Illegal
+  eV[ 0x2c] = RST_RX;    // Rst
+  eV[ 0x2d] = BAD_FLAGS; // Illegal
+  eV[ 0x2e] = BAD_FLAGS; // Illegal
+  eV[ 0x2f] = BAD_FLAGS; // Illegal
+  eV[ 0x30] = ACK_RX;    // Ack (Urgent not used)
+  eV[ 0x31] = FIN_ACK_RX;// Fin/Ack
+  eV[ 0x32] = SYN_ACK_RX;// Syn/Ack
+  eV[ 0x33] = BAD_FLAGS; // Illegal
+  eV[ 0x34] = RST_RX;    // Rst
+  eV[ 0x35] = BAD_FLAGS; // Illegal
+  eV[ 0x36] = BAD_FLAGS; // Illegal
+  eV[ 0x37] = BAD_FLAGS; // Illegal
+  eV[ 0x38] = ACK_RX;    // Ack
+  eV[ 0x39] = FIN_ACK_RX;// Fin/Ack
+  eV[ 0x3a] = SYN_ACK_RX;// Syn/Ack
+  eV[ 0x3b] = BAD_FLAGS; // Illegal
+  eV[ 0x3c] = RST_RX;    // Rst
+  eV[ 0x3d] = BAD_FLAGS; // Illegal
+  eV[ 0x3e] = BAD_FLAGS; // Illegal
+  eV[ 0x3f] = BAD_FLAGS; // Illegal
+}
+
+SA TcpStateMachine::Lookup (States_t s, Events_t e)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << s << e);
+  return aT[s][e];
+}
+
+Events_t TcpStateMachine::FlagsEvent (uint8_t f)
+{ 
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << f);
+  // Lookup event from flags
+  if (f >= MAX_FLAGS) return BAD_FLAGS;
+  return eV[f]; // Look up flags event
+}
+
+static TcpStateMachine tcpStateMachine; //only instance of a TcpStateMachine
+
+//TcpL4Protocol stuff----------------------------------------------------------
+
+
+/* see http://www.iana.org/assignments/protocol-numbers */
+const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
+
+TcpL4Protocol::TcpL4Protocol (Ptr<Node> node)
+  : Ipv4L4Protocol (PROT_NUMBER, 2),
+    m_node (node),
+    m_endPoints (new Ipv4EndPointDemux ())
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << node);
+  NS_LOG_LOGIC("Made a TcpL4Protocol "<<this);
+}
+
+TcpL4Protocol::~TcpL4Protocol ()
+{
+  NS_LOG_FUNCTION;
+ }
+
+void
+TcpL4Protocol::DoDispose (void)
+{
+  NS_LOG_FUNCTION;
+  if (m_endPoints != 0)
+    {
+      delete m_endPoints;
+      m_endPoints = 0;
+    }
+  m_node = 0;
+  Ipv4L4Protocol::DoDispose ();
+}
+
+Ptr<Socket>
+TcpL4Protocol::CreateSocket (void)
+{
+  NS_LOG_FUNCTION;
+  Ptr<Socket> socket = Create<TcpSocket> (m_node, this);
+  return socket;
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (void)
+{
+  NS_LOG_FUNCTION;
+  return m_endPoints->Allocate ();
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address address)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << address);
+  return m_endPoints->Allocate (address);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (uint16_t port)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << port);
+  return m_endPoints->Allocate (port);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << address << port);
+  return m_endPoints->Allocate (address, port);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
+               Ipv4Address peerAddress, uint16_t peerPort)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << localAddress << localPort << peerAddress << peerPort);
+  return m_endPoints->Allocate (localAddress, localPort,
+                                peerAddress, peerPort);
+}
+
+void 
+TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << endPoint);
+  m_endPoints->DeAllocate (endPoint);
+}
+
+void 
+TcpL4Protocol::Receive (Ptr<Packet> packet,
+             Ipv4Address const &source,
+             Ipv4Address const &destination,
+             Ptr<Ipv4Interface> incomingInterface)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << packet << source << destination << incomingInterface);
+
+  TcpHeader tcpHeader;
+  //these two do a peek, so that the packet can be forwarded up
+  packet->RemoveHeader (tcpHeader);
+  packet->AddHeader (tcpHeader); 
+  NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
+  Ipv4EndPointDemux::EndPoints endPoints =
+    m_endPoints->Lookup (destination, tcpHeader.GetDestinationPort (),
+                         source, tcpHeader.GetSourcePort (),incomingInterface);
+  if (endPoints.empty ())
+  {
+    NS_LOG_LOGIC ("  No endpoints matched on TcpL4Protocol "<<this);
+    std::ostringstream oss;
+    oss<<"  destination IP: ";
+    destination.Print (oss);
+    oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
+    source.Print (oss);
+    oss<<" source port: "<<tcpHeader.GetSourcePort ();
+    NS_LOG_LOGIC (oss.str ());
+  }
+  for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
+       endPoint != endPoints.end (); endPoint++)
+    {
+      NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
+      (*endPoint)->ForwardUp (packet, source, tcpHeader.GetSourcePort ());
+    }
+}
+
+void
+TcpL4Protocol::Send (Ptr<Packet> packet, 
+           Ipv4Address saddr, Ipv4Address daddr, 
+           uint16_t sport, uint16_t dport)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << packet << saddr << daddr << sport << dport);
+
+  TcpHeader tcpHeader;
+  tcpHeader.SetDestinationPort (dport);
+  tcpHeader.SetSourcePort (sport);
+  tcpHeader.InitializeChecksum (saddr,
+                               daddr,
+                               PROT_NUMBER);
+  tcpHeader.SetFlags (TcpHeader::ACK);
+  tcpHeader.SetAckNumber (0);
+
+  packet->AddHeader (tcpHeader);
+
+  Ptr<Ipv4L3Protocol> ipv4 = 
+    m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
+  if (ipv4 != 0)
+    {
+      ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+    }
+}
+
+void
+TcpL4Protocol::SendPacket (Ptr<Packet> packet, TcpHeader outgoingHeader,
+                               Ipv4Address saddr, Ipv4Address daddr)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << packet << saddr << daddr);
+  // XXX outgoingHeader cannot be logged
+
+  outgoingHeader.SetLength (5); //header length in units of 32bit words
+  outgoingHeader.SetChecksum (0);  //XXX
+  outgoingHeader.SetUrgentPointer (0); //XXX
+
+  packet->AddHeader (outgoingHeader);
+
+  Ptr<Ipv4L3Protocol> ipv4 = 
+    m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
+  if (ipv4 != 0)
+    {
+      ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+    }
+  else
+    NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface");
+}
+
+}; // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-l4-protocol.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,111 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#ifndef TCP_L4_PROTOCOL_H
+#define TCP_L4_PROTOCOL_H
+
+#include <stdint.h>
+
+#include "ns3/packet.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-l4-protocol.h"
+#include "ipv4-interface.h"
+
+#include "tcp-header.h"
+#include "tcp-typedefs.h"
+
+namespace ns3 {
+
+class Node;
+class TraceResolver;
+class TraceContext;
+class Socket;
+class TcpHeader;
+/**
+ * \brief Implementation of the TCP protocol
+ */
+class TcpL4Protocol : public Ipv4L4Protocol {
+public:
+  static const uint8_t PROT_NUMBER;
+  /**
+   * \brief Constructor
+   * \param node The node this protocol is associated with
+   */
+  TcpL4Protocol (Ptr<Node> node);
+  virtual ~TcpL4Protocol ();
+
+  /**
+   * \return A smart Socket pointer to a TcpSocket, allocated by this instance
+   * of the TCP protocol
+   */
+  Ptr<Socket> CreateSocket (void);
+
+  Ipv4EndPoint *Allocate (void);
+  Ipv4EndPoint *Allocate (Ipv4Address address);
+  Ipv4EndPoint *Allocate (uint16_t port);
+  Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
+  Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
+                         Ipv4Address peerAddress, uint16_t peerPort);
+
+  void DeAllocate (Ipv4EndPoint *endPoint);
+
+//   // called by TcpSocket.
+//   bool Connect (const Ipv4Address& saddr, const Ipv4Address& daddr,
+//                 uint16_t sport, uint16_t dport);
+
+  /**
+   * \brief Send a packet via TCP
+   * \param packet The packet to send
+   * \param saddr The source Ipv4Address
+   * \param daddr The destination Ipv4Address
+   * \param sport The source port number
+   * \param dport The destination port number
+   */
+  void Send (Ptr<Packet> packet,
+             Ipv4Address saddr, Ipv4Address daddr, 
+             uint16_t sport, uint16_t dport);
+  /**
+   * \brief Recieve a packet up the protocol stack
+   * \param p The Packet to dump the contents into
+   * \param source The source's Ipv4Address
+   * \param destination The destinations Ipv4Address
+   * \param incomingInterface The Ipv4Interface it was received on
+   */
+  virtual void Receive (Ptr<Packet> p,
+                       Ipv4Address const &source,
+                       Ipv4Address const &destination,
+                       Ptr<Ipv4Interface> incomingInterface);
+
+protected:
+  virtual void DoDispose (void);
+private:
+  Ptr<Node> m_node;
+  Ipv4EndPointDemux *m_endPoints;
+private:
+  friend class TcpSocket;
+  void SendPacket (Ptr<Packet>, TcpHeader,
+                  Ipv4Address, Ipv4Address);
+};
+
+}; // namespace ns3
+
+#endif /* TCP_L4_PROTOCOL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,1077 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/log.h"
+#include "ns3/ipv4.h"
+#include "tcp-socket.h"
+#include "tcp-l4-protocol.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l4-demux.h"
+#include "ns3/simulation-singleton.h"
+#include "tcp-typedefs.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/default-value.h"
+
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("TcpSocket");
+
+using namespace std;
+
+namespace ns3 {
+
+TcpSocket::TcpSocket (Ptr<Node> node, Ptr<TcpL4Protocol> tcp)
+  : m_skipRetxResched (false),
+    m_dupAckCount (0),
+    m_endPoint (0),
+    m_node (node),
+    m_tcp (tcp),
+    m_errno (ERROR_NOTERROR),
+    m_shutdownSend (false),
+    m_shutdownRecv (false),
+    m_connected (false),
+    m_state (CLOSED),
+    m_closeNotified (false),
+    m_closeRequestNotified (false),
+    m_closeOnEmpty (false),
+    m_nextTxSequence (0),
+    m_highTxMark (0),
+    m_highestRxAck (0),
+    m_lastRxAck (0),
+    m_nextRxSequence (0),
+    m_pendingData (0),
+    m_segmentSize (Tcp::defaultSegSize.GetValue()),
+    m_rxWindowSize (Tcp::defaultAdvWin.GetValue()),
+    m_advertisedWindowSize (Tcp::defaultAdvWin.GetValue()),
+    m_cWnd (Tcp::defaultInitialCWnd.GetValue() * m_segmentSize),
+    m_ssThresh (Tcp::defaultSSThresh.GetValue()),
+    m_initialCWnd (Tcp::defaultInitialCWnd.GetValue()),
+    m_rtt (RttEstimator::CreateDefault()),
+    m_lastMeasuredRtt (Seconds(0.0)),
+    m_cnTimeout (Seconds (Tcp::defaultConnTimeout.GetValue ())),
+    m_cnCount (Tcp::defaultConnCount.GetValue ())
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this<<node<<tcp);
+}
+
+TcpSocket::~TcpSocket ()
+{
+  NS_LOG_FUNCTION;
+  m_node = 0;
+  if (m_endPoint != 0)
+    {
+      NS_ASSERT (m_tcp != 0);
+      /**
+       * Note that this piece of code is a bit tricky:
+       * when DeAllocate is called, it will call into
+       * Ipv4EndPointDemux::Deallocate which triggers
+       * a delete of the associated endPoint which triggers
+       * in turn a call to the method ::Destroy below
+       * will will zero the m_endPoint field.
+       */
+      NS_ASSERT (m_endPoint != 0);
+      m_tcp->DeAllocate (m_endPoint);
+      NS_ASSERT (m_endPoint == 0);
+    }
+  m_tcp = 0;
+  delete m_pendingData; //prevents leak
+}
+
+enum Socket::SocketErrno
+TcpSocket::GetErrno (void) const
+{
+  NS_LOG_FUNCTION;
+  return m_errno;
+}
+
+Ptr<Node>
+TcpSocket::GetNode (void) const
+{
+  NS_LOG_FUNCTION;
+  return m_node;
+}
+
+void 
+TcpSocket::Destroy (void)
+{
+  NS_LOG_FUNCTION;
+  m_node = 0;
+  m_endPoint = 0;
+  m_tcp = 0;
+}
+int
+TcpSocket::FinishBind (void)
+{
+  NS_LOG_FUNCTION;
+  if (m_endPoint == 0)
+    {
+      return -1;
+    }
+  m_endPoint->SetRxCallback (MakeCallback (&TcpSocket::ForwardUp, this));
+  m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, this));
+  return 0;
+}
+
+int
+TcpSocket::Bind (void)
+{
+  NS_LOG_FUNCTION;
+  m_endPoint = m_tcp->Allocate ();
+  return FinishBind ();
+}
+int 
+TcpSocket::Bind (const Address &address)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this<<address);
+  if (!InetSocketAddress::IsMatchingType (address))
+    {
+      return ERROR_INVAL;
+    }
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  Ipv4Address ipv4 = transport.GetIpv4 ();
+  uint16_t port = transport.GetPort ();
+  if (ipv4 == Ipv4Address::GetAny () && port == 0)
+    {
+      m_endPoint = m_tcp->Allocate ();
+      NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_tcp->Allocate (port);
+      NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+    {
+      m_endPoint = m_tcp->Allocate (ipv4);
+      NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_tcp->Allocate (ipv4, port);
+      NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+
+  return FinishBind ();
+}
+
+int 
+TcpSocket::ShutdownSend (void)
+{
+  NS_LOG_FUNCTION;
+  m_shutdownSend = true;
+  return 0;
+}
+int 
+TcpSocket::ShutdownRecv (void)
+{
+  NS_LOG_FUNCTION;
+  m_shutdownRecv = false;
+  return 0;
+}
+
+int
+TcpSocket::Close (void)
+{
+  NS_LOG_FUNCTION;
+  if (m_state == CLOSED) 
+    {
+      return -1;
+    }
+  Actions_t action  = ProcessEvent (APP_CLOSE);
+  if (m_pendingData)
+    {
+      if (action == FIN_TX && m_pendingData->Size () != 0 )
+        {
+          m_closeOnEmpty = true;
+          return 0;
+        }
+    }
+  ProcessAction (action);
+  ShutdownSend ();
+  return 0;
+}
+
+int
+TcpSocket::Connect (const Address & address)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << address);
+  if (m_endPoint == 0)
+    {
+      if (Bind () == -1)
+        {
+          NS_ASSERT (m_endPoint == 0);
+          return -1;
+        }
+      NS_ASSERT (m_endPoint != 0);
+    }
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  m_defaultAddress = transport.GetIpv4 ();
+  m_defaultPort = transport.GetPort ();
+  
+  uint32_t localIfIndex;
+  Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
+
+  if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
+    {
+      m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
+    }
+  else
+    {
+      m_errno = ERROR_NOROUTETOHOST;
+      return -1;
+    }
+
+  Actions_t action = ProcessEvent (APP_CONNECT);
+  bool success = ProcessAction (action);
+  if (success) 
+    {
+      return 0;
+    }
+  return -1;
+}
+int 
+TcpSocket::Send (const Ptr<Packet> p) //p here is just data, no headers
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << p);
+  if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+    { // Ok to buffer some data to send
+      if (!m_pendingData)
+        {
+          m_pendingData = new PendingData (0);   // Create if non-existent
+          m_firstPendingSequence = m_nextTxSequence; // Note seq of first
+        }
+      //PendingData::Add always copies the data buffer, never modifies
+      m_pendingData->Add (p->GetSize (), p->PeekData ());
+      Actions_t action = ProcessEvent (APP_SEND);
+      if (!ProcessAction (action)) 
+        {
+          return -1; // Failed, return zero
+        }
+      return p->GetSize ();
+    }
+  else
+    {
+      m_errno = ERROR_NOTCONN;
+      return -1;
+    }
+}
+
+int TcpSocket::Send (const uint8_t* buf, uint32_t size)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << buf << size);
+  if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+    { // Ok to buffer some data to send
+      if (!m_pendingData)
+      {
+        m_pendingData = new PendingData ();   // Create if non-existent
+        m_firstPendingSequence = m_nextTxSequence; // Note seq of first
+      }
+      //PendingData::Add always copies the data buffer, never modifies
+      m_pendingData->Add (size,buf);
+      Actions_t action = ProcessEvent (APP_SEND);
+      if (!ProcessAction (action)) 
+        {
+          return -1; // Failed, return zero
+        }
+      return size;
+    }
+  else
+  {
+    m_errno = ERROR_NOTCONN;
+    return -1;
+  }
+}
+
+int TcpSocket::DoSendTo (Ptr<Packet> p, const Address &address)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << p << address);
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  Ipv4Address ipv4 = transport.GetIpv4 ();
+  uint16_t port = transport.GetPort ();
+  return DoSendTo (p, ipv4, port);
+}
+
+int TcpSocket::DoSendTo (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << p << ipv4 << port);
+  if (m_endPoint == 0)
+    {
+      if (Bind () == -1)
+	{
+          NS_ASSERT (m_endPoint == 0);
+	  return -1;
+	}
+      NS_ASSERT (m_endPoint != 0);
+    }
+  if (m_shutdownSend)
+    {
+      m_errno = ERROR_SHUTDOWN;
+      return -1;
+    }
+  m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv4,
+                  m_endPoint->GetLocalPort (), port);
+  NotifyDataSent (p->GetSize ());
+  return 0;
+}
+
+int 
+TcpSocket::SendTo (const Address &address, Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << address << p);
+  if (!m_connected)
+    {
+      m_errno = ERROR_NOTCONN;
+      return -1;
+    }
+  else
+    {
+      return Send (p); //drop the address according to BSD manpages
+    }
+}
+
+int
+TcpSocket::Listen (uint32_t q)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << q);
+  Actions_t action = ProcessEvent (APP_LISTEN);
+  ProcessAction (action);
+  return 0;
+}
+
+void
+TcpSocket::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << packet << ipv4 << port);
+  if (m_shutdownRecv)
+    {
+      return;
+    }
+  TcpHeader tcpHeader;
+  packet->RemoveHeader (tcpHeader);
+
+  if (tcpHeader.GetFlags () & TcpHeader::ACK)
+    {
+      Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
+      if (m != Seconds (0.0))
+        {
+          m_lastMeasuredRtt = m;
+        }
+    }
+
+  Events_t event = SimulationSingleton<TcpStateMachine>::Get ()->FlagsEvent (tcpHeader.GetFlags () );
+  Actions_t action = ProcessEvent (event); //updates the state
+  Address address = InetSocketAddress (ipv4, port);
+  ProcessPacketAction (action, packet, tcpHeader, address);
+}
+
+Actions_t TcpSocket::ProcessEvent (Events_t e)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << e);
+  States_t saveState = m_state;
+  NS_LOG_LOGIC ("TcpSocket " << this << " processing event " << e);
+  // simulation singleton is a way to get a single global static instance of a
+  // class intended to be a singleton; see simulation-singleton.h
+  SA stateAction = SimulationSingleton<TcpStateMachine>::Get ()->Lookup (m_state,e);
+  // debug
+  if (stateAction.action == RST_TX)
+    {
+      NS_LOG_LOGIC ("TcpSocket " << this << " sending RST from state "
+              << saveState << " event " << e);
+    }
+  bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED 
+    && e != TIMEOUT);
+  m_state = stateAction.state;
+  NS_LOG_LOGIC ("TcpSocket " << this << " moved from state " << saveState 
+    << " to state " <<m_state);
+  NS_LOG_LOGIC ("TcpSocket " << this << " pendingData " << m_pendingData);
+  if (saveState == SYN_SENT && m_state == ESTABLISHED)
+    // this means the application side has completed its portion of 
+    // the handshaking
+    {
+      NotifyConnectionSucceeded ();
+      m_connected = true;
+      m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
+      NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
+    }
+  if (needCloseNotify && !m_closeNotified)
+    {
+      NS_LOG_LOGIC ("TcpSocket " << this << " transition to CLOSED from " 
+               << m_state << " event " << e << " closeNot " << m_closeNotified
+               << " action " << stateAction.action);
+      NotifyCloseCompleted ();
+      m_closeNotified = true;
+      NS_LOG_LOGIC ("TcpSocket " << this << " calling Closed from PE"
+              << " origState " << saveState
+              << " event " << e);
+      NS_LOG_LOGIC ("TcpSocket " << this << " transition to CLOSED from "
+          << m_state << " event " << e
+          << " set CloseNotif ");
+    }
+  return stateAction.action;
+}
+
+void TcpSocket::SendEmptyPacket (uint8_t flags)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << flags);
+  Ptr<Packet> p = Create<Packet> ();
+  TcpHeader header;
+
+  header.SetFlags (flags);
+  header.SetSequenceNumber (m_nextTxSequence);
+  header.SetAckNumber (m_nextRxSequence);
+  header.SetSourcePort (m_endPoint->GetLocalPort ());
+  header.SetDestinationPort (m_defaultPort);
+  header.SetWindowSize (m_advertisedWindowSize);
+  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), 
+    m_defaultAddress);
+  Time rto = m_rtt->RetransmitTimeout ();
+  if (flags & TcpHeader::SYN)
+    {
+      rto = m_cnTimeout;
+      m_cnCount--;
+    }
+  if (m_retxEvent.IsExpired () ) //no outstanding timer
+  {
+    NS_LOG_LOGIC ("Schedule retransmission timeout at time " 
+          << Simulator::Now ().GetSeconds () << " to expire at time " 
+          << (Simulator::Now () + rto).GetSeconds ());
+    m_retxEvent = Simulator::Schedule (rto, &TcpSocket::ReTxTimeout, this);
+  }
+}
+
+bool TcpSocket::ProcessAction (Actions_t a)
+{ // These actions do not require a packet or any TCP Headers
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << a);
+  switch (a)
+  {
+    case NO_ACT:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action: NO_ACT");
+      break;
+    case ACK_TX:
+      SendEmptyPacket (TcpHeader::ACK);
+      break;
+    case ACK_TX_1:
+      NS_ASSERT (false); // This should be processed in ProcessPacketAction
+      break;
+    case RST_TX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action RST_TX");
+      SendEmptyPacket (TcpHeader::RST);
+      break;
+    case SYN_TX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_TX");
+      // TCP SYN Flag consumes one byte
+      m_nextTxSequence+= 1;
+      SendEmptyPacket (TcpHeader::SYN);
+      break;
+    case SYN_ACK_TX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
+      SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+      break;
+    case FIN_TX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action FIN_TX");
+      SendEmptyPacket (TcpHeader::FIN);
+      break;
+    case FIN_ACK_TX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action FIN_ACK_TX");
+      SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
+      break;
+    case NEW_ACK:
+      NS_ASSERT (false); // This should be processed in ProcessPacketAction
+      break;
+    case NEW_SEQ_RX:
+      NS_ASSERT (false); // This should be processed in ProcessPacketAction
+      break;
+    case RETX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action RETX");
+      break;
+    case TX_DATA:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action TX_DATA");
+      SendPendingData ();
+      break;
+    case PEER_CLOSE:
+      NS_ASSERT (false); // This should be processed in ProcessPacketAction
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action PEER_CLOSE");
+      break;
+    case APP_CLOSED:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action APP_CLOSED");
+      break;
+    case CANCEL_TM:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action CANCEL_TM");
+      break;
+    case APP_NOTIFY:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action APP_NOTIFY");
+      break;
+    case SERV_NOTIFY:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action SERV_NOTIFY");
+      NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
+      NotifyConnectionSucceeded ();
+      m_connected = true; // ! This is bogus; fix when we clone the tcp
+      m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
+      break;
+    case LAST_ACTION:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action LAST_ACTION");
+      break;
+  }
+  return true;
+}
+
+bool TcpSocket::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
+                                     const TcpHeader& tcpHeader,
+                                     const Address& fromAddress)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << p << "tcpHeader " << fromAddress);
+  uint32_t localIfIndex;
+  Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
+  switch (a)
+  {
+    case SYN_ACK_TX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
+      m_defaultPort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
+      m_defaultAddress = 
+        InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
+      m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
+      if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
+        {
+          m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
+        }
+      // TCP SYN consumes one byte
+      m_nextRxSequence++;
+      SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+      break;
+    case ACK_TX_1:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action ACK_TX_1");
+      // TCP SYN consumes one byte
+      m_nextRxSequence++;
+      SendEmptyPacket (TcpHeader::ACK);
+      m_rxWindowSize = tcpHeader.GetWindowSize ();
+      if (tcpHeader.GetAckNumber () > m_highestRxAck)
+      {
+        m_highestRxAck = tcpHeader.GetAckNumber ();
+      }
+      SendPendingData ();
+      break;
+    case NEW_ACK:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_ACK_TX");
+      if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing
+      {
+        break;
+      }
+      if (tcpHeader.GetAckNumber () == m_highestRxAck && 
+         tcpHeader.GetAckNumber ()  < m_nextTxSequence)
+      {
+        DupAck (tcpHeader, ++m_dupAckCount);
+        break;
+      }
+      if (tcpHeader.GetAckNumber () > m_highestRxAck)  
+        {
+          m_dupAckCount = 0;
+        }
+      NewAck (tcpHeader.GetAckNumber ());
+      break;
+    case NEW_SEQ_RX:
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_SEQ_TX");
+      NewRx (p, tcpHeader, fromAddress); // Process new data received
+      break;
+    case PEER_CLOSE:
+    {
+      // First we have to be sure the FIN packet was not received
+      // out of sequence.  If so, note pending close and process
+      // new sequence rx
+      if (tcpHeader.GetSequenceNumber () != m_nextRxSequence)
+        { // process close later
+          m_pendingClose = true;
+          NS_LOG_LOGIC ("TcpSocket " << this << " setting pendingClose" 
+            << " rxseq " << tcpHeader.GetSequenceNumber () 
+            << " nextRxSeq " << m_nextRxSequence);
+          NewRx (p, tcpHeader, fromAddress);
+          return true;
+        }
+      // Now we need to see if any data came with the FIN
+      // if so, call NewRx
+      if (p->GetSize () != 0)
+        {
+          NewRx (p, tcpHeader, fromAddress);
+        }
+      States_t saveState = m_state; // Used to see if app responds
+      NS_LOG_LOGIC ("TcpSocket " << this 
+          << " peer close, state " << m_state);
+      if (!m_closeRequestNotified)
+        {
+          NS_LOG_LOGIC ("TCP " << this 
+              << " calling AppCloseRequest");
+          NotifyCloseRequested ();
+          m_closeRequestNotified = true;
+        }
+      NS_LOG_LOGIC ("TcpSocket " << this 
+          << " peer close, state after " << m_state);
+      if (m_state == saveState)
+        { // Need to ack, the application will close later
+          SendEmptyPacket (TcpHeader::ACK);
+              // Also need to re-tx the ack if we
+        }
+      if (m_state == LAST_ACK)
+        {
+          NS_LOG_LOGIC ("TcpSocket " << this << " scheduling LATO1");
+          m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
+                                                &TcpSocket::LastAckTimeout,this);
+        }
+      break;
+    }
+    default:
+      break;
+  }
+  return true;
+}
+
+bool TcpSocket::SendPendingData (bool withAck)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << withAck);
+  NS_LOG_LOGIC ("ENTERING SendPendingData");
+  if (!m_pendingData)
+    {
+      return false; // No data exists
+    }
+  uint32_t nPacketsSent = 0;
+  while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence))
+    {
+      uint32_t w = AvailableWindow ();// Get available window size
+      NS_LOG_LOGIC ("TcpSocket " << this << " SendPendingData"
+           << " w " << w 
+           << " rxwin " << m_rxWindowSize
+           << " cWnd " << m_cWnd
+           << " segsize " << m_segmentSize
+           << " nextTxSeq " << m_nextTxSequence
+           << " highestRxAck " << m_highestRxAck 
+           << " pd->Size " << m_pendingData->Size ()
+           << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence));
+
+      if (w < m_segmentSize && m_pendingData->Size () > w)
+        {
+          break; // No more
+        }
+      uint32_t s = std::min (w, m_segmentSize);  // Send no more than window
+      PendingData* d = m_pendingData->CopyFromSeq (s, m_firstPendingSequence, 
+        m_nextTxSequence);
+      NS_LOG_LOGIC("TcpSocket " << this << " sendPendingData"
+                   << " txseq " << m_nextTxSequence
+                   << " s " << s 
+                   << " datasize " << d->Size() );
+      uint8_t flags = 0;
+      if (withAck)
+        {
+          flags |= TcpHeader::ACK;
+        }
+      uint32_t sz = d->Size (); // Size of packet
+      uint32_t remainingData = m_pendingData->SizeFromSeq(
+          m_firstPendingSequence,
+          m_nextTxSequence + SequenceNumber (sz));
+      if (m_closeOnEmpty && (remainingData == 0))
+        {
+          flags = TcpHeader::FIN;
+          m_state = FIN_WAIT_1;
+        }
+      // Create and send the packet
+
+      Ptr<Packet> p = Create<Packet> (d->data, sz);
+
+      TcpHeader header;
+      header.SetFlags (flags);
+      header.SetSequenceNumber (m_nextTxSequence);
+      header.SetAckNumber (m_nextRxSequence);
+      header.SetSourcePort (m_endPoint->GetLocalPort());
+      header.SetDestinationPort (m_defaultPort);
+      if (m_shutdownSend)
+        {
+          m_errno = ERROR_SHUTDOWN;
+          return -1;
+        }
+
+      Time rto = m_rtt->RetransmitTimeout ();
+      if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
+        {
+          NS_LOG_LOGIC ("Schedule retransmission timeout at time " << 
+              Simulator::Now ().GetSeconds () << " to expire at time " <<
+              (Simulator::Now () + rto).GetSeconds () );
+          m_retxEvent = Simulator::Schedule (rto,&TcpSocket::ReTxTimeout,this);
+        }
+      NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
+      m_tcp->SendPacket (p, header,
+                         m_endPoint->GetLocalAddress (),
+                         m_defaultAddress);
+      m_rtt->SentSeq(m_nextTxSequence, sz);           // notify the RTT
+      NotifyDataSent (p->GetSize () );                // notify the application
+      nPacketsSent++;                                 // Count sent this loop
+      m_nextTxSequence += sz;                         // Advance next tx sequence
+      m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);// Note the high water mark
+    }
+  NS_LOG_LOGIC ("Sent "<<nPacketsSent<<" packets");
+  NS_LOG_LOGIC("RETURN SendPendingData");
+  return (nPacketsSent>0);
+}
+
+uint32_t  TcpSocket::UnAckDataCount ()
+{
+  NS_LOG_FUNCTION;
+  return m_nextTxSequence - m_highestRxAck;
+}
+
+uint32_t  TcpSocket::BytesInFlight ()
+{
+  NS_LOG_FUNCTION;
+  return m_highTxMark - m_highestRxAck;
+}
+
+uint32_t  TcpSocket::Window ()
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_LOGIC ("TcpSocket::Window() "<<this);
+  return std::min (m_rxWindowSize, m_cWnd);
+}
+
+uint32_t  TcpSocket::AvailableWindow ()
+{
+  NS_LOG_FUNCTION;
+  uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
+  uint32_t win = Window ();
+  if (win < unack) 
+    {
+      return 0;  // No space available
+    }
+  return (win - unack);       // Amount of window space available
+}
+
+void TcpSocket::NewRx (Ptr<Packet> p,
+                        const TcpHeader& tcpHeader, 
+                        const Address& fromAddress)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << p << "tcpHeader " << fromAddress);
+  NS_LOG_LOGIC ("TcpSocket " << this << " NewRx, p.size is " << p->GetSize () );
+  States_t origState = m_state;
+  uint32_t s = p->GetSize ();  // Size of associated data
+  if (s == 0)
+    {// Nothing to do if no associated data
+      return;
+    }
+  // Log sequence received if enabled
+  // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber);
+  // Three possibilities
+  // 1) Received seq is expected, deliver this and any buffered data
+  // 2) Received seq is < expected, just re-ack previous
+  // 3) Received seq is > expected, just re-ack previous and buffer data
+  if (tcpHeader.GetSequenceNumber () == m_nextRxSequence)
+    { // If seq is expected seq
+      // 1) Update nextRxSeq
+      // 2) Deliver to application this packet
+      // 3) See if any buffered can be delivered
+      // 4) Send the ack
+      m_nextRxSequence += s;           // Advance next expected sequence
+      //bytesReceived += s;       // Statistics
+      NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
+	  NotifyDataReceived (p, fromAddress);
+      if (m_closeNotified)
+        {
+          NS_LOG_LOGIC ("Tcp " << this << " HuH?  Got data after closeNotif");
+        }
+      NS_LOG_LOGIC ("TcpSocket " << this << " adv rxseq by " << s);
+      // Look for buffered data
+      UnAckData_t::iterator i;
+      // Note that the bufferedData list DOES contain the tcp header
+      while (!m_bufferedData.empty ())
+        { // Check the buffered data for delivery
+          NS_LOG_LOGIC("TCP " << this << " bufferedData.size() " 
+              << m_bufferedData.size () 
+              << " time " << Simulator::Now ());
+          i = m_bufferedData.begin ();
+          Ptr<Packet> p1 = i->second;
+          SequenceNumber s1 = 0;
+          if (i->first > m_nextRxSequence) 
+            {
+              break;  // Not next expected
+            }
+          // already have the header as a param
+          //TCPHeader* h = dynamic_cast<TCPHeader*>(p1->PopPDU());
+          // Check non-null here...
+          uint8_t flags = tcpHeader.GetFlags ();           // Flags (used below)
+          if (i->first < m_nextRxSequence)
+            { // remove already delivered data
+              // Two cases here.
+              // 1) seq + length <= nextRxSeq, just discard
+              // 2) seq + length > nextRxSeq, can deliver partial
+              s1 = p->GetSize ();
+              if (i->first + s1 < m_nextRxSequence)
+                { // Just remove from list
+                  //bufferedData.erase(i);
+                  p1 = 0; // Nothing to deliver
+                }
+              else
+                { // Remove partial data to prepare for delivery
+                  uint32_t dup = m_nextRxSequence - i->first;
+                  i->second = p1->CreateFragment (0, p1->GetSize () - dup);
+                  p1 = i->second;
+                }
+            }
+          else
+            { // At this point i->first must equal nextRxSeq
+              if (i->first != m_nextRxSequence)
+                {
+                  NS_FATAL_ERROR ("HuH?  NexRx failure, first " 
+                      << i->first << " nextRxSeq " << m_nextRxSequence);
+                }
+              s1 = p1->GetSize ();
+            }
+          NotifyDataReceived (p1, fromAddress);
+
+          NS_LOG_LOGIC ("TcpSocket " << this << " adv rxseq1 by " << s1 );
+          m_nextRxSequence += s1;           // Note data received
+          m_bufferedData.erase (i);     // Remove from list
+          if (flags & TcpHeader::FIN)
+            NS_LOG_LOGIC("TcpSocket " << this 
+                    << " found FIN in buffered");
+        }
+
+      if (m_pendingClose || (origState > ESTABLISHED))
+        { // See if we can close now
+          if (m_bufferedData.empty())
+            {
+              ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress);
+            }
+        }
+    }
+  else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence)
+    { // Need to buffer this one
+      NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () );
+      UnAckData_t::iterator i = 
+        m_bufferedData.find (tcpHeader.GetSequenceNumber () );
+      if (i != m_bufferedData.end () )
+        {
+          i->second = 0; // relase reference to already buffered
+        }
+      // Save for later delivery
+      m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;  
+    }
+  else
+    { // debug
+      NS_LOG_LOGIC("TCP " << this 
+               << " got seq " << tcpHeader.GetSequenceNumber ()
+               << " expected " << m_nextRxSequence
+               << "       flags " << tcpHeader.GetFlags ());
+    }
+  // Now send a new ack packet acknowledging all received and delivered data
+  SendEmptyPacket (TcpHeader::ACK);
+}
+
+
+void TcpSocket::CommonNewAck (SequenceNumber ack, bool skipTimer)
+{ // CommonNewAck is called only for "New" (non-duplicate) acks
+  // and MUST be called by any subclass, from the NewAck function
+  // Always cancel any pending re-tx timer on new acknowledgement
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << ack << skipTimer);
+  //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
+  if (!skipTimer)
+    {
+      m_retxEvent.Cancel ();
+    }
+  uint32_t numberAck = ack - m_highestRxAck; // Number bytes ack'ed
+  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack 
+           << " numberAck " << numberAck);
+  m_highestRxAck = ack;         // Note the highest recieved Ack
+  if (ack > m_nextTxSequence) 
+    {
+      m_nextTxSequence = ack; // If advanced
+    }
+  // See if all pending ack'ed; if so we can delete the data
+  if (m_pendingData)
+    { // Data exists, see if can be deleted
+      if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0)
+        { // All pending acked, can be deleted
+          m_pendingData->Clear ();
+          delete m_pendingData;
+          m_pendingData = 0;
+          // Insure no re-tx timer
+          m_retxEvent.Cancel();
+        }
+    }
+  // Try to send more data
+  SendPendingData();
+}
+
+void TcpSocket::NewAck (SequenceNumber seq)
+{ // New acknowledgement up to sequence number "seq"
+  // Adjust congestion window in response to new ack's received
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << seq);
+  NS_LOG_LOGIC ("TcpSocket " << this << " NewAck "
+           << " seq " << seq
+           << " cWnd " << m_cWnd
+           << " ssThresh " << m_ssThresh);
+  if (m_cWnd < m_ssThresh)
+    { // Slow start mode, add one segSize to cWnd
+      m_cWnd += m_segmentSize;
+      NS_LOG_LOGIC ("TcpSocket " << this << " NewCWnd SlowStart, cWnd " << m_cWnd 
+          << " sst " << m_ssThresh);
+    }
+  else
+    { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd
+      double adder =  ((double) m_segmentSize * m_segmentSize) / m_cWnd;
+      if (adder < 1.0) 
+        {
+          adder = 1.0;
+        }
+      m_cWnd += (uint32_t) adder;
+      NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd 
+           << " sst " << m_ssThresh);
+    }
+  CommonNewAck (seq, false);           // Complete newAck processing
+}
+
+void TcpSocket::DupAck (const TcpHeader& t, uint32_t count)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << "t " << count);
+  NS_LOG_LOGIC ("TcpSocket " << this << " DupAck " <<  t.GetAckNumber ()
+      << ", count " << count
+      << ", time " << Simulator::Now ());
+  if (count == 3)
+  { // Count of three indicates triple duplicate ack
+    m_ssThresh = Window () / 2; // Per RFC2581
+    m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
+    NS_LOG_LOGIC("TcpSocket " << this << "Tahoe TDA, time " << Simulator::Now ()
+        << " seq " << t.GetAckNumber ()
+        << " in flight " << BytesInFlight ()
+        << " new ssthresh " << m_ssThresh);
+
+    m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart)
+    // For Tahoe, we also reset nextTxSeq
+    m_nextTxSequence = m_highestRxAck;
+    SendPendingData ();
+  }
+}
+
+void TcpSocket::ReTxTimeout ()
+{ // Retransmit timeout
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this);
+  m_ssThresh = Window () / 2; // Per RFC2581
+  m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
+  // Set cWnd to segSize on timeout,  per rfc2581
+  // Collapse congestion window (re-enter slowstart)
+  m_cWnd = m_segmentSize;           
+  m_nextTxSequence = m_highestRxAck; // Start from highest Ack
+  m_rtt->IncreaseMultiplier (); // Double timeout value for next retx timer
+  Retransmit ();             // Retransmit the packet
+}
+
+void TcpSocket::LastAckTimeout ()
+{
+  m_lastAckEvent.Cancel ();
+  if (m_state == LAST_ACK)
+    {
+      Actions_t action = ProcessEvent (TIMEOUT);
+      ProcessAction (action);
+    }
+  if (!m_closeNotified)
+    {
+      m_closeNotified = true;
+    }
+}
+
+void TcpSocket::Retransmit ()
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this);
+  uint8_t flags = TcpHeader::NONE;
+  if (m_state == SYN_SENT) 
+    {
+      if (m_cnCount > 0) 
+        {
+          SendEmptyPacket (TcpHeader::SYN);
+          return;
+        }
+      else
+        {
+          NotifyConnectionFailed ();
+          return;
+        }
+    } 
+  if (!m_pendingData)
+    {
+      if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2)
+        { // Must have lost FIN, re-send
+          SendEmptyPacket (TcpHeader::FIN);
+        }
+      return;
+    }
+  PendingData* d = m_pendingData->CopyFromSeq (m_segmentSize,
+                                            m_firstPendingSequence,
+                                            m_highestRxAck);
+  // Calculate remaining data for COE check
+  uint32_t remainingData =
+      m_pendingData->SizeFromSeq (m_firstPendingSequence,
+                                m_nextTxSequence + SequenceNumber(d->Size ()));
+  if (m_closeOnEmpty && remainingData == 0)
+    { // Add the FIN flag
+      flags = flags | TcpHeader::FIN;
+    }
+  Ptr<Packet> p = Create<Packet> (d->data, d->Size());
+  NS_LOG_LOGIC ("TcpSocket " << this << " retxing seq " << m_highestRxAck);
+  if (m_retxEvent.IsExpired () )
+    {
+      Time rto = m_rtt->RetransmitTimeout ();
+      NS_LOG_LOGIC ("Schedule retransmission timeout at time "
+          << Simulator::Now ().GetSeconds () << " to expire at time "
+          << (Simulator::Now () + rto).GetSeconds ());
+      m_retxEvent = Simulator::Schedule (rto,&TcpSocket::ReTxTimeout,this);
+    }
+  m_rtt->SentSeq (m_highestRxAck,d->Size ());
+  // And send the packet
+  TcpHeader tcpHeader;
+  tcpHeader.SetSequenceNumber (m_nextTxSequence);
+  tcpHeader.SetAckNumber (m_nextRxSequence);
+  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
+  tcpHeader.SetDestinationPort (m_defaultPort);
+  tcpHeader.SetFlags (flags);
+  tcpHeader.SetWindowSize (m_advertisedWindowSize);
+
+  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
+    m_defaultAddress);
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,161 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_SOCKET_H
+#define TCP_SOCKET_H
+
+#include <stdint.h>
+#include "ns3/callback.h"
+#include "ns3/socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/event-id.h"
+#include "tcp-typedefs.h"
+#include "pending-data.h"
+#include "sequence-number.h"
+#include "rtt-estimator.h"
+
+namespace ns3 {
+
+class Ipv4EndPoint;
+class Node;
+class Packet;
+class TcpL4Protocol;
+class TcpHeader;
+
+class TcpSocket : public Socket
+{
+public:
+  /**
+   * Create an unbound tcp socket.
+   */
+  TcpSocket (Ptr<Node> node, Ptr<TcpL4Protocol> tcp);
+  virtual ~TcpSocket ();
+
+  virtual enum SocketErrno GetErrno (void) const;
+  virtual Ptr<Node> GetNode (void) const;
+  virtual int Bind (void);
+  virtual int Bind (const Address &address);
+  virtual int Close (void);
+  virtual int ShutdownSend (void);
+  virtual int ShutdownRecv (void);
+  virtual int Connect(const Address &address);
+  virtual int Send (Ptr<Packet> p);
+  virtual int Send (const uint8_t* buf, uint32_t size);
+  virtual int SendTo(const Address &address, Ptr<Packet> p);
+  virtual int Listen(uint32_t queueLimit);
+
+private:
+  friend class Tcp;
+  // invoked by Tcp class
+  int FinishBind (void);
+  void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
+  void Destroy (void);
+  int DoSendTo (Ptr<Packet> p, const Address &daddr);
+  int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
+  void SendEmptyPacket(uint8_t flags);
+  //methods for state
+  bool ProcessAction (Actions_t a);
+  bool ProcessAction (Actions_t a, const TcpHeader& tcpHeader,
+                      Ipv4Address saddr, Ipv4Address daddr);
+  bool ProcessPacketAction (Actions_t a, Ptr<Packet> p,
+                                       const TcpHeader& tcpHeader,
+                                       const Address& fromAddress);
+  Actions_t ProcessEvent (Events_t e);
+  bool SendPendingData(bool withAck = false);
+
+  //methods for window management
+  virtual uint32_t  UnAckDataCount(); // Return count of number of unacked bytes
+  virtual uint32_t  BytesInFlight();  // Return total bytes in flight
+  virtual uint32_t  Window();         // Return window size (integer)
+  virtual uint32_t  AvailableWindow();// Return unfilled portion of window
+
+  // Manage data tx/rx
+  void NewRx (Ptr<Packet>, const TcpHeader&, const Address&);
+  // XXX This should be virtual and overridden
+  void NewAck (SequenceNumber seq); 
+  // XXX This should be virtual and overridden
+  void DupAck (const TcpHeader& t, uint32_t count); 
+  void ReTxTimeout ();
+  void LastAckTimeout ();
+  void Retransmit ();
+  void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
+
+  bool m_skipRetxResched;
+  uint32_t m_dupAckCount;
+  EventId m_retxEvent;
+  EventId m_lastAckEvent;
+
+  Ipv4EndPoint *m_endPoint;
+  Ptr<Node> m_node;
+  Ptr<TcpL4Protocol> m_tcp;
+  Ipv4Address m_defaultAddress;
+  uint16_t m_defaultPort;
+  Callback<void, Ptr<Socket>, uint32_t, const Address &> m_dummyRxCallback;
+  Callback<void, Ptr<Socket>, uint8_t const*, uint32_t, const Address &> 
+    m_rxCallback;
+  enum SocketErrno m_errno;
+  bool m_shutdownSend;
+  bool m_shutdownRecv;
+  bool m_connected;
+  
+  //manage the state infomation
+  States_t m_state;
+  bool m_closeNotified;
+  bool m_closeRequestNotified;
+  bool m_closeOnEmpty;
+  bool m_pendingClose;
+
+  
+  //sequence info, sender side
+  SequenceNumber m_nextTxSequence;
+  SequenceNumber m_highTxMark;
+  SequenceNumber m_highestRxAck;
+  SequenceNumber m_lastRxAck;
+  
+  //sequence info, reciever side
+  SequenceNumber m_nextRxSequence;
+  SequenceNumber m_nextAckSequence;
+
+  //history data
+  UnAckData_t m_bufferedData;
+  PendingData* m_pendingData;
+  SequenceNumber m_firstPendingSequence;
+
+  // Window management
+  uint32_t          m_segmentSize;                     // SegmentSize
+  uint32_t          m_rxWindowSize;
+  uint32_t          m_advertisedWindowSize;            // Window to advertise to peer
+  uint32_t          m_cWnd;            // Congestion window
+  uint32_t          m_ssThresh;                     // Slow Start Threshold
+  uint32_t          m_initialCWnd;     // Initial (and reset) value for cWnd
+
+  // Round trip time estimation
+  Ptr<RttEstimator> m_rtt;
+  Time m_lastMeasuredRtt;
+
+  // Timer-related members
+  Time              m_cnTimeout; 
+  uint32_t          m_cnCount;
+  
+};
+
+}//namespace ns3
+
+#endif /* UDP_SOCKET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-typedefs.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,111 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ * typedefs for tcp state machine
+ */ 
+
+#include <vector>
+#include <map>
+#include "sequence-number.h"
+
+#ifndef TCP_TYPEDEFS_H
+#define TCP_TYPEDEFS_H
+
+namespace ns3 {
+
+typedef enum { MAX_FLAGS = 0x40 } TCPMaxFlags_t;  // Flags are 6 bits
+
+typedef enum {
+  CLOSED,       // 0
+  LISTEN,       // 1
+  SYN_SENT,     // 2
+  SYN_RCVD,     // 3
+  ESTABLISHED,  // 4
+  CLOSE_WAIT,   // 5
+  LAST_ACK,     // 6
+  FIN_WAIT_1,   // 7
+  FIN_WAIT_2,   // 8
+  CLOSING,      // 9
+  TIMED_WAIT,   // 10
+  LAST_STATE } States_t;
+
+typedef enum {
+  APP_LISTEN,   // 0
+  APP_CONNECT,  // 1
+  APP_SEND,     // 2
+  SEQ_RECV,     // 3
+  APP_CLOSE,    // 4
+  TIMEOUT,      // 5
+  ACK_RX,       // 6
+  SYN_RX,       // 7
+  SYN_ACK_RX,   // 8
+  FIN_RX,       // 9
+  FIN_ACK_RX,   // 10
+  RST_RX,       // 11
+  BAD_FLAGS,    // 12
+  LAST_EVENT } Events_t;
+
+typedef enum {
+  NO_ACT,       // 0
+  ACK_TX,       // 1
+  ACK_TX_1,     // ACK response to syn
+  RST_TX,       // 2
+  SYN_TX,       // 3
+  SYN_ACK_TX,   // 4
+  FIN_TX,       // 5
+  FIN_ACK_TX,   // 6
+  NEW_ACK,      // 7
+  NEW_SEQ_RX,   // 8
+  RETX,         // 9
+  TX_DATA,      // 10
+  PEER_CLOSE,   // 11
+  APP_CLOSED,   // 12
+  CANCEL_TM,    // 13
+  APP_NOTIFY,   // 14 - Notify app that connection failed
+  SERV_NOTIFY,  // 15 - Notify server tcp that connection completed
+  LAST_ACTION } Actions_t;
+
+class SA  // State/Action pair
+{
+public:
+  SA () : state (LAST_STATE), action (LAST_ACTION) { }
+  SA (States_t s, Actions_t a) : state (s), action (a) { }
+public:
+  States_t  state;
+  Actions_t action;
+};
+typedef std::vector<SA>  StateActionVec_t;
+typedef std::vector<StateActionVec_t> StateActions_t;  // One per current state
+typedef std::vector<Events_t> EventVec_t;      // For flag events lookup
+
+//type for managing buffered out of sequence data
+typedef std::map<SequenceNumber, Ptr<Packet> > UnAckData_t;
+
+class TcpStateMachine {
+  public:
+    TcpStateMachine ();
+    SA Lookup (States_t, Events_t);
+    Events_t FlagsEvent (uint8_t); // Lookup event from flags
+
+  public:
+    StateActions_t aT; // Action table
+    EventVec_t     eV; // Flags event lookup  
+};
+
+}//namespace ns3
+#endif //TCP_TYPEDEFS_H
--- a/src/internet-node/wscript	Sat Jan 19 21:03:18 2008 -0800
+++ b/src/internet-node/wscript	Fri Jan 25 13:57:38 2008 -0500
@@ -9,23 +9,30 @@
         'ipv4-l4-protocol.cc',
         'ipv4-header.cc',
         'udp-header.cc',
+        'tcp-header.cc',
         'ipv4-checksum.cc',
         'ipv4-interface.cc',
         'ipv4-l3-protocol.cc',
         'ipv4-static-routing.cc',
         'ipv4-end-point.cc',
         'udp-l4-protocol.cc',
+        'tcp-l4-protocol.cc',
         'arp-header.cc',
         'arp-cache.cc',
         'arp-ipv4-interface.cc',
         'arp-l3-protocol.cc',
         'ipv4-loopback-interface.cc',
         'udp-socket.cc',
+        'tcp-socket.cc',
         'ipv4-end-point-demux.cc',
         'ipv4-impl.cc',
         'ascii-trace.cc',
         'pcap-trace.cc',
         'udp-impl.cc',
+        'tcp-impl.cc',
+        'pending-data.cc',
+        'sequence-number.cc',
+        'rtt-estimator.cc',
         ]
 
     headers = bld.create_obj('ns3header')
@@ -35,4 +42,5 @@
         'pcap-trace.h',
         'ipv4-header.h',
         'udp-header.h',
+        'tcp-header.h',
         ]
--- a/src/node/socket.cc	Sat Jan 19 21:03:18 2008 -0800
+++ b/src/node/socket.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -108,6 +108,12 @@
   return SendTo (address,p);
 }
 
+int Socket::Listen(uint32_t queueLimit)
+{
+  return 0; //XXX the base class version does nothing
+}
+
+
 void 
 Socket::NotifyCloseCompleted (void)
 {
--- a/src/node/socket.h	Sat Jan 19 21:03:18 2008 -0800
+++ b/src/node/socket.h	Fri Jan 25 13:57:38 2008 -0500
@@ -197,6 +197,13 @@
   virtual int SendTo(const Address &address,Ptr<Packet> p) = 0;
 
   /**
+   * \brief Listen for incoming connections.
+   * \param queueLimit maximum number of incoming request to queue
+   * \returns XXX an error code
+   */
+  virtual int Listen(uint32_t queueLimit);
+
+  /**
    * \brief Send data to a specified peer.
    * \param address IP Address of remote host
    * \param buf A pointer to a raw byte buffer of some data to send.  If this 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp.cc	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#include "tcp.h"
+
+namespace ns3 {
+
+NumericDefaultValue<uint32_t>       Tcp::defaultSegSize
+("TcpDefaultSegmentSize",
+"Default TCP maximum segment size in bytes (may be adjusted based on MTU discovery)",
+536);
+
+NumericDefaultValue<uint32_t>       Tcp::defaultAdvWin
+("TcpDefaultAdvertisedWindowSize",
+"Default TCP advertised window size (bytes)",
+0xffff);
+
+NumericDefaultValue<uint32_t>       Tcp::defaultSSThresh
+("TcpDefaultSlowStartThreshold",
+"Default TCP slow start threshold (bytes)",
+0xffff);
+
+NumericDefaultValue<uint32_t>       Tcp::defaultTxBuffer
+("TcpDefaultTxBufferSize",
+"Default TCP maximum transmit buffer size (bytes)",
+0xffffffffl);
+
+NumericDefaultValue<uint32_t>       Tcp::defaultRxBuffer
+("TcpDefaultRxBufferSize",
+"Default TCP maximum receive buffer size (bytes)",
+0xffffffffl);
+
+NumericDefaultValue<uint32_t>       Tcp::defaultInitialCWnd
+("TcpDefaultInitialCongestionWindowSize",
+"Default TCP initial congestion window size (segments)",
+1);
+
+NumericDefaultValue<uint32_t>       Tcp::defaultConnTimeout
+("TcpDefaultConnTimeout",
+"Default TCP retransmission timeout when opening connection (seconds)",
+6);
+
+NumericDefaultValue<uint32_t>       Tcp::defaultConnCount
+("TcpDefaultConnCount",
+"Default number of connection attempts (SYN retransmissions) before returning failure",
+3);
+
+const InterfaceId Tcp::iid = MakeInterfaceId ("Tcp", SocketFactory::iid);
+
+Tcp::Tcp ()
+{
+  SetInterfaceId (Tcp::iid);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp.h	Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_H
+#define TCP_H
+
+#include "ns3/default-value.h"
+#include "socket-factory.h"
+
+namespace ns3 {
+
+class Socket;
+
+/**
+ * \brief API to create TCP socket instances 
+ *
+ * This abstract class defines the API for TCP sockets.
+ * This class also holds the global default variables used to
+ * initialize newly created sockets, such as values that are
+ * set through the sysctl or proc interfaces in Linux.
+
+ * All TCP implementations must provide an implementation of CreateSocket
+ * below, and should make use of the default values configured below.
+ * 
+ * \see TcpImpl
+ *
+ */
+class Tcp : public SocketFactory
+{
+public:
+  static const InterfaceId iid;
+
+  Tcp ();
+
+  virtual Ptr<Socket> CreateSocket (void) = 0;
+
+public:
+  static NumericDefaultValue<uint32_t>       defaultSegSize;  
+  static NumericDefaultValue<uint32_t>       defaultAdvWin;   
+  static NumericDefaultValue<uint32_t>       defaultSSThresh; 
+  static NumericDefaultValue<uint32_t>       defaultTxBuffer; 
+  static NumericDefaultValue<uint32_t>       defaultRxBuffer; 
+  static NumericDefaultValue<uint32_t>       defaultInitialCWnd; 
+  static NumericDefaultValue<uint32_t>       defaultConnTimeout;  
+  static NumericDefaultValue<uint32_t>       defaultConnCount;  
+
+};
+
+} // namespace ns3
+
+#endif /* UDP_H */
--- a/src/node/wscript	Sat Jan 19 21:03:18 2008 -0800
+++ b/src/node/wscript	Fri Jan 25 13:57:38 2008 -0500
@@ -25,6 +25,7 @@
         'packet-socket-factory.cc',
         'packet-socket.cc',
         'udp.cc',
+        'tcp.cc',
         'ipv4.cc',
         'application.cc',
         ]
@@ -52,6 +53,7 @@
         'socket-factory.h',
         'packet-socket-factory.h',
         'udp.h',
+        'tcp.h',
         'ipv4.h',
         'application.h',
         ]