merge with HEAD
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 27 May 2008 15:01:11 -0700
changeset 3153 1433edf49f02
parent 3152 4260de124c74 (current diff)
parent 3145 16dd98873ec3 (diff)
child 3154 aa61e5f85334
merge with HEAD
src/internet-node/ipv4-l3-protocol.cc
src/internet-node/tcp-impl.cc
src/internet-node/tcp-impl.h
src/internet-node/tcp-socket.cc
src/internet-node/tcp-socket.h
src/internet-node/udp-impl.cc
src/internet-node/udp-impl.h
src/internet-node/udp-socket.cc
src/internet-node/udp-socket.h
src/node/tcp.cc
src/node/tcp.h
src/node/udp.cc
src/node/udp.h
--- a/doc/tutorial/Makefile	Sun May 25 14:58:22 2008 -0700
+++ b/doc/tutorial/Makefile	Tue May 27 15:01:11 2008 -0700
@@ -7,7 +7,7 @@
 CSS = --css-include=tutorial.css
 SPLIT = --split section
 
-DIA_SOURCES = buffer.dia pp.dia dumbbell.dia star.dia
+DIA_SOURCES = buffer.dia pp.dia dumbbell.dia star.dia sockets-overview.dia
 TGIF_SOURCES = packet.obj helpers.obj 
 
 DIA_EPS = ${DIA_SOURCES:.dia=.eps}
Binary file doc/tutorial/figures/sockets-overview.dia has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/sockets.texi	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,243 @@
+@node Sockets APIs
+@chapter Sockets APIs
+
+The @uref{http://en.wikipedia.org/wiki/Berkeley_sockets,,sockets API}
+is a long-standing API used by user-space applications to access
+network services in the kernel.  A ``socket'' is an abstraction, like
+a Unix file handle, that allows applications to connect to other
+Internet hosts and exchange reliable byte streams and unreliable
+datagrams, among other services.   
+
+ns-3 provides two types of sockets APIs, and it is important to
+understand the differences between them.  The first is a @emph{native}
+ns-3 API, while the second uses the services of the native API to 
+provide a @uref{http://en.wikipedia.org/wiki/POSIX,,POSIX-like}
+API as part of an overall application process.  Both APIs strive
+to be close to the typical sockets API that application writers
+on Unix systems are accustomed to, but the POSIX variant is much
+closer to a real system's sockets API.
+
+@section ns-3 sockets API
+
+The native sockets API for ns-3 provides an interface to various
+types of transport protocols (TCP, UDP) as well as to packet sockets
+and, in the future, Netlink-like sockets.  However, users are cautioned
+to understand that the semantics are @strong{not} the exact same as 
+one finds in a real system (for an API which is very much aligned
+to real systems, see the next section).
+
+@code{class ns3::Socket} is defined in @code{src/node/socket.cc,h}.
+Readers will note that many public member functions are aligned
+with real sockets function calls, and all other things being equal,
+we have tried to align with a Posix sockets API.  However, note that:
+
+@itemize @bullet
+@item ns-3 applications handle a smart pointer to a Socket object, not
+a file descriptor;
+@item there is no notion of synchronous API or a ``blocking'' API;
+in fact, the model for interaction between application and socket is
+one of asynchronous I/O, which is not typically found in real systems
+(more on this below);
+@item the C-style socket address structures are not used;
+@item the API is not a complete sockets API, such as supporting
+all socket options or all function variants; 
+@item many calls use @code{ns3::Packet} class to transfer data
+between application and socket.  This may seem a little funny to
+people to pass ``Packets'' across a stream socket API, but think
+of these packets as just fancy byte buffers at this level (more
+on this also below).
+@end itemize
+
+@subsection Basic operation and calls
+
+@float Figure,fig:sockets-overview
+@caption{Implementation overview of native sockets API}
+@image{figures/sockets-overview, 10cm}
+@end float
+
+@subsubsection Creating sockets
+
+An application that wants to use sockets must first create one.
+On real systems, this is accomplished by calling socket():
+@verbatim
+     int
+     socket(int domain, int type, int protocol);
+@end verbatim
+which creates a socket in the system and returns an integer descriptor.
+
+In ns-3, we have no equivalent of a system call at the lower layers,
+so we adopt the following model.  There are certain @emph{factory}
+objects that can create sockets.  Each factory is capable of creating
+one type of socket, and if sockets of a particular type are able to
+be created on a given node, then a factory that can create such sockets
+must be aggregated to the Node. 
+@verbatim
+  static Ptr<Socket> CreateSocket (Ptr<Node> node, TypeId tid);
+@end verbatim
+Examples of TypeIds to pass to this method are @code{TcpSocketFactory}, 
+@code{PacketSocketFactory}, and @code{UdpSocketFactory}.
+
+This method returns a smart pointer to a Socket object.  Here is an
+example:  
+@verbatim
+  Ptr<Node> n0;
+  // Do some stuff to build up the Node's internet stack
+  Ptr<Socket> localSocket = Socket::CreateSocket (n0, TcpSocketFactory::GetTypeId ());
+@end verbatim
+
+In some ns-3 code, sockets will not be explicitly created by user's
+main programs, if an ns-3 application does it.  For instance, for
+@code{class ns3::OnOffApplication}, the function @code{StartApplication()}
+performs the socket creation, and the application holds the socket
+pointer.
+
+@subsubsection Using sockets
+
+Below is a typical sequence of socket calls for a TCP client in a
+real implementation:
+@itemize @bullet
+@item @code{sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);}
+@item @code{bind(sock, ...);}
+@item @code{connect(sock, ...);}
+@item @code{send(sock, ...);}
+@item @code{recv(sock, ...);}
+@item @code{close(sock);}
+@end itemize
+
+There are analogs to all of these calls in ns-3, but we will focus on  
+two aspects here.  First, most usage of sockets in real systems 
+requires a way to manage I/O between the application and kernel.  
+These models include @emph{blocking sockets}, @emph{signal-based I/O},
+and @emph{non-blocking sockets} with polling.  In ns-3, we make use
+of the callback mechanisms to support a fourth mode, which is 
+analogous to POSIX @emph{asynchronous I/O}.
+
+In this model, on the sending side, if the @code{send()} call were to
+fail because of insufficient buffers, the application suspends the
+sending of more data until a function registered at the 
+@code{SetSendCallback()} callback is invoked.  An application can
+also ask the socket how much space is available by calling
+@code{GetTxAvailable ()}.  A typical sequence of events for 
+sending data (ignoring connection setup) might be:
+
+@itemize @bullet
+@item @code{SetSendCallback (MakeCallback(&HandleSendCallback));}
+@item @code{Send ();}
+@item @code{Send ();}
+@item ...
+@item @code{// Send fails because buffer is full}
+@item (wait until HandleSendCallback() is called)
+@item (HandleSendCallback() is called by socket, since space now available)
+@item @code{Send (); // Start sending again}
+@end itemize
+
+Similarly, on the receive side, the socket user does not block on
+a call to @code{recv()}.  Instead, the application sets a callback
+with @code{SetRecvCallback ()} in which the socket will notify the
+application when (and how much) there is data to be read, and
+the application then calls @code{Recv()} to read the data until
+no more can be read.
+
+@subsection Packet vs. buffer variants
+
+There are two basic variants of @code{Send()} and @code{Recv()} supported:
+@verbatim
+  virtual int Send (Ptr<Packet> p) = 0;
+  int Send (const uint8_t* buf, uint32_t size);
+
+  Ptr<Packet> Recv (void);
+  int Recv (uint8_t* buf, uint32_t size);
+@end verbatim
+
+The non-Packet variants are left for legacy API reasons.  When calling
+the raw buffer variant of @code{Send()}, the buffer is immediately
+written into a Packet and the @code{Send (Ptr<Packet> p)} is invoked.
+
+Users may find it semantically odd to pass a Packet to a stream socket
+such as TCP.  However, do not let the name bother you; think of 
+@code{ns3::Packet} to be a fancy byte buffer.  There are a few reasons why
+the Packet variants are more likely to be preferred in ns-3:
+
+@itemize @bullet
+@item Users can use the Tags facility of packets to, for example, encode
+a flow ID or other helper data.
+@item Users can exploit the copy-on-write implementation to avoid
+memory copies (on the receive side, the conversion back to a 
+@code{uint8_t* buf} may sometimes incur an additional copy).
+@item Use of Packet is more aligned with the rest of the ns-3 API
+@end itemize
+
+@subsection Sending dummy data
+
+Sometimes, users want the simulator to just pretend that there is an
+actual data payload in the packet (e.g. to calculate transmission delay)
+but do not want to actually produce or consume the data.  This is
+straightforward to support in ns-3; have applications call
+@code{Create<Packet> (size);} instead of @code{Create<Packet> (buffer, size);}.
+Similarly, passing in a zero to the pointer argument in the raw buffer
+variants has the same effect.  Note that, if some subsequent code tries
+to read the Packet data buffer, the fake buffer will be converted to
+a real (zero'ed) buffer on the spot, and the efficiency will be lost there.
+
+@subsection Socket options
+
+@emph{to be completed}
+
+@subsection Socket errno
+
+@emph{to be completed}
+
+@subsection Example programs
+
+@emph{to be completed}
+
+@section POSIX-like sockets API 
+
+@emph{this capability is under development and is scheduled for
+inclusion in August 2008 timeframe; see the repository
+http://code.nsnam.org/mathieu/ns-3-simu for details}
+
+The below is excerpted from Mathieu's post to ns-developers list
+on April 4, 2008.
+
+"To summarize, the goal is that the full posix/socket API is defined in
+src/process/simu.h: each posix type and function is re-defined there
+with a simu_ or SIMU_ prefix to avoid ugly name clashes and collisions
+(feel free to come up with a better prefix).
+
+Each process is created with a call to ProcessManager::Create and is
+attached to that ProcessManager instance. So, if the ProcessManager
+(which is aggregated to a Node in src/helper/process-helper.cc) is
+killed when the simulation ends, the system will automatically reclaim
+all the resources of each process associated to each manager. The same
+happens when an application "exits" from its main function.
+
+The example application defines two posix "processes": the function
+ClientProgram creates a udp socket on the localhost port 2000 and the
+function ServerProgram creates a udp socket on the localhost port 2000.
+The code does not work right now because I did not get the details of
+simu_read right yet but, I do plan to make this work at some point.
+
+I really think that this approach is worthwhile for many reasons, a few
+of which are outlined below:
+@itemize @bullet
+@item makes porting real world application code _much_ easier
+
+@item makes write applications for new users much easier because they can
+read the bsd socket api reference and documentation and write code
+directly.
+
+@item can be used to write applications which work in both simulation and
+in the real world at the same time. To do this, all you have to do is
+write your application to use the simu_ API, and, then, you can chose at
+compile-time which implementation of that API you want to use: you can
+pick one implementation which forwards all calls to the system BSD
+socket API or another one which forwards all calls to the attached
+ProcessManager. Arguably, I did not implement the version which forwards
+to system BSD sockets but, that should be pretty trivial.
+@end itemize
+
+So, anyway, comments about the overall API would be welcome. Students
+interested in the gsoc project for real-world code integration should
+consider looking at this also."
+
--- a/doc/tutorial/tutorial.texi	Sun May 25 14:58:22 2008 -0700
+++ b/doc/tutorial/tutorial.texi	Tue May 27 15:01:11 2008 -0700
@@ -95,9 +95,10 @@
 * Other-network-topologies::
 Part 5:  Key ns-3 objects and systems
 * ns-3 Packets::
+* ns-3 Callbacks::
+* Sockets APIs::
+* ns-3 routing overview::
 Part 6:  Extending ns-3
-* ns-3 Callbacks::
-* ns-3 routing overview::
 * Nonlinear-Thinking::
 * Summary::
 * Object-Model::
@@ -115,6 +116,7 @@
 @include helpers.texi
 @include packets.texi
 @include callbacks.texi
+@include sockets.texi
 @c @include output.texi
 @include routing.texi
 @c @include other.texi
--- a/examples/csma-broadcast.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/csma-broadcast.cc	Tue May 27 15:01:11 2008 -0700
@@ -49,6 +49,7 @@
 #if 0
   LogComponentEnable ("CsmaBroadcastExample", LOG_LEVEL_INFO);
 #endif
+  LogComponentEnable ("CsmaBroadcastExample", LOG_PREFIX_TIME);
 
   //
   // Make the random number generators generate reproducible results.
@@ -93,7 +94,7 @@
   // Create the OnOff application to send UDP datagrams of size
   // 512 bytes (default) at a rate of 500 Kb/s (default) from n0
   NS_LOG_INFO ("Create Applications.");
-  OnOffHelper onoff ("ns3::Udp", 
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
     Address (InetSocketAddress (Ipv4Address ("255.255.255.255"), port)));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
@@ -104,7 +105,7 @@
   app.Stop (Seconds (10.0));
   
   // Create an optional packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp",
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
     Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
   sink.Install (c0.Get (1));
   sink.Install (c1.Get (1));
--- a/examples/csma-multicast.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/csma-multicast.cc	Tue May 27 15:01:11 2008 -0700
@@ -140,7 +140,7 @@
 
   // Configure a multicast packet generator that generates a packet
   // every few seconds
-  OnOffHelper onoff ("ns3::Udp", 
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
     Address (InetSocketAddress (multicastGroup, multicastPort)));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
@@ -156,7 +156,7 @@
   srcC.Stop (Seconds(10.));
 
   // Create an optional packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp",
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
                          InetSocketAddress (Ipv4Address::GetAny(), multicastPort));
 
   ApplicationContainer sinkC = sink.Install (c1.Get (2)); // Node n4 
--- a/examples/csma-one-subnet.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/csma-one-subnet.cc	Tue May 27 15:01:11 2008 -0700
@@ -95,7 +95,7 @@
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
 
-  OnOffHelper onoff ("ns3::Udp", 
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
     Address (InetSocketAddress (Ipv4Address ("10.1.1.2"), port)));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
@@ -106,7 +106,7 @@
   app.Stop (Seconds (10.0));
 
   // Create an optional packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp",
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
     Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
   sink.Install (c.Get (1));
 
--- a/examples/mixed-global-routing.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/mixed-global-routing.cc	Tue May 27 15:01:11 2008 -0700
@@ -110,7 +110,7 @@
   // 210 bytes at a rate of 448 Kb/s
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  OnOffHelper onoff ("ns3::Udp",
+  OnOffHelper onoff ("ns3::UdpSocketFactory",
                      InetSocketAddress (i5i6.GetAddress (1), port));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
--- a/examples/mixed-wireless.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/mixed-wireless.cc	Tue May 27 15:01:11 2008 -0700
@@ -308,7 +308,7 @@
   Ptr<Node> appSink = NodeList::GetNode (13);  
   Ipv4Address remoteAddr = Ipv4Address ("172.16.0.5");
 
-  OnOffHelper onoff ("ns3::Udp", 
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
                      Address (InetSocketAddress (remoteAddr, port)));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
@@ -317,7 +317,7 @@
   apps.Stop (Seconds (20.0));
 
   // Create a packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp", 
+  PacketSinkHelper sink ("ns3::UdpSocketFactory", 
                          InetSocketAddress (Ipv4Address::GetAny (), port));
   apps = sink.Install (appSink);
   apps.Start (Seconds (3.0));
--- a/examples/simple-alternate-routing.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/simple-alternate-routing.cc	Tue May 27 15:01:11 2008 -0700
@@ -141,7 +141,7 @@
   uint16_t port = 9;   // Discard port (RFC 863)
 
   // Create a flow from n3 to n1, starting at time 1.1 seconds
-  OnOffHelper onoff ("ns3::Udp",
+  OnOffHelper onoff ("ns3::UdpSocketFactory",
     Address (InetSocketAddress (i1i2.GetAddress (0), port)));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
@@ -151,7 +151,7 @@
   apps.Start (Seconds (10.0));
 
   // Create a packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp",
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
     Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
   apps = sink.Install (c.Get (1));
   apps.Start (Seconds (1.1));
--- a/examples/simple-error-model.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/simple-error-model.cc	Tue May 27 15:01:11 2008 -0700
@@ -122,7 +122,7 @@
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
 
-  OnOffHelper onoff ("ns3::Udp",
+  OnOffHelper onoff ("ns3::UdpSocketFactory",
     Address (InetSocketAddress (i3i2.GetAddress (1), port)));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable(1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable(0)));
@@ -132,7 +132,7 @@
   apps.Stop (Seconds(10.0));
 
   // Create an optional packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp",
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
     Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
   apps = sink.Install (c.Get (3));
   apps.Start (Seconds (1.0));
--- a/examples/simple-global-routing.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/simple-global-routing.cc	Tue May 27 15:01:11 2008 -0700
@@ -122,7 +122,7 @@
   // 210 bytes at a rate of 448 Kb/s
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  OnOffHelper onoff ("ns3::Udp", 
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
     Address (InetSocketAddress (i3i2.GetAddress (0), port)));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
@@ -131,7 +131,7 @@
   apps.Stop (Seconds (10.0));
 
   // Create a packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp",
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
     Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
   apps = sink.Install (c.Get (3));
   apps.Start (Seconds (1.0));
--- a/examples/simple-point-to-point-olsr.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/simple-point-to-point-olsr.cc	Tue May 27 15:01:11 2008 -0700
@@ -127,7 +127,7 @@
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
 
-  OnOffHelper onoff ("ns3::Udp", 
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
                      InetSocketAddress (i34.GetAddress (1), port));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
@@ -137,7 +137,7 @@
   apps.Stop (Seconds (10.0));
 
   // Create a packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Udp",
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
                          InetSocketAddress (Ipv4Address::GetAny (), port));
 
   apps = sink.Install (c.Get (3));
--- a/examples/tcp-large-transfer.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/tcp-large-transfer.cc	Tue May 27 15:01:11 2008 -0700
@@ -169,16 +169,15 @@
   uint16_t servPort = 50000;
 
   // Create a packet sink to receive these packets
-  PacketSinkHelper sink ("ns3::Tcp",
+  PacketSinkHelper sink ("ns3::TcpSocketFactory",
                          InetSocketAddress (Ipv4Address::GetAny (), servPort));
 
   ApplicationContainer apps = sink.Install (c1.Get (1));
   apps.Start (Seconds (0.0));
 
   // and generate traffic to remote sink.
-  Ptr<SocketFactory> socketFactory = 
-    c0.Get (0)->GetObject<Tcp> ();
-  Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+  //TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory");
+  Ptr<Socket> localSocket = Socket::CreateSocket (c0.Get (0), TcpSocketFactory::GetTypeId ());
   localSocket->Bind ();
   Simulator::ScheduleNow (&StartFlow, localSocket, nBytes,
                           ipInterfs.GetAddress (1), servPort);
--- a/examples/wifi-adhoc.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/wifi-adhoc.cc	Tue May 27 15:01:11 2008 -0700
@@ -38,7 +38,7 @@
   Experiment (std::string name);
   GnuplotDataset Run (const WifiHelper &wifi);
 private:
-  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &address);
+  void ReceivePacket (Ptr<Socket> socket);
   void SetPosition (Ptr<Node> node, Vector position);
   Vector GetPosition (Ptr<Node> node);
   void AdvancePosition (Ptr<Node> node);
@@ -90,17 +90,20 @@
 }
 
 void
-Experiment::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &address)
+Experiment::ReceivePacket (Ptr<Socket> socket)
 {
-  m_bytesTotal += packet->GetSize ();
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
+    {
+      m_bytesTotal += packet->GetSize ();
+    }
 }
 
 Ptr<Socket>
 Experiment::SetupPacketReceive (Ptr<Node> node)
 {
-  TypeId tid = TypeId::LookupByName ("ns3::PacketSocketFactory");
-  Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
-  Ptr<Socket> sink = socketFactory->CreateSocket ();
+  TypeId tid = TypeId::LookupByName ("ns3::PacketSocket");
+  Ptr<Socket> sink = Socket::CreateSocket (node, tid);
   sink->Bind ();
   sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
   return sink;
@@ -133,7 +136,7 @@
   socket.SetPhysicalAddress (devices.Get (1)->GetAddress ());
   socket.SetProtocol (1);
 
-  OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
+  OnOffHelper onoff ("ns3::PacketSocket", Address (socket));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (250)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
   onoff.SetAttribute ("DataRate", DataRateValue (DataRate (60000000)));
--- a/examples/wifi-ap.cc	Sun May 25 14:58:22 2008 -0700
+++ b/examples/wifi-ap.cc	Tue May 27 15:01:11 2008 -0700
@@ -162,7 +162,7 @@
   socket.SetPhysicalAddress (staDevs.Get (1)->GetAddress ());
   socket.SetProtocol (1);
 
-  OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
+  OnOffHelper onoff ("ns3::PacketSocket", Address (socket));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (42)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
 
--- a/samples/main-simple.cc	Sun May 25 14:58:22 2008 -0700
+++ b/samples/main-simple.cc	Tue May 27 15:01:11 2008 -0700
@@ -23,9 +23,13 @@
 }
 
 static void
-SocketPrinter (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+SocketPrinter (Ptr<Socket> socket)
 {
-  std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet->GetSize () << std::endl;
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
+    { 
+      std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet->GetSize () << std::endl;
+    }
 }
 
 static void
@@ -44,14 +48,12 @@
   internet.Install (c);
 
 
-  TypeId tid = TypeId::LookupByName ("ns3::Udp");
-  Ptr<SocketFactory> socketFactory = c.Get (0)->GetObject<SocketFactory> (tid);
-
-  Ptr<Socket> sink = socketFactory->CreateSocket ();
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> sink = Socket::CreateSocket (c.Get (0), tid);
   InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
   sink->Bind (local);
 
-  Ptr<Socket> source = socketFactory->CreateSocket ();
+  Ptr<Socket> source = Socket::CreateSocket (c.Get (0), tid);
   InetSocketAddress remote = InetSocketAddress (Ipv4Address::GetLoopback (), 80);
   source->Connect (remote);
 
--- a/src/applications/onoff/onoff-application.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/applications/onoff/onoff-application.cc	Tue May 27 15:01:11 2008 -0700
@@ -35,7 +35,7 @@
 #include "ns3/uinteger.h"
 #include "ns3/trace-source-accessor.h"
 #include "onoff-application.h"
-#include "ns3/udp.h"
+#include "ns3/udp-socket-factory.h"
 
 NS_LOG_COMPONENT_DEFINE ("OnOffApplication");
 
@@ -79,7 +79,7 @@
                    MakeUintegerAccessor (&OnOffApplication::m_maxBytes),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("Protocol", "The type of protocol to use.",
-                   TypeIdValue (Udp::GetTypeId ()),
+                   TypeIdValue (UdpSocketFactory::GetTypeId ()),
                    MakeTypeIdAccessor (&OnOffApplication::m_tid),
                    MakeTypeIdChecker ())
     .AddTraceSource ("Tx", "A new packet is created and is sent",
@@ -130,8 +130,7 @@
   // Create the socket if not already
   if (!m_socket)
     {
-      Ptr<SocketFactory> socketFactory = GetNode ()->GetObject<SocketFactory> (m_tid);
-      m_socket = socketFactory->CreateSocket ();
+      m_socket = Socket::CreateSocket (GetNode(), m_tid);
       m_socket->Bind ();
       m_socket->Connect (m_peer);
     }
--- a/src/applications/packet-sink/packet-sink.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/applications/packet-sink/packet-sink.cc	Tue May 27 15:01:11 2008 -0700
@@ -26,7 +26,7 @@
 #include "ns3/socket-factory.h"
 #include "ns3/packet.h"
 #include "ns3/trace-source-accessor.h"
-#include "ns3/udp.h"
+#include "ns3/udp-socket-factory.h"
 #include "packet-sink.h"
 
 using namespace std;
@@ -47,7 +47,7 @@
                    MakeAddressAccessor (&PacketSink::m_local),
                    MakeAddressChecker ())
     .AddAttribute ("Protocol", "The type id of the protocol to use for the rx socket.",
-                   TypeIdValue (Udp::GetTypeId ()),
+                   TypeIdValue (UdpSocketFactory::GetTypeId ()),
                    MakeTypeIdAccessor (&PacketSink::m_tid),
                    MakeTypeIdChecker ())
     .AddTraceSource ("Rx", "A packet has been received",
@@ -80,14 +80,12 @@
   // Create the socket if not already
   if (!m_socket)
     {
-      Ptr<SocketFactory> socketFactory = 
-        GetNode ()->GetObject<SocketFactory> (m_tid);
-      m_socket = socketFactory->CreateSocket ();
+      m_socket = Socket::CreateSocket (GetNode(), m_tid);
       m_socket->Bind (m_local);
       m_socket->Listen (0);
     }
 
-  m_socket->SetRecvCallback (MakeCallback(&PacketSink::Receive, this));
+  m_socket->SetRecvCallback (MakeCallback(&PacketSink::HandleRead, this));
   m_socket->SetAcceptCallback (
             MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
             MakeNullCallback<void, Ptr<Socket>, const Address&> (),
@@ -98,23 +96,30 @@
 {
   if (m_socket) 
     {
-      m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket>, 
-        Ptr<Packet>, const Address &> ());
+      m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
     }
 }
 
-// This LOG output inspired by the application on Joseph Kopena's wiki
-void PacketSink::Receive(Ptr<Socket> socket, Ptr<Packet> packet,
-                       const Address &from) 
+void PacketSink::HandleRead (Ptr<Socket> socket)
 {
-  if (InetSocketAddress::IsMatchingType (from))
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
     {
-      InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
-      NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " << 
-        address.GetIpv4() << " [" << address << "]---'" << 
-        packet->PeekData() << "'");
+      SocketRxAddressTag tag;
+      bool found;
+      found = packet->FindFirstMatchingTag (tag);
+      NS_ASSERT (found);
+      Address from = tag.GetAddress ();
+      // XXX packet->RemoveTag (tag);
+      if (InetSocketAddress::IsMatchingType (from))
+        {
+          InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
+          NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " << 
+            address.GetIpv4() << " [" << address << "]---'" << 
+            packet->PeekData() << "'");
+        }    
+      m_rxTrace (packet, from);
     }
-  m_rxTrace (packet, from);
 }
 
 void PacketSink::CloseConnection (Ptr<Socket> socket)
--- a/src/applications/packet-sink/packet-sink.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/applications/packet-sink/packet-sink.h	Tue May 27 15:01:11 2008 -0700
@@ -65,7 +65,8 @@
   virtual void StartApplication (void);    // Called at time specified by Start
   virtual void StopApplication (void);     // Called at time specified by Stop
 
-  virtual void Receive (Ptr<Socket> socket, Ptr<Packet> packet, const Address& from);
+  virtual void HandleRead (Ptr<Socket> socket);
+
   virtual void CloseConnection (Ptr<Socket> socket);
 
   Ptr<Socket>     m_socket;       // Associated socket
--- a/src/applications/udp-echo/udp-echo-client.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/applications/udp-echo/udp-echo-client.cc	Tue May 27 15:01:11 2008 -0700
@@ -95,15 +95,13 @@
 
   if (m_socket == 0)
     {
-      TypeId tid = TypeId::LookupByName ("ns3::Udp");
-      Ptr<SocketFactory> socketFactory = 
-        GetNode ()->GetObject<SocketFactory> (tid);
-      m_socket = socketFactory->CreateSocket ();
+      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+      m_socket = Socket::CreateSocket (GetNode(), tid);
       m_socket->Bind ();
       m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
     }
 
-  m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::Receive, this));
+  m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::HandleRead, this));
 
   ScheduleTransmit (Seconds(0.));
 }
@@ -115,8 +113,7 @@
 
   if (m_socket != 0) 
     {
-      m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>, 
-        Ptr<Packet>, const Address &> ());
+      m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
     }
 
   Simulator::Cancel(m_sendEvent);
@@ -149,20 +146,25 @@
 }
 
 void
-UdpEchoClient::Receive(
-  Ptr<Socket> socket, 
-  Ptr<Packet> packet,
-  const Address &from) 
+UdpEchoClient::HandleRead (Ptr<Socket> socket)
 {
-  NS_LOG_FUNCTION (this << socket << packet << from);
-
-  if (InetSocketAddress::IsMatchingType (from))
+  NS_LOG_FUNCTION (this << socket);
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
     {
-      InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
-      NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " << 
-        address.GetIpv4());
+      SocketRxAddressTag tag;
+      bool found;
+      found  = packet->FindFirstMatchingTag (tag);
+      NS_ASSERT (found);
+      Address from = tag.GetAddress ();
+      // XXX packet->RemoveTag (tag);
+      if (InetSocketAddress::IsMatchingType (from))
+        {
+          InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
+          NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
+            address.GetIpv4());
+        }
     }
 }
 
-
 } // Namespace ns3
--- a/src/applications/udp-echo/udp-echo-client.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/applications/udp-echo/udp-echo-client.h	Tue May 27 15:01:11 2008 -0700
@@ -56,7 +56,7 @@
   void ScheduleTransmit (Time dt);
   void Send (void);
 
-  void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void HandleRead (Ptr<Socket> socket);
 
   uint32_t m_count;
   Time m_interval;
--- a/src/applications/udp-echo/udp-echo-server.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/applications/udp-echo/udp-echo-server.cc	Tue May 27 15:01:11 2008 -0700
@@ -71,16 +71,13 @@
 
   if (m_socket == 0)
     {
-      TypeId tid = TypeId::LookupByName ("ns3::Udp");
-      Ptr<SocketFactory> socketFactory = 
-        GetNode ()->GetObject<SocketFactory> (tid);
-      m_socket = socketFactory->CreateSocket ();
-      InetSocketAddress local = 
-        InetSocketAddress (Ipv4Address::GetAny (), m_port);
+      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+      m_socket = Socket::CreateSocket (GetNode(), tid);
+      InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), m_port);
       m_socket->Bind (local);
     }
 
-  m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::Receive, this));
+  m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this));
 }
 
 void 
@@ -90,27 +87,31 @@
 
   if (m_socket != 0) 
     {
-      m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>, 
-        Ptr<Packet>, const Address &> ());
+      m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
     }
 }
 
-void
-UdpEchoServer::Receive(
-  Ptr<Socket> socket, 
-  Ptr<Packet> packet,
-  const Address &from) 
+void 
+UdpEchoServer::HandleRead (Ptr<Socket> socket)
 {
-  NS_LOG_FUNCTION (this << socket << packet << from);
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
+    {
+      SocketRxAddressTag tag;
+      bool found;
+      found = packet->FindFirstMatchingTag (tag); 
+      NS_ASSERT (found);
+      Address from = tag.GetAddress ();
+      // XXX packet->RemoveTag (tag);
+      if (InetSocketAddress::IsMatchingType (from))
+        {
+          InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
+          NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " << 
+            address.GetIpv4());
 
-  if (InetSocketAddress::IsMatchingType (from))
-    {
-      InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
-      NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " << 
-        address.GetIpv4());
-
-      NS_LOG_LOGIC ("Echoing packet");
-      socket->SendTo (from, packet);
+          NS_LOG_LOGIC ("Echoing packet");
+          socket->SendTo (packet, from);
+        }
     }
 }
 
--- a/src/applications/udp-echo/udp-echo-server.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/applications/udp-echo/udp-echo-server.h	Tue May 27 15:01:11 2008 -0700
@@ -49,7 +49,7 @@
   virtual void StartApplication (void);
   virtual void StopApplication (void);
 
-  void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void HandleRead (Ptr<Socket> socket);
 
   uint16_t m_port;
   Ptr<Socket> m_socket;
--- a/src/common/data-rate.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/common/data-rate.h	Tue May 27 15:01:11 2008 -0700
@@ -80,7 +80,6 @@
    */
   uint64_t GetBitRate() const;
 
-  ATTRIBUTE_HELPER_HEADER_1 (DataRate);
 private:
   uint64_t m_bps;
   static uint64_t Parse(const std::string);
@@ -94,7 +93,7 @@
  * \brief hold objects of type ns3::DataRate
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (DataRate);
+ATTRIBUTE_HELPER_HEADER (DataRate);
 
 /**
  * \param lhs
--- a/src/contrib/gtk-config-store.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/contrib/gtk-config-store.cc	Tue May 27 15:01:11 2008 -0700
@@ -304,7 +304,7 @@
       }
     break;
   case ModelNode::NODE_ATTRIBUTE: {
-    uint32_t attrIndex;
+    uint32_t attrIndex = 0;
     TypeId tid;
     for (tid = node->object->GetInstanceTypeId (); tid.HasParent (); tid = tid.GetParent ())
       {
--- a/src/core/attribute-helper.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/core/attribute-helper.h	Tue May 27 15:01:11 2008 -0700
@@ -83,8 +83,7 @@
  *
  * The simple macros are implemented in terms of the complex
  * macros and should generally be prefered over the complex macros:
- *    - \ref ATTRIBUTE_HELPER_HEADER_1,
- *    - \ref ATTRIBUTE_HELPER_HEADER_2, and,
+ *    - \ref ATTRIBUTE_HELPER_HEADER, and,
  *    - \ref ATTRIBUTE_HELPER_CPP,
  */
 
@@ -236,19 +235,10 @@
  * \ingroup AttributeHelper
  * \param type the name of the class
  *
- * This macro should be invoked from a public section of the class
- * declaration.
- */
-#define ATTRIBUTE_HELPER_HEADER_1(type)
-
-/**
- * \ingroup AttributeHelper
- * \param type the name of the class
- *
  * This macro should be invoked outside of the class
  * declaration in its public header.
  */
-#define ATTRIBUTE_HELPER_HEADER_2(type)					\
+#define ATTRIBUTE_HELPER_HEADER(type)					\
   ATTRIBUTE_VALUE_DEFINE (type);					\
   ATTRIBUTE_ACCESSOR_DEFINE (type);					\
   ATTRIBUTE_CHECKER_DEFINE (type);
--- a/src/core/attribute-test.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/core/attribute-test.cc	Tue May 27 15:01:11 2008 -0700
@@ -53,7 +53,7 @@
 {
   return is;
 }
-ATTRIBUTE_HELPER_HEADER_2 (ValueClassTest);
+ATTRIBUTE_HELPER_HEADER (ValueClassTest);
 ATTRIBUTE_HELPER_CPP (ValueClassTest);
 
 class AttributeTest : public Test
--- a/src/core/log.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/core/log.h	Tue May 27 15:01:11 2008 -0700
@@ -69,7 +69,7 @@
 #define NS_LOG_COMPONENT_DEFINE(name)                           \
   static ns3::LogComponent g_log = ns3::LogComponent (name)
 
-#define APPEND_TIME_PREFIX                                      \
+#define NS_LOG_APPEND_TIME_PREFIX                               \
   if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME))                   \
     {                                                           \
       LogTimePrinter printer = LogGetTimePrinter ();            \
@@ -80,13 +80,17 @@
         }                                                       \
     }
 
-#define APPEND_FUNC_PREFIX                                      \
+#define NS_LOG_APPEND_FUNC_PREFIX                               \
   if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC))                   \
     {                                                           \
       std::clog << g_log.Name () << ":" <<                      \
         __FUNCTION__ << "(): ";                                 \
     }                                                           \
 
+#ifndef NS_LOG_APPEND_CONTEXT
+#define NS_LOG_APPEND_CONTEXT
+#endif /* NS_LOG_APPEND_CONTEXT */
+
 
 /**
  * \ingroup logging
@@ -107,8 +111,9 @@
     {                                                           \
       if (g_log.IsEnabled (level))                              \
         {                                                       \
-          APPEND_TIME_PREFIX;                                   \
-          APPEND_FUNC_PREFIX;                                   \
+          NS_LOG_APPEND_TIME_PREFIX;                            \
+          NS_LOG_APPEND_CONTEXT;                                \
+          NS_LOG_APPEND_FUNC_PREFIX;                            \
           std::clog << msg << std::endl;                        \
         }                                                       \
     }                                                           \
@@ -160,7 +165,8 @@
     {                                                           \
       if (g_log.IsEnabled (ns3::LOG_FUNCTION))                  \
         {                                                       \
-          APPEND_TIME_PREFIX;                                   \
+          NS_LOG_APPEND_TIME_PREFIX;                            \
+          NS_LOG_APPEND_CONTEXT;                                \
           std::clog << g_log.Name () << ":"                     \
                     << __FUNCTION__ << "()" << std::endl;       \
         }                                                       \
@@ -189,7 +195,8 @@
     {                                                   \
       if (g_log.IsEnabled (ns3::LOG_FUNCTION))          \
         {                                               \
-          APPEND_TIME_PREFIX;                           \
+          NS_LOG_APPEND_TIME_PREFIX;                    \
+          NS_LOG_APPEND_CONTEXT;                        \
           std::clog << g_log.Name () << ":"             \
                     << __FUNCTION__ << "(";             \
           ParameterLogger (std::clog)  << parameters;   \
--- a/src/core/object-factory.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/core/object-factory.h	Tue May 27 15:01:11 2008 -0700
@@ -77,7 +77,6 @@
   template <typename T>
   Ptr<T> Create (void) const;
 
-  ATTRIBUTE_HELPER_HEADER_1 (ObjectFactory);
 private:
   friend std::ostream & operator << (std::ostream &os, const ObjectFactory &factory);
   friend std::istream & operator >> (std::istream &is, ObjectFactory &factory);
@@ -94,7 +93,7 @@
  * \brief hold objects of type ns3::ObjectFactory
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (ObjectFactory);
+ATTRIBUTE_HELPER_HEADER (ObjectFactory);
 
 } // namespace ns3
 
--- a/src/core/type-id.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/core/type-id.cc	Tue May 27 15:01:11 2008 -0700
@@ -386,7 +386,7 @@
 TypeId::LookupByName (std::string name)
 {
   uint16_t uid = Singleton<IidManager>::Get ()->GetUid (name);
-  NS_ASSERT (uid != 0);
+  NS_ASSERT_MSG (uid != 0, "Assert in TypeId::LookupByName: " << name << " not found");
   return TypeId (uid);
 }
 bool
--- a/src/core/type-id.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/core/type-id.h	Tue May 27 15:01:11 2008 -0700
@@ -354,7 +354,6 @@
   TypeId ();
   ~TypeId ();
 
-  ATTRIBUTE_HELPER_HEADER_1 (TypeId);
 private:
   friend class AttributeList;
   friend bool operator == (TypeId a, TypeId b);
@@ -388,7 +387,7 @@
  */
 
 
-ATTRIBUTE_HELPER_HEADER_2 (TypeId);
+ATTRIBUTE_HELPER_HEADER (TypeId);
 
 } // namespace ns3 
 
--- a/src/devices/wifi/ssid.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/devices/wifi/ssid.h	Tue May 27 15:01:11 2008 -0700
@@ -49,7 +49,6 @@
   Buffer::Iterator Serialize (Buffer::Iterator i) const;
   Buffer::Iterator Deserialize (Buffer::Iterator i);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Ssid);
 private:
   uint8_t m_ssid[33];
   uint8_t m_length;
@@ -63,7 +62,7 @@
  * \brief hold objects of type ns3::Ssid
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Ssid);
+ATTRIBUTE_HELPER_HEADER (Ssid);
 
 } // namespace ns3
 
--- a/src/devices/wifi/wifi-mode.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/devices/wifi/wifi-mode.h	Tue May 27 15:01:11 2008 -0700
@@ -107,7 +107,6 @@
    */
   WifiMode ();
 
-  ATTRIBUTE_HELPER_HEADER_1 (WifiMode);
 private:
   friend class WifiModeFactory;
   WifiMode (uint32_t uid);
@@ -123,7 +122,7 @@
  * \brief hold objects of type ns3::WifiMode
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (WifiMode);
+ATTRIBUTE_HELPER_HEADER (WifiMode);
 
 /**
  * \brief create WifiMode class instances and keep track of them.
--- a/src/helper/packet-sink-helper.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/helper/packet-sink-helper.cc	Tue May 27 15:01:11 2008 -0700
@@ -41,13 +41,13 @@
 void 
 PacketSinkHelper::SetUdpLocal (Ipv4Address ip, uint16_t port)
 {
-  m_factory.Set ("Protocol", String ("ns3::Udp"));
+  m_factory.Set ("Protocol", String ("ns3::UdpSocketFactory"));
   m_factory.Set ("Local", Address (InetSocketAddress (ip, port)));
 }
 void 
 PacketSinkHelper::SetTcpLocal (Ipv4Address ip, uint16_t port)
 {
-  m_factory.Set ("Protocol", String ("ns3::Tcp"));
+  m_factory.Set ("Protocol", String ("ns3::TcpSocketFactory"));
   m_factory.Set ("Local", Address (InetSocketAddress (ip, port)));
 }
 #endif
--- a/src/internet-node/internet-stack.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/internet-stack.cc	Tue May 27 15:01:11 2008 -0700
@@ -27,8 +27,8 @@
 #include "tcp-l4-protocol.h"
 #include "ipv4-l3-protocol.h"
 #include "arp-l3-protocol.h"
-#include "udp-impl.h"
-#include "tcp-impl.h"
+#include "udp-socket-factory-impl.h"
+#include "tcp-socket-factory-impl.h"
 #include "ipv4-impl.h"
 
 namespace ns3 {
@@ -58,19 +58,19 @@
   ipv4L4Demux->Insert (udp);
   ipv4L4Demux->Insert (tcp);
 
-  Ptr<UdpImpl> udpImpl = CreateObject<UdpImpl> ();
-  Ptr<TcpImpl> tcpImpl = CreateObject<TcpImpl> ();
+  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
+  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
   Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
 
-  udpImpl->SetUdp (udp);
-  tcpImpl->SetTcp (tcp);
+  udpFactory->SetUdp (udp);
+  tcpFactory->SetTcp (tcp);
   ipv4Impl->SetIpv4 (ipv4);
 
   node->AggregateObject (ipv4);
   node->AggregateObject (arp);
   node->AggregateObject (ipv4Impl);
-  node->AggregateObject (udpImpl);
-  node->AggregateObject (tcpImpl);
+  node->AggregateObject (udpFactory);
+  node->AggregateObject (tcpFactory);
   node->AggregateObject (ipv4L4Demux);
 }
 
--- a/src/internet-node/ipv4-l3-protocol.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/ipv4-l3-protocol.cc	Tue May 27 15:01:11 2008 -0700
@@ -24,6 +24,7 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/ipv4-route.h"
 #include "ns3/node.h"
+#include "ns3/socket.h"
 #include "ns3/net-device.h"
 #include "ns3/uinteger.h"
 #include "ns3/trace-source-accessor.h"
@@ -491,6 +492,34 @@
 
   m_identification ++;
 
+  // Set TTL to 1 if it is a broadcast packet of any type.  Otherwise,
+  // possibly override the default TTL if the packet is tagged
+  SocketIpTtlTag tag;
+  bool found = packet->FindFirstMatchingTag (tag);
+
+  if (destination.IsBroadcast ()) 
+    {
+      ipHeader.SetTtl (1);
+    }
+  else if (found)
+    {
+      ipHeader.SetTtl (tag.GetTtl ());
+      // XXX remove tag here?  
+    }
+  else
+    {
+      uint32_t ifaceIndex = 0;
+      for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
+           ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
+        {
+          Ptr<Ipv4Interface> outInterface = *ifaceIter;
+          if (destination.IsSubnetDirectedBroadcast (
+                outInterface->GetNetworkMask ()))
+          {
+            ipHeader.SetTtl (1);
+          }
+        }
+    }
   if (destination.IsBroadcast ())
     {
       uint32_t ifaceIndex = 0;
--- a/src/internet-node/tcp-header.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/tcp-header.cc	Tue May 27 15:01:11 2008 -0700
@@ -20,7 +20,7 @@
 
 #include <stdint.h>
 #include <iostream>
-#include "tcp-socket.h"
+#include "tcp-socket-impl.h"
 #include "tcp-header.h"
 #include "ns3/buffer.h"
 
--- a/src/internet-node/tcp-header.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/tcp-header.h	Tue May 27 15:01:11 2008 -0700
@@ -24,7 +24,7 @@
 #include <stdint.h>
 #include "ns3/header.h"
 #include "ns3/buffer.h"
-#include "ns3/tcp.h"
+#include "ns3/tcp-socket-factory.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/sequence-number.h"
 
--- a/src/internet-node/tcp-impl.cc	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/* -*- 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 ()
-  : m_tcp (0)
-{}
-TcpImpl::~TcpImpl ()
-{
-  NS_ASSERT (m_tcp == 0);
-}
-
-void 
-TcpImpl::SetTcp (Ptr<TcpL4Protocol> tcp)
-{
-  m_tcp = tcp;
-}
-
-Ptr<Socket>
-TcpImpl::CreateSocket (void)
-{
-  return m_tcp->CreateSocket ();
-}
-
-void 
-TcpImpl::DoDispose (void)
-{
-  m_tcp = 0;
-  Tcp::DoDispose ();
-}
-
-} // namespace ns3
--- a/src/internet-node/tcp-impl.h	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* -*- 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 ();
-  virtual ~TcpImpl ();
-
-  void SetTcp (Ptr<TcpL4Protocol> tcp);
-
-  virtual Ptr<Socket> CreateSocket (void);
-
-protected:
-  virtual void DoDispose (void);
-private:
-  Ptr<TcpL4Protocol> m_tcp;
-};
-
-} // namespace ns3
-
-#endif /* TCP_IMPL_H */
--- a/src/internet-node/tcp-l4-protocol.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/tcp-l4-protocol.cc	Tue May 27 15:01:11 2008 -0700
@@ -30,7 +30,7 @@
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
-#include "tcp-socket.h"
+#include "tcp-socket-impl.h"
 
 #include "tcp-typedefs.h"
 
@@ -379,7 +379,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
   Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
-  Ptr<TcpSocket> socket = CreateObject<TcpSocket> ();
+  Ptr<TcpSocketImpl> socket = CreateObject<TcpSocketImpl> ();
   socket->SetNode (m_node);
   socket->SetTcp (this);
   socket->SetRtt (rtt);
--- a/src/internet-node/tcp-l4-protocol.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/tcp-l4-protocol.h	Tue May 27 15:01:11 2008 -0700
@@ -58,7 +58,7 @@
   virtual int GetVersion (void) const;
 
   /**
-   * \return A smart Socket pointer to a TcpSocket, allocated by this instance
+   * \return A smart Socket pointer to a TcpSocketImpl, allocated by this instance
    * of the TCP protocol
    */
   Ptr<Socket> CreateSocket (void);
@@ -72,7 +72,7 @@
 
   void DeAllocate (Ipv4EndPoint *endPoint);
 
-//   // called by TcpSocket.
+//   // called by TcpSocketImpl.
 //   bool Connect (const Ipv4Address& saddr, const Ipv4Address& daddr,
 //                 uint16_t sport, uint16_t dport);
 
@@ -106,7 +106,7 @@
   Ipv4EndPointDemux *m_endPoints;
   ObjectFactory m_rttFactory;
 private:
-  friend class TcpSocket;
+  friend class TcpSocketImpl;
   void SendPacket (Ptr<Packet>, TcpHeader,
                   Ipv4Address, Ipv4Address);
   static ObjectFactory GetDefaultRttEstimatorFactory (void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket-factory-impl.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,54 @@
+/* -*- 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-socket-factory-impl.h"
+#include "tcp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+TcpSocketFactoryImpl::TcpSocketFactoryImpl ()
+  : m_tcp (0)
+{}
+TcpSocketFactoryImpl::~TcpSocketFactoryImpl ()
+{
+  NS_ASSERT (m_tcp == 0);
+}
+
+void 
+TcpSocketFactoryImpl::SetTcp (Ptr<TcpL4Protocol> tcp)
+{
+  m_tcp = tcp;
+}
+
+Ptr<Socket>
+TcpSocketFactoryImpl::CreateSocket (void)
+{
+  return m_tcp->CreateSocket ();
+}
+
+void 
+TcpSocketFactoryImpl::DoDispose (void)
+{
+  m_tcp = 0;
+  TcpSocketFactory::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket-factory-impl.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,60 @@
+/* -*- 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_FACTORY_IMPL_H
+#define TCP_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/tcp-socket-factory.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::TcpSocketImpl.
+ */
+class TcpSocketFactoryImpl : public TcpSocketFactory
+{
+public:
+  TcpSocketFactoryImpl ();
+  virtual ~TcpSocketFactoryImpl ();
+
+  void SetTcp (Ptr<TcpL4Protocol> tcp);
+
+  virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+  virtual void DoDispose (void);
+private:
+  Ptr<TcpL4Protocol> m_tcp;
+};
+
+} // namespace ns3
+
+#endif /* TCP_SOCKET_FACTORY_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket-impl.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,1433 @@
+/* -*-  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-impl.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/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("TcpSocketImpl");
+
+using namespace std;
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpSocketImpl);
+
+TypeId
+TcpSocketImpl::GetTypeId ()
+{
+  static TypeId tid = TypeId("ns3::TcpSocketImpl")
+    .SetParent<TcpSocket> ()
+    .AddTraceSource ("CongestionWindow",
+                     "The TCP connection's congestion window",
+                     MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))
+    ;
+  return tid;
+}
+
+  TcpSocketImpl::TcpSocketImpl ()
+  : m_skipRetxResched (false),
+    m_dupAckCount (0),
+    m_delAckCount (0),
+    m_endPoint (0),
+    m_node (0),
+    m_tcp (0),
+    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_pendingClose (false),
+    m_nextTxSequence (0),
+    m_highTxMark (0),
+    m_highestRxAck (0),
+    m_lastRxAck (0),
+    m_nextRxSequence (0),
+    m_pendingData (0),
+    m_rtt (0),
+    m_lastMeasuredRtt (Seconds(0.0)),
+    m_rxAvailable (0), 
+    m_wouldBlock (false) 
+{
+  NS_LOG_FUNCTION (this);
+}
+
+TcpSocketImpl::TcpSocketImpl(const TcpSocketImpl& sock)
+  : TcpSocket(sock), //copy the base class callbacks
+    m_skipRetxResched (sock.m_skipRetxResched),
+    m_dupAckCount (sock.m_dupAckCount),
+    m_delAckCount (0),
+    m_delAckMaxCount (sock.m_delAckMaxCount),
+    m_delAckTimeout (sock.m_delAckTimeout),
+    m_endPoint (0),
+    m_node (sock.m_node),
+    m_tcp (sock.m_tcp),
+    m_remoteAddress (sock.m_remoteAddress),
+    m_remotePort (sock.m_remotePort),
+    m_localAddress (sock.m_localAddress),
+    m_localPort (sock.m_localPort),
+    m_errno (sock.m_errno),
+    m_shutdownSend (sock.m_shutdownSend),
+    m_shutdownRecv (sock.m_shutdownRecv),
+    m_connected (sock.m_connected),
+    m_state (sock.m_state),
+    m_closeNotified (sock.m_closeNotified),
+    m_closeRequestNotified (sock.m_closeRequestNotified),
+    m_closeOnEmpty (sock.m_closeOnEmpty),
+    m_pendingClose (sock.m_pendingClose),
+    m_nextTxSequence (sock.m_nextTxSequence),
+    m_highTxMark (sock.m_highTxMark),
+    m_highestRxAck (sock.m_highestRxAck),
+    m_lastRxAck (sock.m_lastRxAck),
+    m_nextRxSequence (sock.m_nextRxSequence),
+    m_pendingData (0),
+    m_segmentSize (sock.m_segmentSize),
+    m_rxWindowSize (sock.m_rxWindowSize),
+    m_advertisedWindowSize (sock.m_advertisedWindowSize),
+    m_cWnd (sock.m_cWnd),
+    m_ssThresh (sock.m_ssThresh),
+    m_initialCWnd (sock.m_initialCWnd),
+    m_rtt (0),
+    m_lastMeasuredRtt (Seconds(0.0)),
+    m_cnTimeout (sock.m_cnTimeout),
+    m_cnCount (sock.m_cnCount),
+    m_rxAvailable (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC("Invoked the copy constructor");
+  //copy the pending data if necessary
+  if(sock.m_pendingData)
+    {
+      m_pendingData = sock.m_pendingData->Copy();
+    }
+  //copy the rtt if necessary
+  if (sock.m_rtt)
+    {
+      m_rtt = sock.m_rtt->Copy();
+    }
+  //can't "copy" the endpoint just yes, must do this when we know the peer info
+  //too; this is in SYN_ACK_TX
+}
+
+TcpSocketImpl::~TcpSocketImpl ()
+{
+  NS_LOG_FUNCTION(this);
+  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
+  m_pendingData = 0;
+}
+
+void
+TcpSocketImpl::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+  // Initialize some variables 
+  m_cWnd = m_initialCWnd * m_segmentSize;
+  m_rxWindowSize = m_advertisedWindowSize;
+}
+
+void 
+TcpSocketImpl::SetTcp (Ptr<TcpL4Protocol> tcp)
+{
+  m_tcp = tcp;
+}
+void 
+TcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
+{
+  m_rtt = rtt;
+}
+
+
+enum Socket::SocketErrno
+TcpSocketImpl::GetErrno (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_errno;
+}
+
+Ptr<Node>
+TcpSocketImpl::GetNode (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node;
+}
+
+void 
+TcpSocketImpl::Destroy (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  m_endPoint = 0;
+  m_tcp = 0;
+  m_retxEvent.Cancel ();
+}
+int
+TcpSocketImpl::FinishBind (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_endPoint == 0)
+    {
+      return -1;
+    }
+  m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr<TcpSocketImpl>(this)));
+  m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr<TcpSocketImpl>(this)));
+  m_localAddress = m_endPoint->GetLocalAddress ();
+  m_localPort = m_endPoint->GetLocalPort ();
+  return 0;
+}
+
+int
+TcpSocketImpl::Bind (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_endPoint = m_tcp->Allocate ();
+  return FinishBind ();
+}
+int 
+TcpSocketImpl::Bind (const Address &address)
+{
+  NS_LOG_FUNCTION (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 ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_tcp->Allocate (port);
+      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+    {
+      m_endPoint = m_tcp->Allocate (ipv4);
+      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_tcp->Allocate (ipv4, port);
+      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+
+  return FinishBind ();
+}
+
+int 
+TcpSocketImpl::ShutdownSend (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownSend = true;
+  return 0;
+}
+int 
+TcpSocketImpl::ShutdownRecv (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownRecv = false;
+  return 0;
+}
+
+int
+TcpSocketImpl::Close (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_state == CLOSED) 
+    {
+      return -1;
+    }
+  if (m_pendingData && m_pendingData->Size() != 0)
+    { // App close with pending data must wait until all data transmitted
+      m_closeOnEmpty = true;
+      NS_LOG_LOGIC("Socket " << this << 
+                   " deferring close, state " << m_state);
+      return 0;
+    }
+
+  Actions_t action  = ProcessEvent (APP_CLOSE);
+  ProcessAction (action);
+  ShutdownSend ();
+  return 0;
+}
+
+int
+TcpSocketImpl::Connect (const Address & address)
+{
+  NS_LOG_FUNCTION (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_remoteAddress = transport.GetIpv4 ();
+  m_remotePort = transport.GetPort ();
+  
+  uint32_t localIfIndex;
+  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+  if (ipv4->GetIfIndexForDestination (m_remoteAddress, 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 
+TcpSocketImpl::Send (const Ptr<Packet> p) //p here is just data, no headers
+{ // TCP Does not deal with packets from app, just data
+  return Send(p->PeekData(), p->GetSize());
+}
+
+int TcpSocketImpl::Send (const uint8_t* buf, uint32_t size)
+{
+  NS_LOG_FUNCTION (this << buf << size);
+  if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+    { 
+      if (size > GetTxAvailable ())
+        {
+          m_wouldBlock = true;
+          m_errno = ERROR_MSGSIZE;
+          return -1;
+        }
+      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);
+      NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() << 
+                   " state " << m_state);
+      Actions_t action = ProcessEvent (APP_SEND);
+      NS_LOG_DEBUG(" action " << action);
+      if (!ProcessAction (action)) 
+        {
+          return -1; // Failed, return zero
+        }
+      return size;
+    }
+  else
+  {
+    m_errno = ERROR_NOTCONN;
+    return -1;
+  }
+}
+
+int TcpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
+{
+  NS_LOG_FUNCTION (this << p << address);
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  Ipv4Address ipv4 = transport.GetIpv4 ();
+  uint16_t port = transport.GetPort ();
+  return DoSendTo (p, ipv4, port);
+}
+
+int TcpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port)
+{
+  NS_LOG_FUNCTION (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 
+TcpSocketImpl::SendTo (Ptr<Packet> p, const Address &address)
+{
+  NS_LOG_FUNCTION (this << address << p);
+  if (!m_connected)
+    {
+      m_errno = ERROR_NOTCONN;
+      return -1;
+    }
+  else
+    {
+      return Send (p); //drop the address according to BSD manpages
+    }
+}
+
+uint32_t
+TcpSocketImpl::GetTxAvailable (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_pendingData != 0)
+    {
+      uint32_t unAckedDataSize = 
+        m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck);
+      NS_ASSERT (m_sndBufSize >= unAckedDataSize); //else a logical error
+      return m_sndBufSize-unAckedDataSize;
+    }
+  else
+    {
+      return m_sndBufSize;
+    }
+}
+
+int
+TcpSocketImpl::Listen (uint32_t q)
+{
+  NS_LOG_FUNCTION (this << q);
+  Actions_t action = ProcessEvent (APP_LISTEN);
+  ProcessAction (action);
+  return 0;
+}
+
+Ptr<Packet>
+TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_deliveryQueue.empty() )
+    {
+      return 0;
+    }
+  Ptr<Packet> p = m_deliveryQueue.front ();
+  if (p->GetSize () <= maxSize)
+    {
+      m_deliveryQueue.pop ();
+      m_rxAvailable -= p->GetSize ();
+    }
+  else
+    {
+      p = 0;
+    }
+  return p;
+}
+
+uint32_t
+TcpSocketImpl::GetRxAvailable (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  // We separately maintain this state to avoid walking the queue 
+  // every time this might be called
+  return m_rxAvailable;
+}
+
+void
+TcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+  NS_LOG_DEBUG("Socket " << this << " got forward up" <<
+               " dport " << m_endPoint->GetLocalPort() <<
+               " daddr " << m_endPoint->GetLocalAddress() <<
+               " sport " << m_endPoint->GetPeerPort() <<
+               " saddr " << m_endPoint->GetPeerAddress());
+
+  NS_LOG_FUNCTION (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);
+  NS_LOG_DEBUG("Socket " << this << 
+               " processing pkt action, " << action <<
+               " current state " << m_state);
+  ProcessPacketAction (action, packet, tcpHeader, address);
+}
+
+Actions_t TcpSocketImpl::ProcessEvent (Events_t e)
+{
+  NS_LOG_FUNCTION (this << e);
+  States_t saveState = m_state;
+  NS_LOG_LOGIC ("TcpSocketImpl " << 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 ("TcpSocketImpl " << 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 ("TcpSocketImpl " << this << " moved from state " << saveState 
+    << " to state " <<m_state);
+  NS_LOG_LOGIC ("TcpSocketImpl " << this << " pendingData " << m_pendingData);
+
+  //extra event logic is here for RX events
+  //e = SYN_ACK_RX
+  if (saveState == SYN_SENT && m_state == ESTABLISHED)
+    // this means the application side has completed its portion of 
+    // the handshaking
+    {
+      Simulator::ScheduleNow(&TcpSocketImpl::ConnectionSucceeded, this);
+      //NotifyConnectionSucceeded ();
+      m_connected = true;
+      m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
+      NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!");
+    }
+
+  if (needCloseNotify && !m_closeNotified)
+    {
+      NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from " 
+               << m_state << " event " << e << " closeNot " << m_closeNotified
+               << " action " << stateAction.action);
+      NotifyCloseCompleted ();
+      m_closeNotified = true;
+      NS_LOG_LOGIC ("TcpSocketImpl " << this << " calling Closed from PE"
+              << " origState " << saveState
+              << " event " << e);
+      NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from "
+          << m_state << " event " << e
+          << " set CloseNotif ");
+    }
+  return stateAction.action;
+}
+
+void TcpSocketImpl::SendEmptyPacket (uint8_t flags)
+{
+  NS_LOG_FUNCTION (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_remotePort);
+  header.SetWindowSize (m_advertisedWindowSize);
+  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), 
+    m_remoteAddress);
+  Time rto = m_rtt->RetransmitTimeout ();
+  if (flags & TcpHeader::SYN)
+    {
+      rto = m_cnTimeout;
+      m_cnTimeout = m_cnTimeout + 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, &TcpSocketImpl::ReTxTimeout, this);
+  }
+}
+
+bool TcpSocketImpl::ProcessAction (Actions_t a)
+{ // These actions do not require a packet or any TCP Headers
+  NS_LOG_FUNCTION (this << a);
+  switch (a)
+  {
+    case NO_ACT:
+      NS_LOG_LOGIC ("TcpSocketImpl " << 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 ("TcpSocketImpl " << this <<" Action RST_TX");
+      SendEmptyPacket (TcpHeader::RST);
+      break;
+    case SYN_TX:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_TX");
+      // TCP SYN Flag consumes one byte
+      // is the above correct? we're SENDING a syn, not acking back -- Raj
+      // commented out for now
+      // m_nextTxSequence+= 1;
+      SendEmptyPacket (TcpHeader::SYN);
+      break;
+    case SYN_ACK_TX:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX");
+      // TCP SYN Flag consumes one byte
+      ++m_nextRxSequence;
+      SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+      break;
+    case FIN_TX:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_TX");
+      SendEmptyPacket (TcpHeader::FIN);
+      break;
+    case FIN_ACK_TX:
+      NS_LOG_LOGIC ("TcpSocketImpl " << 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 ("TcpSocketImpl " << this <<" Action RETX");
+      break;
+    case TX_DATA:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action TX_DATA");
+      SendPendingData ();
+      break;
+    case PEER_CLOSE:
+      NS_ASSERT (false); // This should be processed in ProcessPacketAction
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action PEER_CLOSE");
+      break;
+    case APP_CLOSED:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_CLOSED");
+      break;
+    case CANCEL_TM:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action CANCEL_TM");
+      break;
+    case APP_NOTIFY:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_NOTIFY");
+      break;
+    case SERV_NOTIFY:
+      NS_ASSERT (false); // This should be processed in ProcessPacketAction
+      break;
+    case LAST_ACTION:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action LAST_ACTION");
+      break;
+  }
+  return true;
+}
+
+bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
+                                     const TcpHeader& tcpHeader,
+                                     const Address& fromAddress)
+{
+  NS_LOG_FUNCTION (this << a << p  << fromAddress);
+  uint32_t localIfIndex;
+  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+  switch (a)
+  {
+    case SYN_ACK_TX:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX");
+//      m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
+//      m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
+//       if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
+//         {
+//           m_localAddress = ipv4->GetAddress (localIfIndex);
+//         }
+      if (m_state == LISTEN) //this means we should fork a new TcpSocketImpl
+        {
+          NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this);
+          //notify the server that we got a SYN
+          // If server refuses connection do nothing
+          if (!NotifyConnectionRequest(fromAddress)) return true;
+          // Clone the socket
+          Ptr<TcpSocketImpl> newSock = Copy ();
+          NS_LOG_LOGIC ("Cloned a TcpSocketImpl " << newSock);
+          //this listening socket should do nothing more
+          Simulator::ScheduleNow (&TcpSocketImpl::CompleteFork, newSock,
+                                  p, tcpHeader,fromAddress);
+          return true;
+        }
+        // This is the cloned endpoint
+        m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
+        if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
+          {
+            m_localAddress = ipv4->GetAddress (localIfIndex);
+            m_endPoint->SetLocalAddress (m_localAddress);
+            // Leave local addr in the portmap to any, as the path from
+            // remote can change and packets can arrive on different interfaces
+            //m_endPoint->SetLocalAddress (Ipv4Address::GetAny());
+          }
+        // TCP SYN consumes one byte
+        m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
+        SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+      break;
+    case ACK_TX_1:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1");
+      // TCP SYN consumes one byte
+      m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
+      m_nextTxSequence = tcpHeader.GetAckNumber ();
+      m_firstPendingSequence = m_nextTxSequence;  //bug 166
+      NS_LOG_DEBUG ("TcpSocketImpl " << this << " ACK_TX_1" <<
+                    " nextRxSeq " << m_nextRxSequence);
+      SendEmptyPacket (TcpHeader::ACK);
+      m_rxWindowSize = tcpHeader.GetWindowSize ();
+      if (tcpHeader.GetAckNumber () > m_highestRxAck)
+      {
+        m_highestRxAck = tcpHeader.GetAckNumber ();
+        // Data freed from the send buffer; notify any blocked sender
+        if (m_wouldBlock)
+          {
+            NotifySend (GetTxAvailable ());
+            m_wouldBlock = false;
+          }
+      }
+      SendPendingData ();
+      break;
+    case NEW_ACK:
+      NS_LOG_LOGIC ("TcpSocketImpl " << 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 ("TcpSocketImpl " << this <<" Action NEW_SEQ_RX");
+      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 ("TcpSocketImpl " << 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 ("TcpSocketImpl " << this 
+          << " peer close, state " << m_state);
+      if (!m_closeRequestNotified)
+        {
+          NS_LOG_LOGIC ("TCP " << this 
+              << " calling AppCloseRequest");
+          NotifyCloseRequested(); 
+          m_closeRequestNotified = true;
+        }
+      NS_LOG_LOGIC ("TcpSocketImpl " << 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 ("TcpSocketImpl " << this << " scheduling LATO1");
+          m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
+                                                &TcpSocketImpl::LastAckTimeout,this);
+        }
+      break;
+    }
+    case SERV_NOTIFY:
+      NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SERV_NOTIFY");
+      NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!");
+      NotifyNewConnectionCreated (this, fromAddress);
+      m_connected = true; // ! This is bogus; fix when we clone the tcp
+      m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
+      //treat the connection orientation final ack as a newack
+      CommonNewAck (tcpHeader.GetAckNumber (), true);
+      break;
+    default:
+      break;
+  }
+  return true;
+}
+
+void TcpSocketImpl::CompleteFork(Ptr<Packet> p, const TcpHeader& h, const Address& fromAddress)
+{
+  // Get port and address from peer (connecting host)
+  m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
+  m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
+  m_endPoint = m_tcp->Allocate (m_localAddress,
+                                m_localPort,
+                                m_remoteAddress,
+                                m_remotePort);
+  //the cloned socket with be in listen state, so manually change state
+  m_state = SYN_RCVD;
+  //equivalent to FinishBind
+  m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr<TcpSocketImpl>(this)));
+  m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr<TcpSocketImpl>(this)));
+  ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress);
+ }
+
+void TcpSocketImpl::ConnectionSucceeded()
+{ // We would preferred to have scheduled an event directly to
+  // NotifyConnectionSucceeded, but (sigh) these are protected
+  // and we can get the address of it :(
+  NotifyConnectionSucceeded();
+}
+
+bool TcpSocketImpl::SendPendingData (bool withAck)
+{
+  NS_LOG_FUNCTION (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 ("TcpSocketImpl " << 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
+      Ptr<Packet> p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence, 
+        m_nextTxSequence);
+      NS_LOG_LOGIC("TcpSocketImpl " << this << " sendPendingData"
+                   << " txseq " << m_nextTxSequence
+                   << " s " << s 
+                   << " datasize " << p->GetSize() );
+      uint8_t flags = 0;
+      if (withAck)
+        {
+          flags |= TcpHeader::ACK;
+        }
+      uint32_t sz = p->GetSize (); // 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;
+        }
+
+      TcpHeader header;
+      header.SetFlags (flags);
+      header.SetSequenceNumber (m_nextTxSequence);
+      header.SetAckNumber (m_nextRxSequence);
+      header.SetSourcePort (m_endPoint->GetLocalPort());
+      header.SetDestinationPort (m_remotePort);
+      if (m_shutdownSend)
+        {
+          m_errno = ERROR_SHUTDOWN;
+          return -1;
+        }
+
+      
+      if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
+        {
+            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,&TcpSocketImpl::ReTxTimeout,this);
+        }
+      NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
+      m_tcp->SendPacket (p, header,
+                         m_endPoint->GetLocalAddress (),
+                         m_remoteAddress);
+      m_rtt->SentSeq(m_nextTxSequence, sz);       // notify the RTT
+      // Notify the application
+      Simulator::ScheduleNow(&TcpSocketImpl::NotifyDataSent, this, p->GetSize ());
+      nPacketsSent++;                             // Count sent this loop
+      m_nextTxSequence += sz;                     // Advance next tx sequence
+      // Note the high water mark
+      m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
+    }
+  NS_LOG_LOGIC ("Sent "<<nPacketsSent<<" packets");
+  NS_LOG_LOGIC("RETURN SendPendingData");
+  return (nPacketsSent>0);
+}
+
+uint32_t  TcpSocketImpl::UnAckDataCount ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_nextTxSequence - m_highestRxAck;
+}
+
+uint32_t  TcpSocketImpl::BytesInFlight ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_highTxMark - m_highestRxAck;
+}
+
+uint32_t  TcpSocketImpl::Window ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC ("TcpSocketImpl::Window() "<<this);
+  return std::min (m_rxWindowSize, m_cWnd.Get());
+}
+
+uint32_t  TcpSocketImpl::AvailableWindow ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  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 TcpSocketImpl::NewRx (Ptr<Packet> p,
+                        const TcpHeader& tcpHeader, 
+                        const Address& fromAddress)
+{
+  NS_LOG_FUNCTION (this << p << "tcpHeader " << fromAddress);
+  NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewRx,"
+                << " seq " << tcpHeader.GetSequenceNumber()
+                << " ack " << tcpHeader.GetAckNumber()
+                << " p.size is " << p->GetSize () );
+  NS_LOG_DEBUG ("TcpSocketImpl " << this <<
+                " NewRx," <<
+                " seq " << tcpHeader.GetSequenceNumber() <<
+                " ack " << tcpHeader.GetAckNumber() <<
+                " 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 );
+      SocketRxAddressTag tag;
+      tag.SetAddress (fromAddress);
+      p->AddTag (tag);
+      m_deliveryQueue.push (p);
+      m_rxAvailable += p->GetSize ();
+      NotifyDataRecv ();
+      if (m_closeNotified)
+        {
+          NS_LOG_LOGIC ("Tcp " << this << " HuH?  Got data after closeNotif");
+        }
+      NS_LOG_LOGIC ("TcpSocketImpl " << 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 ();
+            }
+          SocketRxAddressTag tag;
+          tag.SetAddress (fromAddress);
+          p1->AddTag (tag);
+          m_deliveryQueue.push (p1);
+          m_rxAvailable += p->GetSize ();
+          NotifyDataRecv ();
+
+          NS_LOG_LOGIC ("TcpSocketImpl " << 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("TcpSocketImpl " << 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
+  if(++m_delAckCount >= m_delAckMaxCount)
+  {
+    m_delAckEvent.Cancel();
+    m_delAckCount = 0;
+    SendEmptyPacket (TcpHeader::ACK);
+  }
+  else
+  {
+    m_delAckEvent = Simulator::Schedule (m_delAckTimeout, &TcpSocketImpl::DelAckTimeout, this);
+  }
+}
+
+void TcpSocketImpl::DelAckTimeout ()
+{
+  m_delAckCount = 0;
+  SendEmptyPacket (TcpHeader::ACK);
+}
+
+void TcpSocketImpl::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 (this << ack << skipTimer); 
+  //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
+  if (!skipTimer)
+    {
+      m_retxEvent.Cancel ();  
+      //On recieving a "New" ack we restart retransmission timer .. RFC 2988
+      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, &TcpSocketImpl::ReTxTimeout, this);
+    }
+  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack 
+           << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed
+  m_highestRxAck = ack;         // Note the highest recieved Ack
+  if (m_wouldBlock)
+    {
+      // m_highestRxAck advancing means some data was acked, and the size 
+      // of free space in the buffer has increased
+      NotifySend (GetTxAvailable ());
+      m_wouldBlock = false;
+    }
+  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();
+}
+
+Ptr<TcpSocketImpl> TcpSocketImpl::Copy ()
+{
+  return CopyObject<TcpSocketImpl> (this);
+}
+
+void TcpSocketImpl::NewAck (SequenceNumber seq)
+{ // New acknowledgement up to sequence number "seq"
+  // Adjust congestion window in response to new ack's received
+  NS_LOG_FUNCTION (this << seq);
+  NS_LOG_LOGIC ("TcpSocketImpl " << 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 ("TcpSocketImpl " << 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.Get();
+      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 TcpSocketImpl::DupAck (const TcpHeader& t, uint32_t count)
+{
+  NS_LOG_FUNCTION (this << "t " << count);
+  NS_LOG_LOGIC ("TcpSocketImpl " << 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("TcpSocketImpl " << 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 TcpSocketImpl::ReTxTimeout ()
+{ // Retransmit timeout
+  NS_LOG_FUNCTION (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 (); // DoubleValue timeout value for next retx timer
+  Retransmit ();             // Retransmit the packet
+}
+
+void TcpSocketImpl::LastAckTimeout ()
+{
+  m_lastAckEvent.Cancel ();
+  if (m_state == LAST_ACK)
+    {
+      Actions_t action = ProcessEvent (TIMEOUT);
+      ProcessAction (action);
+    }
+  if (!m_closeNotified)
+    {
+      m_closeNotified = true;
+    }
+}
+
+void TcpSocketImpl::Retransmit ()
+{
+  NS_LOG_FUNCTION (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;
+    }
+  Ptr<Packet> p = 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(p->GetSize ()));
+  if (m_closeOnEmpty && remainingData == 0)
+    { // Add the FIN flag
+      flags = flags | TcpHeader::FIN;
+    }
+
+  NS_LOG_LOGIC ("TcpSocketImpl " << 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,&TcpSocketImpl::ReTxTimeout,this);
+    }
+  m_rtt->SentSeq (m_highestRxAck,p->GetSize ());
+  // And send the packet
+  TcpHeader tcpHeader;
+  tcpHeader.SetSequenceNumber (m_nextTxSequence);
+  tcpHeader.SetAckNumber (m_nextRxSequence);
+  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
+  tcpHeader.SetDestinationPort (m_remotePort);
+  tcpHeader.SetFlags (flags);
+  tcpHeader.SetWindowSize (m_advertisedWindowSize);
+
+  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
+    m_remoteAddress);
+}
+
+void
+TcpSocketImpl::SetSndBufSize (uint32_t size)
+{
+  m_sndBufSize = size;
+}
+
+uint32_t
+TcpSocketImpl::GetSndBufSize (void) const
+{
+  return m_sndBufSize;
+}
+
+void
+TcpSocketImpl::SetRcvBufSize (uint32_t size)
+{
+  m_rcvBufSize = size;
+}
+
+uint32_t
+TcpSocketImpl::GetRcvBufSize (void) const
+{
+  return m_rcvBufSize;
+}
+
+void
+TcpSocketImpl::SetSegSize (uint32_t size)
+{
+  m_segmentSize = size;
+}
+
+uint32_t
+TcpSocketImpl::GetSegSize (void) const
+{
+  return m_segmentSize;
+}
+
+void
+TcpSocketImpl::SetAdvWin (uint32_t window)
+{
+  m_advertisedWindowSize = window;
+}
+
+uint32_t
+TcpSocketImpl::GetAdvWin (void) const
+{
+  return m_advertisedWindowSize;
+}
+
+void
+TcpSocketImpl::SetSSThresh (uint32_t threshold)
+{
+  m_ssThresh = threshold;
+}
+
+uint32_t
+TcpSocketImpl::GetSSThresh (void) const
+{
+  return m_ssThresh;
+}
+
+void
+TcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
+{
+  m_initialCWnd = cwnd;
+}
+
+uint32_t
+TcpSocketImpl::GetInitialCwnd (void) const
+{
+  return m_initialCWnd;
+}
+
+void 
+TcpSocketImpl::SetConnTimeout (Time timeout)
+{
+  m_cnTimeout = timeout;
+}
+
+Time
+TcpSocketImpl::GetConnTimeout (void) const
+{
+  return m_cnTimeout;
+}
+
+void 
+TcpSocketImpl::SetConnCount (uint32_t count)
+{
+  m_cnCount = count;
+}
+
+uint32_t 
+TcpSocketImpl::GetConnCount (void) const
+{
+  return m_cnCount;
+}
+
+void 
+TcpSocketImpl::SetDelAckTimeout (Time timeout)
+{
+  m_delAckTimeout = timeout;
+}
+
+Time
+TcpSocketImpl::GetDelAckTimeout (void) const
+{
+  return m_delAckTimeout;
+}
+
+void
+TcpSocketImpl::SetDelAckMaxCount (uint32_t count)
+{
+  m_delAckMaxCount = count;
+}
+
+uint32_t
+TcpSocketImpl::GetDelAckMaxCount (void) const
+{
+  return m_delAckMaxCount;
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket-impl.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,215 @@
+/* -*-  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_IMPL_H
+#define TCP_SOCKET_IMPL_H
+
+#include <stdint.h>
+#include <queue>
+#include "ns3/callback.h"
+#include "ns3/traced-value.h"
+#include "ns3/tcp-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 TcpSocketImpl : public TcpSocket
+{
+public:
+  static TypeId GetTypeId (void);
+  /**
+   * Create an unbound tcp socket.
+   */
+  TcpSocketImpl ();
+  TcpSocketImpl (const TcpSocketImpl& sock);
+  virtual ~TcpSocketImpl ();
+
+  void SetNode (Ptr<Node> node);
+  void SetTcp (Ptr<TcpL4Protocol> tcp);
+  void SetRtt (Ptr<RttEstimator> rtt);
+
+  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(Ptr<Packet> p, const Address &address);
+  virtual uint32_t GetTxAvailable (void) const;
+  virtual int Listen(uint32_t queueLimit);
+
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+  virtual uint32_t GetRxAvailable (void) const;
+
+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);
+  void CompleteFork(Ptr<Packet>, const TcpHeader&, const Address& fromAddress);
+  void ConnectionSucceeded();
+  
+  //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
+  Ptr<TcpSocketImpl> Copy ();
+  void NewAck (SequenceNumber seq); 
+  // XXX This should be virtual and overridden
+  void DupAck (const TcpHeader& t, uint32_t count); 
+  void ReTxTimeout ();
+  void DelAckTimeout ();
+  void LastAckTimeout ();
+  void Retransmit ();
+  void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
+
+  // attribute related
+  virtual void SetSndBufSize (uint32_t size);
+  virtual uint32_t GetSndBufSize (void) const;
+  virtual void SetRcvBufSize (uint32_t size);
+  virtual uint32_t GetRcvBufSize (void) const;
+  virtual void SetSegSize (uint32_t size);
+  virtual uint32_t GetSegSize (void) const;
+  virtual void SetAdvWin (uint32_t window);
+  virtual uint32_t GetAdvWin (void) const;
+  virtual void SetSSThresh (uint32_t threshold);
+  virtual uint32_t GetSSThresh (void) const;
+  virtual void SetInitialCwnd (uint32_t cwnd);
+  virtual uint32_t GetInitialCwnd (void) const;
+  virtual void SetConnTimeout (Time timeout);
+  virtual Time GetConnTimeout (void) const;
+  virtual void SetConnCount (uint32_t count);
+  virtual uint32_t GetConnCount (void) const;
+  virtual void SetDelAckTimeout (Time timeout);
+  virtual Time GetDelAckTimeout (void) const;
+  virtual void SetDelAckMaxCount (uint32_t count);
+  virtual uint32_t GetDelAckMaxCount (void) const;
+
+  bool m_skipRetxResched;
+  uint32_t m_dupAckCount;
+  EventId m_retxEvent;
+  EventId m_lastAckEvent;
+
+  EventId m_delAckEvent;
+  uint32_t m_delAckCount;
+  uint32_t m_delAckMaxCount;
+  Time m_delAckTimeout;
+
+  Ipv4EndPoint *m_endPoint;
+  Ptr<Node> m_node;
+  Ptr<TcpL4Protocol> m_tcp;
+  Ipv4Address m_remoteAddress;
+  uint16_t m_remotePort;
+  //these two are so that the socket/endpoint cloning works
+  Ipv4Address m_localAddress;
+  uint16_t m_localPort;
+  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;
+
+  //history data
+  //this is the incoming data buffer which sorts out of sequence data
+  UnAckData_t m_bufferedData;
+  //this is kind of the tx buffer
+  PendingData* m_pendingData;
+  SequenceNumber m_firstPendingSequence;
+
+  // Window management
+  uint32_t                       m_segmentSize;          //SegmentSize
+  uint32_t                       m_rxWindowSize;
+  uint32_t                       m_advertisedWindowSize; //Window to advertise
+  TracedValue<uint32_t>          m_cWnd;                 //Congestion window
+  uint32_t                       m_ssThresh;             //Slow Start Threshold
+  uint32_t                       m_initialCWnd;          //Initial cWnd value
+
+  // Round trip time estimation
+  Ptr<RttEstimator> m_rtt;
+  Time m_lastMeasuredRtt;
+
+  // Timer-related members
+  Time              m_cnTimeout; 
+  uint32_t          m_cnCount;
+  
+  // Temporary queue for delivering data to application
+  std::queue<Ptr<Packet> > m_deliveryQueue;
+  uint32_t m_rxAvailable;
+  
+  bool m_wouldBlock;  // set to true whenever socket would block on send()
+
+  // Attributes
+  uint32_t m_rcvBufSize;   // maximum receive socket buffer size
+  uint32_t m_sndBufSize;   // buffer limit for the outgoing queue
+};
+
+}//namespace ns3
+
+#endif /* TCP_SOCKET_IMPL_H */
--- a/src/internet-node/tcp-socket.cc	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1251 +0,0 @@
-/* -*-  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/trace-source-accessor.h"
-
-#include <algorithm>
-
-NS_LOG_COMPONENT_DEFINE ("TcpSocket");
-
-using namespace std;
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (TcpSocket);
-
-TypeId
-TcpSocket::GetTypeId ()
-{
-  static TypeId tid = TypeId("ns3::TcpSocket")
-    .SetParent<Socket> ()
-    .AddTraceSource ("CongestionWindow",
-                     "The TCP connection's congestion window",
-                     MakeTraceSourceAccessor (&TcpSocket::m_cWnd))
-    ;
-  return tid;
-}
-
-  TcpSocket::TcpSocket ()
-  : m_skipRetxResched (false),
-    m_dupAckCount (0),
-    m_delAckCount (0),
-    m_endPoint (0),
-    m_node (0),
-    m_tcp (0),
-    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_pendingClose (false),
-    m_nextTxSequence (0),
-    m_highTxMark (0),
-    m_highestRxAck (0),
-    m_lastRxAck (0),
-    m_nextRxSequence (0),
-    m_pendingData (0),
-    m_rtt (0),
-    m_lastMeasuredRtt (Seconds(0.0))
-{
-  NS_LOG_FUNCTION (this);
-  
-}
-
-TcpSocket::TcpSocket(const TcpSocket& sock)
-  : Socket(sock), //copy the base class callbacks
-    m_skipRetxResched (sock.m_skipRetxResched),
-    m_dupAckCount (sock.m_dupAckCount),
-    m_delAckCount (0),
-    m_delAckMaxCount (sock.m_delAckMaxCount),
-    m_delAckTimout (sock.m_delAckTimout),
-    m_endPoint (0),
-    m_node (sock.m_node),
-    m_tcp (sock.m_tcp),
-    m_remoteAddress (sock.m_remoteAddress),
-    m_remotePort (sock.m_remotePort),
-    m_localAddress (sock.m_localAddress),
-    m_localPort (sock.m_localPort),
-    m_errno (sock.m_errno),
-    m_shutdownSend (sock.m_shutdownSend),
-    m_shutdownRecv (sock.m_shutdownRecv),
-    m_connected (sock.m_connected),
-    m_state (sock.m_state),
-    m_closeNotified (sock.m_closeNotified),
-    m_closeRequestNotified (sock.m_closeRequestNotified),
-    m_closeOnEmpty (sock.m_closeOnEmpty),
-    m_pendingClose (sock.m_pendingClose),
-    m_nextTxSequence (sock.m_nextTxSequence),
-    m_highTxMark (sock.m_highTxMark),
-    m_highestRxAck (sock.m_highestRxAck),
-    m_lastRxAck (sock.m_lastRxAck),
-    m_nextRxSequence (sock.m_nextRxSequence),
-    m_pendingData (0),
-    m_segmentSize (sock.m_segmentSize),
-    m_rxWindowSize (sock.m_rxWindowSize),
-    m_advertisedWindowSize (sock.m_advertisedWindowSize),
-    m_cWnd (sock.m_cWnd),
-    m_ssThresh (sock.m_ssThresh),
-    m_initialCWnd (sock.m_initialCWnd),
-    m_rtt (0),
-    m_lastMeasuredRtt (Seconds(0.0)),
-    m_cnTimeout (sock.m_cnTimeout),
-    m_cnCount (sock.m_cnCount)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  NS_LOG_LOGIC("Invoked the copy constructor");
-  //copy the pending data if necessary
-  if(sock.m_pendingData)
-    {
-      m_pendingData = sock.m_pendingData->Copy();
-    }
-  //copy the rtt if necessary
-  if (sock.m_rtt)
-    {
-      m_rtt = sock.m_rtt->Copy();
-    }
-  //can't "copy" the endpoint just yes, must do this when we know the peer info
-  //too; this is in SYN_ACK_TX
-}
-
-TcpSocket::~TcpSocket ()
-{
-  NS_LOG_FUNCTION(this);
-  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
-  m_pendingData = 0;
-}
-
-void
-TcpSocket::SetNode (Ptr<Node> node)
-{
-  m_node = node;
-  Ptr<Tcp> t = node->GetObject<Tcp> ();
-  m_segmentSize = t->GetDefaultSegSize ();
-  m_rxWindowSize = t->GetDefaultAdvWin ();
-  m_advertisedWindowSize = t->GetDefaultAdvWin ();
-  m_cWnd = t->GetDefaultInitialCwnd () * m_segmentSize;
-  m_ssThresh = t->GetDefaultSsThresh ();
-  m_initialCWnd = t->GetDefaultInitialCwnd ();
-  m_cnTimeout = Seconds (t->GetDefaultConnTimeout ());
-  m_cnCount = t->GetDefaultConnCount ();
-  m_delAckTimout = Seconds(t->GetDefaultDelAckTimeout ());
-  m_delAckMaxCount = t->GetDefaultDelAckCount ();
-}
-
-void 
-TcpSocket::SetTcp (Ptr<TcpL4Protocol> tcp)
-{
-  m_tcp = tcp;
-}
-void 
-TcpSocket::SetRtt (Ptr<RttEstimator> rtt)
-{
-  m_rtt = rtt;
-}
-
-
-enum Socket::SocketErrno
-TcpSocket::GetErrno (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_errno;
-}
-
-Ptr<Node>
-TcpSocket::GetNode (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_node;
-}
-
-void 
-TcpSocket::Destroy (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_node = 0;
-  m_endPoint = 0;
-  m_tcp = 0;
-  m_retxEvent.Cancel ();
-}
-int
-TcpSocket::FinishBind (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  if (m_endPoint == 0)
-    {
-      return -1;
-    }
-  m_endPoint->SetRxCallback (MakeCallback (&TcpSocket::ForwardUp, Ptr<TcpSocket>(this)));
-  m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, Ptr<TcpSocket>(this)));
-  m_localAddress = m_endPoint->GetLocalAddress ();
-  m_localPort = m_endPoint->GetLocalPort ();
-  return 0;
-}
-
-int
-TcpSocket::Bind (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_endPoint = m_tcp->Allocate ();
-  return FinishBind ();
-}
-int 
-TcpSocket::Bind (const Address &address)
-{
-  NS_LOG_FUNCTION (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_NOARGS ();
-  m_shutdownSend = true;
-  return 0;
-}
-int 
-TcpSocket::ShutdownRecv (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_shutdownRecv = false;
-  return 0;
-}
-
-int
-TcpSocket::Close (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  if (m_state == CLOSED) 
-    {
-      return -1;
-    }
-  if (m_pendingData && m_pendingData->Size() != 0)
-    { // App close with pending data must wait until all data transmitted
-      m_closeOnEmpty = true;
-      NS_LOG_LOGIC("Socket " << this << 
-                   " deferring close, state " << m_state);
-      return 0;
-    }
-
-  Actions_t action  = ProcessEvent (APP_CLOSE);
-  ProcessAction (action);
-  ShutdownSend ();
-  return 0;
-}
-
-int
-TcpSocket::Connect (const Address & address)
-{
-  NS_LOG_FUNCTION (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_remoteAddress = transport.GetIpv4 ();
-  m_remotePort = transport.GetPort ();
-  
-  uint32_t localIfIndex;
-  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-
-  if (ipv4->GetIfIndexForDestination (m_remoteAddress, 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
-{ // TCP Does not deal with packets from app, just data
-  return Send(p->PeekData(), p->GetSize());
-}
-
-int TcpSocket::Send (const uint8_t* buf, uint32_t size)
-{
-  NS_LOG_FUNCTION (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);
-      NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() << 
-                   " state " << m_state);
-      Actions_t action = ProcessEvent (APP_SEND);
-      NS_LOG_DEBUG(" action " << action);
-      // We do not model any limit to the buffer, so report that the
-      // maximum is available
-      NotifySend (std::numeric_limits<uint32_t>::max ());
-      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 (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 (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 (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 (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_DEBUG("Socket " << this << " got forward up" <<
-               " dport " << m_endPoint->GetLocalPort() <<
-               " daddr " << m_endPoint->GetLocalAddress() <<
-               " sport " << m_endPoint->GetPeerPort() <<
-               " saddr " << m_endPoint->GetPeerAddress());
-
-  NS_LOG_FUNCTION (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);
-  NS_LOG_DEBUG("Socket " << this << 
-               " processing pkt action, " << action <<
-               " current state " << m_state);
-  ProcessPacketAction (action, packet, tcpHeader, address);
-}
-
-Actions_t TcpSocket::ProcessEvent (Events_t e)
-{
-  NS_LOG_FUNCTION (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);
-
-  //extra event logic is here for RX events
-  //e = SYN_ACK_RX
-  if (saveState == SYN_SENT && m_state == ESTABLISHED)
-    // this means the application side has completed its portion of 
-    // the handshaking
-    {
-      Simulator::ScheduleNow(&TcpSocket::ConnectionSucceeded, this);
-      //NotifyConnectionSucceeded ();
-      m_connected = true;
-      m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
-      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 (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_remotePort);
-  header.SetWindowSize (m_advertisedWindowSize);
-  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), 
-    m_remoteAddress);
-  Time rto = m_rtt->RetransmitTimeout ();
-  if (flags & TcpHeader::SYN)
-    {
-      rto = m_cnTimeout;
-      m_cnTimeout = m_cnTimeout + 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 (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
-      // is the above correct? we're SENDING a syn, not acking back -- Raj
-      // commented out for now
-      // m_nextTxSequence+= 1;
-      SendEmptyPacket (TcpHeader::SYN);
-      break;
-    case SYN_ACK_TX:
-      NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
-      // TCP SYN Flag consumes one byte
-      ++m_nextRxSequence;
-      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_ASSERT (false); // This should be processed in ProcessPacketAction
-      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 (this << a << p  << fromAddress);
-  uint32_t localIfIndex;
-  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-  switch (a)
-  {
-    case SYN_ACK_TX:
-      NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
-//      m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
-//      m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
-//       if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
-//         {
-//           m_localAddress = ipv4->GetAddress (localIfIndex);
-//         }
-      if (m_state == LISTEN) //this means we should fork a new TcpSocket
-        {
-          NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this);
-          //notify the server that we got a SYN
-          // If server refuses connection do nothing
-          if (!NotifyConnectionRequest(fromAddress)) return true;
-          // Clone the socket
-          Ptr<TcpSocket> newSock = Copy ();
-          NS_LOG_LOGIC ("Cloned a TcpSocket " << newSock);
-          //this listening socket should do nothing more
-          Simulator::ScheduleNow (&TcpSocket::CompleteFork, newSock,
-                                  p, tcpHeader,fromAddress);
-          return true;
-        }
-        // This is the cloned endpoint
-        m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
-        if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
-          {
-            m_localAddress = ipv4->GetAddress (localIfIndex);
-            m_endPoint->SetLocalAddress (m_localAddress);
-            // Leave local addr in the portmap to any, as the path from
-            // remote can change and packets can arrive on different interfaces
-            //m_endPoint->SetLocalAddress (Ipv4Address::GetAny());
-          }
-        // TCP SYN consumes one byte
-        m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
-        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 = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
-      m_nextTxSequence = tcpHeader.GetAckNumber ();
-      m_firstPendingSequence = m_nextTxSequence;  //bug 166
-      NS_LOG_DEBUG ("TcpSocket " << this << " ACK_TX_1" <<
-                    " nextRxSeq " << m_nextRxSequence);
-      SendEmptyPacket (TcpHeader::ACK);
-      m_rxWindowSize = tcpHeader.GetWindowSize ();
-      if (tcpHeader.GetAckNumber () > m_highestRxAck)
-      {
-        m_highestRxAck = tcpHeader.GetAckNumber ();
-        // We do not model any limit to the buffer, so report that the
-        // maximum is available
-        NotifySend (std::numeric_limits<uint32_t>::max ());
-      }
-      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_RX");
-      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;
-    }
-    case SERV_NOTIFY:
-      NS_LOG_LOGIC ("TcpSocket " << this <<" Action SERV_NOTIFY");
-      NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
-      NotifyNewConnectionCreated (this, fromAddress);
-      m_connected = true; // ! This is bogus; fix when we clone the tcp
-      m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
-      //treat the connection orientation final ack as a newack
-      CommonNewAck (tcpHeader.GetAckNumber (), true);
-      break;
-    default:
-      break;
-  }
-  return true;
-}
-
-void TcpSocket::CompleteFork(Ptr<Packet> p, const TcpHeader& h, const Address& fromAddress)
-{
-  // Get port and address from peer (connecting host)
-  m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
-  m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
-  m_endPoint = m_tcp->Allocate (m_localAddress,
-                                m_localPort,
-                                m_remoteAddress,
-                                m_remotePort);
-  //the cloned socket with be in listen state, so manually change state
-  m_state = SYN_RCVD;
-  //equivalent to FinishBind
-  m_endPoint->SetRxCallback (MakeCallback (&TcpSocket::ForwardUp, Ptr<TcpSocket>(this)));
-  m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, Ptr<TcpSocket>(this)));
-  ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress);
- }
-
-void TcpSocket::ConnectionSucceeded()
-{ // We would preferred to have scheduled an event directly to
-  // NotifyConnectionSucceeded, but (sigh) these are protected
-  // and we can get the address of it :(
-  NotifyConnectionSucceeded();
-}
-
-bool TcpSocket::SendPendingData (bool withAck)
-{
-  NS_LOG_FUNCTION (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
-      Ptr<Packet> p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence, 
-        m_nextTxSequence);
-      NS_LOG_LOGIC("TcpSocket " << this << " sendPendingData"
-                   << " txseq " << m_nextTxSequence
-                   << " s " << s 
-                   << " datasize " << p->GetSize() );
-      uint8_t flags = 0;
-      if (withAck)
-        {
-          flags |= TcpHeader::ACK;
-        }
-      uint32_t sz = p->GetSize (); // 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;
-        }
-
-      TcpHeader header;
-      header.SetFlags (flags);
-      header.SetSequenceNumber (m_nextTxSequence);
-      header.SetAckNumber (m_nextRxSequence);
-      header.SetSourcePort (m_endPoint->GetLocalPort());
-      header.SetDestinationPort (m_remotePort);
-      if (m_shutdownSend)
-        {
-          m_errno = ERROR_SHUTDOWN;
-          return -1;
-        }
-
-      
-      if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
-        {
-            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);
-        }
-      NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
-      m_tcp->SendPacket (p, header,
-                         m_endPoint->GetLocalAddress (),
-                         m_remoteAddress);
-      m_rtt->SentSeq(m_nextTxSequence, sz);       // notify the RTT
-      // Notify the application
-      Simulator::ScheduleNow(&TcpSocket::NotifyDataSent, this, p->GetSize ());
-      nPacketsSent++;                             // Count sent this loop
-      m_nextTxSequence += sz;                     // Advance next tx sequence
-      // Note the high water mark
-      m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
-    }
-  NS_LOG_LOGIC ("Sent "<<nPacketsSent<<" packets");
-  NS_LOG_LOGIC("RETURN SendPendingData");
-  return (nPacketsSent>0);
-}
-
-uint32_t  TcpSocket::UnAckDataCount ()
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_nextTxSequence - m_highestRxAck;
-}
-
-uint32_t  TcpSocket::BytesInFlight ()
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_highTxMark - m_highestRxAck;
-}
-
-uint32_t  TcpSocket::Window ()
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  NS_LOG_LOGIC ("TcpSocket::Window() "<<this);
-  return std::min (m_rxWindowSize, m_cWnd.Get());
-}
-
-uint32_t  TcpSocket::AvailableWindow ()
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  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 (this << p << "tcpHeader " << fromAddress);
-  NS_LOG_LOGIC ("TcpSocket " << this << " NewRx,"
-                << " seq " << tcpHeader.GetSequenceNumber()
-                << " ack " << tcpHeader.GetAckNumber()
-                << " p.size is " << p->GetSize () );
-  NS_LOG_DEBUG ("TcpSocket " << this <<
-                " NewRx," <<
-                " seq " << tcpHeader.GetSequenceNumber() <<
-                " ack " << tcpHeader.GetAckNumber() <<
-                " 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
-  if(++m_delAckCount >= m_delAckMaxCount)
-  {
-    m_delAckEvent.Cancel();
-    m_delAckCount = 0;
-    SendEmptyPacket (TcpHeader::ACK);
-  }
-  else
-  {
-    m_delAckEvent = Simulator::Schedule (m_delAckTimout, &TcpSocket::DelAckTimeout, this);
-  }
-}
-
-void TcpSocket::DelAckTimeout ()
-{
-  m_delAckCount = 0;
-  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 (this << ack << skipTimer); 
-  //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
-  if (!skipTimer)
-    {
-      m_retxEvent.Cancel ();  
-      //On recieving a "New" ack we restart retransmission timer .. RFC 2988
-      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);
-    }
-  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack 
-           << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed
-  m_highestRxAck = ack;         // Note the highest recieved Ack
-  // We do not model any limit to the buffer, so report that the
-  // maximum is available
-  NotifySend (std::numeric_limits<uint32_t>::max ());
-  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();
-}
-
-Ptr<TcpSocket> TcpSocket::Copy ()
-{
-  return CopyObject<TcpSocket> (this);
-}
-
-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 (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.Get();
-      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 (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 (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 (); // DoubleValue 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 (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;
-    }
-  Ptr<Packet> p = 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(p->GetSize ()));
-  if (m_closeOnEmpty && remainingData == 0)
-    { // Add the FIN flag
-      flags = flags | TcpHeader::FIN;
-    }
-
-  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,p->GetSize ());
-  // And send the packet
-  TcpHeader tcpHeader;
-  tcpHeader.SetSequenceNumber (m_nextTxSequence);
-  tcpHeader.SetAckNumber (m_nextRxSequence);
-  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
-  tcpHeader.SetDestinationPort (m_remotePort);
-  tcpHeader.SetFlags (flags);
-  tcpHeader.SetWindowSize (m_advertisedWindowSize);
-
-  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
-    m_remoteAddress);
-}
-
-}//namespace ns3
--- a/src/internet-node/tcp-socket.h	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/* -*-  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/traced-value.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:
-  static TypeId GetTypeId (void);
-  /**
-   * Create an unbound tcp socket.
-   */
-  TcpSocket ();
-  TcpSocket (const TcpSocket& sock);
-  virtual ~TcpSocket ();
-
-  void SetNode (Ptr<Node> node);
-  void SetTcp (Ptr<TcpL4Protocol> tcp);
-  void SetRtt (Ptr<RttEstimator> rtt);
-
-  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);
-  void CompleteFork(Ptr<Packet>, const TcpHeader&, const Address& fromAddress);
-  void ConnectionSucceeded();
-  
-  //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
-  Ptr<TcpSocket> Copy ();
-  void NewAck (SequenceNumber seq); 
-  // XXX This should be virtual and overridden
-  void DupAck (const TcpHeader& t, uint32_t count); 
-  void ReTxTimeout ();
-  void DelAckTimeout ();
-  void LastAckTimeout ();
-  void Retransmit ();
-  void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
-
-  bool m_skipRetxResched;
-  uint32_t m_dupAckCount;
-  EventId m_retxEvent;
-  EventId m_lastAckEvent;
-
-  EventId m_delAckEvent;
-  uint32_t m_delAckCount;
-  uint32_t m_delAckMaxCount;
-  Time m_delAckTimout;
-
-  Ipv4EndPoint *m_endPoint;
-  Ptr<Node> m_node;
-  Ptr<TcpL4Protocol> m_tcp;
-  Ipv4Address m_remoteAddress;
-  uint16_t m_remotePort;
-  //these two are so that the socket/endpoint cloning works
-  Ipv4Address m_localAddress;
-  uint16_t m_localPort;
-  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;
-
-  //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
-  TracedValue<uint32_t>          m_cWnd;                 //Congestion window
-  uint32_t                       m_ssThresh;             //Slow Start Threshold
-  uint32_t                       m_initialCWnd;          //Initial cWnd value
-
-  // 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 */
--- a/src/internet-node/udp-impl.cc	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "udp-impl.h"
-#include "udp-l4-protocol.h"
-#include "ns3/socket.h"
-#include "ns3/assert.h"
-
-namespace ns3 {
-
-UdpImpl::UdpImpl ()
-  : m_udp (0)
-{}
-UdpImpl::~UdpImpl ()
-{
-  NS_ASSERT (m_udp == 0);
-}
-
-void 
-UdpImpl::SetUdp (Ptr<UdpL4Protocol> udp)
-{
-  m_udp = udp;
-}
-
-Ptr<Socket>
-UdpImpl::CreateSocket (void)
-{
-  return m_udp->CreateSocket ();
-}
-
-void 
-UdpImpl::DoDispose (void)
-{
-  m_udp = 0;
-  Udp::DoDispose ();
-}
-
-} // namespace ns3
--- a/src/internet-node/udp-impl.h	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef UDP_IMPL_H
-#define UDP_IMPL_H
-
-#include "ns3/udp.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class UdpL4Protocol;
-
-/**
- * \brief Object to create UDP socket instances 
- * \internal
- *
- * This class implements the API for UDP sockets.
- * It is a socket factory (deriving from class SocketFactory) and can
- * also hold global variables used to initialize newly created sockets, 
- * such as values that are set through the sysctl or proc interfaces in Linux.
- */
-class UdpImpl : public Udp
-{
-public:
-  UdpImpl ();
-  virtual ~UdpImpl ();
-
-  void SetUdp (Ptr<UdpL4Protocol> udp);
-
-  /**
-   * \brief Implements a method to create a UdpImpl-based socket and return
-   * a base class smart pointer to the socket.
-   * \internal
-   *
-   * \return smart pointer to Socket
-   */
-  virtual Ptr<Socket> CreateSocket (void);
-
-protected:
-  virtual void DoDispose (void);
-private:
-  Ptr<UdpL4Protocol> m_udp;
-};
-
-} // namespace ns3
-
-#endif /* UDP_IMPL_H */
--- a/src/internet-node/udp-l4-protocol.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/udp-l4-protocol.cc	Tue May 27 15:01:11 2008 -0700
@@ -28,7 +28,7 @@
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
-#include "udp-socket.h"
+#include "udp-socket-impl.h"
 
 NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
 
@@ -95,7 +95,7 @@
 UdpL4Protocol::CreateSocket (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  Ptr<UdpSocket> socket = CreateObject<UdpSocket> ();
+  Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl> ();
   socket->SetNode (m_node);
   socket->SetUdp (this);
   return socket;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/udp-socket-factory-impl.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,54 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "udp-socket-factory-impl.h"
+#include "udp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+UdpSocketFactoryImpl::UdpSocketFactoryImpl ()
+  : m_udp (0)
+{}
+UdpSocketFactoryImpl::~UdpSocketFactoryImpl ()
+{
+  NS_ASSERT (m_udp == 0);
+}
+
+void 
+UdpSocketFactoryImpl::SetUdp (Ptr<UdpL4Protocol> udp)
+{
+  m_udp = udp;
+}
+
+Ptr<Socket>
+UdpSocketFactoryImpl::CreateSocket (void)
+{
+  return m_udp->CreateSocket ();
+}
+
+void 
+UdpSocketFactoryImpl::DoDispose (void)
+{
+  m_udp = 0;
+  UdpSocketFactory::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/udp-socket-factory-impl.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef UDP_SOCKET_FACTORY_IMPL_H
+#define UDP_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/udp-socket-factory.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class UdpL4Protocol;
+
+/**
+ * \brief Object to create UDP socket instances 
+ * \internal
+ *
+ * This class implements the API for creating UDP sockets.
+ * It is a socket factory (deriving from class SocketFactory).
+ */
+class UdpSocketFactoryImpl : public UdpSocketFactory
+{
+public:
+  UdpSocketFactoryImpl ();
+  virtual ~UdpSocketFactoryImpl ();
+
+  void SetUdp (Ptr<UdpL4Protocol> udp);
+
+  /**
+   * \brief Implements a method to create a Udp-based socket and return
+   * a base class smart pointer to the socket.
+   * \internal
+   *
+   * \return smart pointer to Socket
+   */
+  virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+  virtual void DoDispose (void);
+private:
+  Ptr<UdpL4Protocol> m_udp;
+};
+
+} // namespace ns3
+
+#endif /* UDP_SOCKET_FACTORY_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/udp-socket-impl.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,687 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/ipv4.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/uinteger.h"
+#include "ns3/boolean.h"
+#include "udp-socket-impl.h"
+#include "udp-l4-protocol.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l4-demux.h"
+
+NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
+
+namespace ns3 {
+
+static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
+
+// Add attributes generic to all UdpSockets to base class UdpSocket
+TypeId
+UdpSocketImpl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UdpSocketImpl")
+    .SetParent<UdpSocket> ()
+    .AddConstructor<UdpSocketImpl> ()
+    .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
+                     MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace))
+    ;
+  return tid;
+}
+
+UdpSocketImpl::UdpSocketImpl ()
+  : m_endPoint (0),
+    m_node (0),
+    m_udp (0),
+    m_errno (ERROR_NOTERROR),
+    m_shutdownSend (false),
+    m_shutdownRecv (false),
+    m_connected (false),
+    m_rxAvailable (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+UdpSocketImpl::~UdpSocketImpl ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  m_node = 0;
+  if (m_endPoint != 0)
+    {
+      NS_ASSERT (m_udp != 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_udp->DeAllocate (m_endPoint);
+      NS_ASSERT (m_endPoint == 0);
+    }
+  m_udp = 0;
+}
+
+void 
+UdpSocketImpl::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = node;
+
+}
+void 
+UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_udp = udp;
+}
+
+
+enum Socket::SocketErrno
+UdpSocketImpl::GetErrno (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_errno;
+}
+
+Ptr<Node>
+UdpSocketImpl::GetNode (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node;
+}
+
+void 
+UdpSocketImpl::Destroy (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  m_endPoint = 0;
+  m_udp = 0;
+}
+
+int
+UdpSocketImpl::FinishBind (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_endPoint == 0)
+    {
+      return -1;
+    }
+  m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, this));
+  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, this));
+  return 0;
+}
+
+int
+UdpSocketImpl::Bind (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_endPoint = m_udp->Allocate ();
+  return FinishBind ();
+}
+
+int 
+UdpSocketImpl::Bind (const Address &address)
+{
+  NS_LOG_FUNCTION (this << address);
+
+  if (!InetSocketAddress::IsMatchingType (address))
+    {
+      NS_LOG_ERROR ("Not IsMatchingType");
+      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_udp->Allocate ();
+    }
+  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_udp->Allocate (port);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+    {
+      m_endPoint = m_udp->Allocate (ipv4);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_udp->Allocate (ipv4, port);
+    }
+
+  return FinishBind ();
+}
+
+int 
+UdpSocketImpl::ShutdownSend (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownSend = true;
+  return 0;
+}
+
+int 
+UdpSocketImpl::ShutdownRecv (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownRecv = false;
+  return 0;
+}
+
+int
+UdpSocketImpl::Close(void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NotifyCloseCompleted ();
+  return 0;
+}
+
+int
+UdpSocketImpl::Connect(const Address & address)
+{
+  NS_LOG_FUNCTION (this << address);
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  m_defaultAddress = transport.GetIpv4 ();
+  m_defaultPort = transport.GetPort ();
+  NotifyConnectionSucceeded ();
+  m_connected = true;
+
+  return 0;
+}
+
+int 
+UdpSocketImpl::Send (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << p);
+
+  if (!m_connected)
+    {
+      m_errno = ERROR_NOTCONN;
+      return -1;
+    }
+  return DoSend (p);
+}
+
+int 
+UdpSocketImpl::DoSend (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  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;
+    } 
+  
+  return DoSendTo (p, m_defaultAddress, m_defaultPort);
+}
+
+int
+UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
+{
+  NS_LOG_FUNCTION (this << p << address);
+
+  if (!m_connected)
+    {
+      NS_LOG_LOGIC ("Not connected");
+      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+      Ipv4Address ipv4 = transport.GetIpv4 ();
+      uint16_t port = transport.GetPort ();
+      return DoSendTo (p, ipv4, port);
+    }
+  else
+    {
+      // connected UDP socket must use default addresses
+      NS_LOG_LOGIC ("Connected");
+      return DoSendTo (p, m_defaultAddress, m_defaultPort);
+    }
+}
+
+int
+UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << p << dest << 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;
+    }
+
+  if (p->GetSize () > GetTxAvailable () )
+    {
+      m_errno = ERROR_MSGSIZE;
+      return -1;
+    }
+
+  uint32_t localIfIndex;
+  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+  // Locally override the IP TTL for this socket
+  // We cannot directly modify the TTL at this stage, so we set a Packet tag
+  // The destination can be either multicast, unicast/anycast, or
+  // either all-hosts broadcast or limited (subnet-directed) broadcast.
+  // For the latter two broadcast types, the TTL will later be set to one
+  // irrespective of what is set in these socket options.  So, this tagging  
+  // may end up setting the TTL of a limited broadcast packet to be
+  // the same as a unicast, but it will be fixed further down the stack
+  //NS_LOG_UNCOND ("IPttl: " << m_ipTtl);
+  if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
+    {
+      SocketIpTtlTag tag;
+      tag.SetTtl (m_ipMulticastTtl);
+      p->AddTag (tag);
+    }
+  else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
+    {
+      SocketIpTtlTag tag;
+      tag.SetTtl (m_ipTtl);
+      p->AddTag (tag);
+    }
+  //
+  // If dest is sent to the limited broadcast address (all ones),
+  // convert it to send a copy of the packet out of every interface
+  //
+  if (dest.IsBroadcast ())
+    {
+      NS_LOG_LOGIC ("Limited broadcast start.");
+      for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
+        {
+          Ipv4Address addri = ipv4->GetAddress (i);
+          Ipv4Mask maski = ipv4->GetNetworkMask (i);
+          Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
+          NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
+                        << " (mask is " << maski << ")");
+          m_udp->Send (p->Copy (), addri, bcast,
+                       m_endPoint->GetLocalPort (), port);
+          NotifyDataSent (p->GetSize ());
+        }
+      NS_LOG_LOGIC ("Limited broadcast end.");
+      return p->GetSize();
+    }
+  else if (ipv4->GetIfIndexForDestination(dest, localIfIndex))
+    {
+      NS_LOG_LOGIC ("Route exists");
+      m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest,
+		   m_endPoint->GetLocalPort (), port);
+      NotifyDataSent (p->GetSize ());
+      return p->GetSize();;
+    }
+  else
+   {
+      NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
+      m_errno = ERROR_NOROUTETOHOST;
+      return -1;
+   }
+
+  return 0;
+}
+
+// XXX maximum message size for UDP broadcast is limited by MTU
+// size of underlying link; we are not checking that now.
+uint32_t
+UdpSocketImpl::GetTxAvailable (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  // No finite send buffer is modelled, but we must respect
+  // the maximum size of an IP datagram (65535 bytes - headers).
+  return MAX_IPV4_UDP_DATAGRAM_SIZE;
+}
+
+int 
+UdpSocketImpl::SendTo (Ptr<Packet> p, const Address &address)
+{
+  NS_LOG_FUNCTION (this << address << p);
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  Ipv4Address ipv4 = transport.GetIpv4 ();
+  uint16_t port = transport.GetPort ();
+  return DoSendTo (p, ipv4, port);
+}
+
+Ptr<Packet>
+UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_deliveryQueue.empty() )
+    {
+      return 0;
+    }
+  Ptr<Packet> p = m_deliveryQueue.front ();
+  if (p->GetSize () <= maxSize) 
+    {
+      m_deliveryQueue.pop ();
+      m_rxAvailable -= p->GetSize ();
+    }
+  else
+    {
+      p = 0; 
+    }
+  return p;
+}
+
+uint32_t
+UdpSocketImpl::GetRxAvailable (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  // We separately maintain this state to avoid walking the queue 
+  // every time this might be called
+  return m_rxAvailable;
+}
+
+void 
+UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << packet << ipv4 << port);
+
+  if (m_shutdownRecv)
+    {
+      return;
+    }
+  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
+    {
+      Address address = InetSocketAddress (ipv4, port);
+      SocketRxAddressTag tag;
+      tag.SetAddress (address);
+      packet->AddTag (tag);
+      m_deliveryQueue.push (packet);
+      m_rxAvailable += packet->GetSize ();
+      NotifyDataRecv ();
+    }
+  else
+    {
+      // In general, this case should not occur unless the
+      // receiving application reads data from this socket slowly
+      // in comparison to the arrival rate
+      //
+      // drop and trace packet
+      NS_LOG_WARN ("No receive buffer space available.  Drop.");
+      m_dropTrace (packet);
+    }
+}
+
+
+void 
+UdpSocketImpl::SetRcvBufSize (uint32_t size)
+{
+  m_rcvBufSize = size;
+}
+
+uint32_t 
+UdpSocketImpl::GetRcvBufSize (void) const
+{
+  return m_rcvBufSize;
+}
+
+void 
+UdpSocketImpl::SetIpTtl (uint32_t ipTtl)
+{
+  m_ipTtl = ipTtl;
+}
+
+uint32_t 
+UdpSocketImpl::GetIpTtl (void) const
+{
+  return m_ipTtl;
+}
+
+void 
+UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl)
+{
+  m_ipMulticastTtl = ipTtl;
+}
+
+uint32_t 
+UdpSocketImpl::GetIpMulticastTtl (void) const
+{
+  return m_ipMulticastTtl;
+}
+
+} //namespace ns3
+
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "internet-stack.h"
+#include <string>
+
+namespace ns3 {
+
+class UdpSocketImplTest: public Test
+{
+  Ptr<Packet> m_receivedPacket;
+  Ptr<Packet> m_receivedPacket2;
+
+public:
+  virtual bool RunTests (void);
+  UdpSocketImplTest ();
+
+  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePkt (Ptr<Socket> socket);
+  void ReceivePkt2 (Ptr<Socket> socket);
+};
+
+
+UdpSocketImplTest::UdpSocketImplTest ()
+  : Test ("UdpSocketImpl") 
+{
+}
+
+void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket = packet;
+}
+
+void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket2 = packet;
+}
+
+void UdpSocketImplTest::ReceivePkt (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+}
+
+void UdpSocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+  NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
+}
+
+bool
+UdpSocketImplTest::RunTests (void)
+{
+  bool result = true;
+
+  // Create topology
+  
+  // Receiver Node
+  Ptr<Node> rxNode = CreateObject<Node> ();
+  AddInternetStack (rxNode);
+  Ptr<SimpleNetDevice> rxDev1, rxDev2;
+  { // first interface
+    rxDev1 = CreateObject<SimpleNetDevice> ();
+    rxDev1->SetAddress (Mac48Address::Allocate ());
+    rxNode->AddDevice (rxDev1);
+    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
+    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1"));
+    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+    ipv4->SetUp (netdev_idx);
+  }
+
+  { // second interface
+    rxDev2 = CreateObject<SimpleNetDevice> ();
+    rxDev2->SetAddress (Mac48Address::Allocate ());
+    rxNode->AddDevice (rxDev2);
+    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
+    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1"));
+    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+    ipv4->SetUp (netdev_idx);
+  }
+  
+  // Sender Node
+  Ptr<Node> txNode = CreateObject<Node> ();
+  AddInternetStack (txNode);
+  Ptr<SimpleNetDevice> txDev1;
+  {
+    txDev1 = CreateObject<SimpleNetDevice> ();
+    txDev1->SetAddress (Mac48Address::Allocate ());
+    txNode->AddDevice (txDev1);
+    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (txDev1);
+    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2"));
+    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+    ipv4->SetUp (netdev_idx);
+  }
+  Ptr<SimpleNetDevice> txDev2;
+  {
+    txDev2 = CreateObject<SimpleNetDevice> ();
+    txDev2->SetAddress (Mac48Address::Allocate ());
+    txNode->AddDevice (txDev2);
+    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (txDev2);
+    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2"));
+    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+    ipv4->SetUp (netdev_idx);
+  }
+
+  // link the two nodes
+  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
+  rxDev1->SetChannel (channel1);
+  txDev1->SetChannel (channel1);
+
+  Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
+  rxDev2->SetChannel (channel2);
+  txDev2->SetChannel (channel2);
+
+
+  // Create the UDP sockets
+  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
+  NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
+  rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this));
+
+  Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
+  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
+  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
+
+  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
+
+  // ------ Now the tests ------------
+
+  // Unicast test
+  m_receivedPacket = Create<Packet> ();
+  m_receivedPacket2 = Create<Packet> ();
+  NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 
+    InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123);
+  Simulator::Run ();
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
+
+  m_receivedPacket->RemoveAllTags ();
+  m_receivedPacket2->RemoveAllTags ();
+
+  // Simple broadcast test
+
+  m_receivedPacket = Create<Packet> ();
+  m_receivedPacket2 = Create<Packet> ();
+  NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 
+    InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+  Simulator::Run ();
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+  // second socket should not receive it (it is bound specifically to the second interface's address
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
+
+  m_receivedPacket->RemoveAllTags ();
+  m_receivedPacket2->RemoveAllTags ();
+
+  // Broadcast test with multiple receiving sockets
+
+  // When receiving broadcast packets, all sockets sockets bound to
+  // the address/port should receive a copy of the same packet -- if
+  // the socket address matches.
+  rxSocket2->Dispose ();
+  rxSocket2 = rxSocketFactory->CreateSocket ();
+  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
+  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
+
+  m_receivedPacket = Create<Packet> ();
+  m_receivedPacket2 = Create<Packet> ();
+  NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123),
+InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+  Simulator::Run ();
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
+
+  m_receivedPacket->RemoveAllTags ();
+  m_receivedPacket2->RemoveAllTags ();
+
+  Simulator::Destroy ();
+
+  return result;
+}
+
+static UdpSocketImplTest gUdpSocketImplTest;
+
+}; // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/udp-socket-impl.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,111 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef UDP_SOCKET_IMPL_H
+#define UDP_SOCKET_IMPL_H
+
+#include <stdint.h>
+#include <queue>
+#include "ns3/callback.h"
+#include "ns3/traced-callback.h"
+#include "ns3/socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/udp-socket.h"
+
+namespace ns3 {
+
+class Ipv4EndPoint;
+class Node;
+class Packet;
+class UdpL4Protocol;
+
+class UdpSocketImpl : public UdpSocket
+{
+public:
+  static TypeId GetTypeId (void);
+  /**
+   * Create an unbound udp socket.
+   */
+  UdpSocketImpl ();
+  virtual ~UdpSocketImpl ();
+
+  void SetNode (Ptr<Node> node);
+  void SetUdp (Ptr<UdpL4Protocol> udp);
+
+  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 SendTo (Ptr<Packet> p, const Address &address);
+  virtual uint32_t GetTxAvailable (void) const;
+
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+  virtual uint32_t GetRxAvailable (void) const;
+
+private:
+  // Attributes set through UdpSocket base class 
+  virtual void SetRcvBufSize (uint32_t size);
+  virtual uint32_t GetRcvBufSize (void) const;
+  virtual void SetIpTtl (uint32_t ipTtl);
+  virtual uint32_t GetIpTtl (void) const;
+  virtual void SetIpMulticastTtl (uint32_t ipTtl);
+  virtual uint32_t GetIpMulticastTtl (void) const;
+
+  friend class UdpSocketFactory;
+  // invoked by Udp class
+  int FinishBind (void);
+  void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
+  void Destroy (void);
+  int DoSend (Ptr<Packet> p);
+  int DoSendTo (Ptr<Packet> p, const Address &daddr);
+  int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
+
+  Ipv4EndPoint *m_endPoint;
+  Ptr<Node> m_node;
+  Ptr<UdpL4Protocol> m_udp;
+  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;
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
+
+  enum SocketErrno m_errno;
+  bool m_shutdownSend;
+  bool m_shutdownRecv;
+  bool m_connected;
+
+  std::queue<Ptr<Packet> > m_deliveryQueue;
+  uint32_t m_rxAvailable;
+  
+  // Socket attributes
+  uint32_t m_rcvBufSize;
+  uint32_t m_ipTtl;
+  uint32_t m_ipMulticastTtl;
+
+};
+
+}//namespace ns3
+
+#endif /* UDP_SOCKET_IMPL_H */
--- a/src/internet-node/udp-socket.cc	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,521 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/inet-socket-address.h"
-#include "ns3/ipv4-route.h"
-#include "ns3/ipv4.h"
-#include "udp-socket.h"
-#include "udp-l4-protocol.h"
-#include "ipv4-end-point.h"
-#include "ipv4-l4-demux.h"
-#include "ns3/ipv4.h"
-
-NS_LOG_COMPONENT_DEFINE ("UdpSocket");
-
-namespace ns3 {
-
-UdpSocket::UdpSocket ()
-  : m_endPoint (0),
-    m_node (0),
-    m_udp (0),
-    m_errno (ERROR_NOTERROR),
-    m_shutdownSend (false),
-    m_shutdownRecv (false),
-    m_connected (false)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-}
-
-UdpSocket::~UdpSocket ()
-{
-  NS_LOG_FUNCTION_NOARGS ();
-
-  m_node = 0;
-  if (m_endPoint != 0)
-    {
-      NS_ASSERT (m_udp != 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_udp->DeAllocate (m_endPoint);
-      NS_ASSERT (m_endPoint == 0);
-    }
-  m_udp = 0;
-}
-
-void 
-UdpSocket::SetNode (Ptr<Node> node)
-{
-  m_node = node;
-}
-void 
-UdpSocket::SetUdp (Ptr<UdpL4Protocol> udp)
-{
-  m_udp = udp;
-}
-
-
-enum Socket::SocketErrno
-UdpSocket::GetErrno (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_errno;
-}
-
-Ptr<Node>
-UdpSocket::GetNode (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_node;
-}
-
-void 
-UdpSocket::Destroy (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_node = 0;
-  m_endPoint = 0;
-  m_udp = 0;
-}
-
-int
-UdpSocket::FinishBind (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  if (m_endPoint == 0)
-    {
-      return -1;
-    }
-  m_endPoint->SetRxCallback (MakeCallback (&UdpSocket::ForwardUp, this));
-  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocket::Destroy, this));
-  return 0;
-}
-
-int
-UdpSocket::Bind (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_endPoint = m_udp->Allocate ();
-  return FinishBind ();
-}
-
-int 
-UdpSocket::Bind (const Address &address)
-{
-  NS_LOG_FUNCTION (this << address);
-
-  if (!InetSocketAddress::IsMatchingType (address))
-    {
-      NS_LOG_ERROR ("Not IsMatchingType");
-      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_udp->Allocate ();
-    }
-  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
-    {
-      m_endPoint = m_udp->Allocate (port);
-    }
-  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
-    {
-      m_endPoint = m_udp->Allocate (ipv4);
-    }
-  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
-    {
-      m_endPoint = m_udp->Allocate (ipv4, port);
-    }
-
-  return FinishBind ();
-}
-
-int 
-UdpSocket::ShutdownSend (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_shutdownSend = true;
-  return 0;
-}
-
-int 
-UdpSocket::ShutdownRecv (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_shutdownRecv = false;
-  return 0;
-}
-
-int
-UdpSocket::Close(void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  NotifyCloseCompleted ();
-  return 0;
-}
-
-int
-UdpSocket::Connect(const Address & address)
-{
-  NS_LOG_FUNCTION (this << address);
-  Ipv4Route routeToDest;
-  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  m_defaultAddress = transport.GetIpv4 ();
-  m_defaultPort = transport.GetPort ();
-  NotifyConnectionSucceeded ();
-  m_connected = true;
-
-  return 0;
-}
-
-int 
-UdpSocket::Send (Ptr<Packet> p)
-{
-  NS_LOG_FUNCTION (this << p);
-
-  if (!m_connected)
-    {
-      m_errno = ERROR_NOTCONN;
-      return -1;
-    }
-  return DoSend (p);
-}
-
-int 
-UdpSocket::DoSend (Ptr<Packet> p)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  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;
-    } 
-  
-  return DoSendTo (p, m_defaultAddress, m_defaultPort);
-}
-
-int
-UdpSocket::DoSendTo (Ptr<Packet> p, const Address &address)
-{
-  NS_LOG_FUNCTION (this << p << address);
-
-  if (!m_connected)
-    {
-      NS_LOG_LOGIC ("Not connected");
-      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-      Ipv4Address ipv4 = transport.GetIpv4 ();
-      uint16_t port = transport.GetPort ();
-      return DoSendTo (p, ipv4, port);
-    }
-  else
-    {
-      // connected UDP socket must use default addresses
-      NS_LOG_LOGIC ("Connected");
-      return DoSendTo (p, m_defaultAddress, m_defaultPort);
-    }
-}
-
-int
-UdpSocket::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
-{
-  NS_LOG_FUNCTION (this << p << dest << port);
-
-  Ipv4Route routeToDest;
-
-  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;
-    }
-
-  uint32_t localIfIndex;
-  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-
-  //
-  // If dest is sent to the limited broadcast address (all ones),
-  // convert it to send a copy of the packet out of every interface
-  //
-  if (dest.IsBroadcast ())
-    {
-      NS_LOG_LOGIC ("Limited broadcast start.");
-      for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
-        {
-          Ipv4Address addri = ipv4->GetAddress (i);
-          Ipv4Mask maski = ipv4->GetNetworkMask (i);
-          Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
-          NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
-                        << " (mask is " << maski << ")");
-          m_udp->Send (p->Copy (), addri, bcast,
-                       m_endPoint->GetLocalPort (), port);
-          NotifyDataSent (p->GetSize ());
-        }
-      NS_LOG_LOGIC ("Limited broadcast end.");
-      return p->GetSize();
-    }
-  else if (ipv4->GetIfIndexForDestination(dest, localIfIndex))
-    {
-      NS_LOG_LOGIC ("Route exists");
-      m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest,
-		   m_endPoint->GetLocalPort (), port);
-      NotifyDataSent (p->GetSize ());
-      return p->GetSize();;
-    }
-  else
-   {
-      NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
-      m_errno = ERROR_NOROUTETOHOST;
-      return -1;
-   }
-
-  return 0;
-}
-
-int 
-UdpSocket::SendTo(const Address &address, Ptr<Packet> p)
-{
-  NS_LOG_FUNCTION (this << address << p);
-  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  Ipv4Address ipv4 = transport.GetIpv4 ();
-  uint16_t port = transport.GetPort ();
-  return DoSendTo (p, ipv4, port);
-}
-
-void 
-UdpSocket::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
-{
-  NS_LOG_FUNCTION (this << packet << ipv4 << port);
-
-  if (m_shutdownRecv)
-    {
-      return;
-    }
-  
-  Address address = InetSocketAddress (ipv4, port);
-  NotifyDataReceived (packet, address);
-}
-
-} //namespace ns3
-
-
-#ifdef RUN_SELF_TESTS
-
-#include "ns3/test.h"
-#include "ns3/socket-factory.h"
-#include "ns3/udp.h"
-#include "ns3/simulator.h"
-#include "ns3/simple-channel.h"
-#include "ns3/simple-net-device.h"
-#include "ns3/drop-tail-queue.h"
-#include "internet-stack.h"
-#include <string>
-
-namespace ns3 {
-
-class UdpSocketTest: public Test
-{
-  Ptr<Packet> m_receivedPacket;
-  Ptr<Packet> m_receivedPacket2;
-
-public:
-  virtual bool RunTests (void);
-  UdpSocketTest ();
-
-  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
-  void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
-};
-
-
-UdpSocketTest::UdpSocketTest ()
-  : Test ("UdpSocket") {}
-
-
-void UdpSocketTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
-{
-  m_receivedPacket = packet;
-}
-
-void UdpSocketTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
-{
-  m_receivedPacket2 = packet;
-}
-
-bool
-UdpSocketTest::RunTests (void)
-{
-  bool result = true;
-
-  // Create topology
-  
-  // Receiver Node
-  Ptr<Node> rxNode = CreateObject<Node> ();
-  AddInternetStack (rxNode);
-  Ptr<SimpleNetDevice> rxDev1, rxDev2;
-  { // first interface
-    rxDev1 = CreateObject<SimpleNetDevice> ();
-    rxDev1->SetAddress (Mac48Address::Allocate ());
-    rxNode->AddDevice (rxDev1);
-    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
-    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1"));
-    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
-    ipv4->SetUp (netdev_idx);
-  }
-
-  { // second interface
-    rxDev2 = CreateObject<SimpleNetDevice> ();
-    rxDev2->SetAddress (Mac48Address::Allocate ());
-    rxNode->AddDevice (rxDev2);
-    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
-    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1"));
-    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
-    ipv4->SetUp (netdev_idx);
-  }
-  
-  // Sender Node
-  Ptr<Node> txNode = CreateObject<Node> ();
-  AddInternetStack (txNode);
-  Ptr<SimpleNetDevice> txDev1;
-  {
-    txDev1 = CreateObject<SimpleNetDevice> ();
-    txDev1->SetAddress (Mac48Address::Allocate ());
-    txNode->AddDevice (txDev1);
-    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (txDev1);
-    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2"));
-    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
-    ipv4->SetUp (netdev_idx);
-  }
-  Ptr<SimpleNetDevice> txDev2;
-  {
-    txDev2 = CreateObject<SimpleNetDevice> ();
-    txDev2->SetAddress (Mac48Address::Allocate ());
-    txNode->AddDevice (txDev2);
-    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (txDev2);
-    ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2"));
-    ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
-    ipv4->SetUp (netdev_idx);
-  }
-
-  // link the two nodes
-  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
-  rxDev1->SetChannel (channel1);
-  txDev1->SetChannel (channel1);
-
-  Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
-  rxDev2->SetChannel (channel2);
-  txDev2->SetChannel (channel2);
-
-
-  // Create the UDP sockets
-  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<Udp> ();
-  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
-  NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
-  rxSocket->SetRecvCallback (MakeCallback (&UdpSocketTest::ReceivePacket, this));
-
-  Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
-  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketTest::ReceivePacket2, this));
-  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
-
-  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<Udp> ();
-  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
-
-  // ------ Now the tests ------------
-
-  // Unicast test
-  m_receivedPacket = Create<Packet> ();
-  m_receivedPacket2 = Create<Packet> ();
-  NS_TEST_ASSERT_EQUAL (txSocket->SendTo (InetSocketAddress (Ipv4Address("10.0.0.1"), 1234),
-                                          Create<Packet> (123)), 123);
-  Simulator::Run ();
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
-
-
-  // Simple broadcast test
-
-  m_receivedPacket = Create<Packet> ();
-  m_receivedPacket2 = Create<Packet> ();
-  NS_TEST_ASSERT_EQUAL (txSocket->SendTo (InetSocketAddress (Ipv4Address("255.255.255.255"), 1234),
-                                          Create<Packet> (123)), 123);
-  Simulator::Run ();
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
-  // second socket should not receive it (it is bound specifically to the second interface's address
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
-
-
-  // Broadcast test with multiple receiving sockets
-
-  // When receiving broadcast packets, all sockets sockets bound to
-  // the address/port should receive a copy of the same packet -- if
-  // the socket address matches.
-  rxSocket2->Dispose ();
-  rxSocket2 = rxSocketFactory->CreateSocket ();
-  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketTest::ReceivePacket2, this));
-  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
-
-  m_receivedPacket = Create<Packet> ();
-  m_receivedPacket2 = Create<Packet> ();
-  NS_TEST_ASSERT_EQUAL (txSocket->SendTo (InetSocketAddress (Ipv4Address("255.255.255.255"), 1234),
-                                          Create<Packet> (123)), 123);
-  Simulator::Run ();
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
-
-  Simulator::Destroy ();
-
-  return result;
-}
-
-
-static UdpSocketTest gUdpSocketTest;
-
-}; // namespace ns3
-
-#endif /* RUN_SELF_TESTS */
--- a/src/internet-node/udp-socket.h	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef UDP_SOCKET_H
-#define UDP_SOCKET_H
-
-#include <stdint.h>
-#include "ns3/callback.h"
-#include "ns3/socket.h"
-#include "ns3/ptr.h"
-#include "ns3/ipv4-address.h"
-
-namespace ns3 {
-
-class Ipv4EndPoint;
-class Node;
-class Packet;
-class UdpL4Protocol;
-
-class UdpSocket : public Socket
-{
-public:
-  /**
-   * Create an unbound udp socket.
-   */
-  UdpSocket ();
-  virtual ~UdpSocket ();
-
-  void SetNode (Ptr<Node> node);
-  void SetUdp (Ptr<UdpL4Protocol> udp);
-
-  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 SendTo(const Address &address,Ptr<Packet> p);
-
-private:
-
-private:
-  friend class Udp;
-  // invoked by Udp class
-  int FinishBind (void);
-  void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
-  void Destroy (void);
-  int DoSend (Ptr<Packet> p);
-  int DoSendTo (Ptr<Packet> p, const Address &daddr);
-  int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
-
-  Ipv4EndPoint *m_endPoint;
-  Ptr<Node> m_node;
-  Ptr<UdpL4Protocol> m_udp;
-  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;
-};
-
-}//namespace ns3
-
-#endif /* UDP_SOCKET_H */
--- a/src/internet-node/wscript	Sun May 25 14:58:22 2008 -0700
+++ b/src/internet-node/wscript	Tue May 27 15:01:11 2008 -0700
@@ -22,12 +22,12 @@
         'arp-ipv4-interface.cc',
         'arp-l3-protocol.cc',
         'ipv4-loopback-interface.cc',
-        'udp-socket.cc',
-        'tcp-socket.cc',
+        'udp-socket-impl.cc',
+        'tcp-socket-impl.cc',
         'ipv4-end-point-demux.cc',
         'ipv4-impl.cc',
-        'udp-impl.cc',
-        'tcp-impl.cc',
+        'udp-socket-factory-impl.cc',
+        'tcp-socket-factory-impl.cc',
         'pending-data.cc',
         'sequence-number.cc',
         'rtt-estimator.cc',
--- a/src/mobility/rectangle.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/mobility/rectangle.h	Tue May 27 15:01:11 2008 -0700
@@ -61,8 +61,6 @@
   double xMax;
   double yMin;
   double yMax;
-
-  ATTRIBUTE_HELPER_HEADER_1 (Rectangle);
 };
 
 std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
@@ -73,7 +71,7 @@
  * \brief hold objects of type ns3::Rectangle
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Rectangle);
+ATTRIBUTE_HELPER_HEADER (Rectangle);
 
 } // namespace ns3
 
--- a/src/mobility/vector.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/mobility/vector.h	Tue May 27 15:01:11 2008 -0700
@@ -57,8 +57,6 @@
    * z coordinate of vector vector
    */
   double z;
-
-  ATTRIBUTE_HELPER_HEADER_1 (Vector);
 };
 
 double CalculateDistance (const Vector &a, const Vector &b);
@@ -68,7 +66,7 @@
  * \brief hold objects of type ns3::Vector
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Vector);
+ATTRIBUTE_HELPER_HEADER (Vector);
 
 std::ostream &operator << (std::ostream &os, const Vector &vector);
 std::istream &operator >> (std::istream &is, Vector &vector);
--- a/src/node/address.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/address.cc	Tue May 27 15:01:11 2008 -0700
@@ -107,6 +107,30 @@
   return type;
 }
 
+uint32_t
+Address::GetSerializedSize (void) const
+{
+  return 1 + 1 + m_len;
+}
+
+void
+Address::Serialize (uint8_t* buf, uint32_t len) const
+{
+  NS_ASSERT (len >= static_cast<uint32_t> (m_len + 2));
+  buf[0] = m_type;
+  buf[1] = m_len;
+  for (uint8_t i = 0; i < m_len; i++)
+    {
+      buf[i+2] = m_data[i];
+    }
+}
+
+Address
+Address::Deserialize (const uint8_t* buf)
+{
+  return Address (buf[0], buf + 2, buf[1]);
+}
+
 ATTRIBUTE_HELPER_CPP (Address);
 
 
--- a/src/node/address.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/address.h	Tue May 27 15:01:11 2008 -0700
@@ -153,8 +153,28 @@
    * \returns a new type id.
    */
   static uint8_t Register (void);
+  /**
+   * Get the number of bytes needed to serialize the underlying Address
+   * Typically, this is GetLength () + 2 
+   *
+   * \returns the number of bytes required for an Address in serialized form
+   */
+  uint32_t GetSerializedSize (void) const;
+  /**
+   * Serialize this address in host byte order to a byte buffer
+   *
+   * \param buf output buffer that gets written with this Address
+   * \param len length of output buffer
+   */
+  void Serialize (uint8_t* buf, uint32_t len) const;
+  /**
+   * \param buf buffer to read address from
+   * \returns an Address
+   * 
+   * The input address buffer is expected to be in host byte order format.
+   */
+  static Address Deserialize (const uint8_t* buf);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Address);
 private:
   friend bool operator == (const Address &a, const Address &b);
   friend bool operator < (const Address &a, const Address &b);
@@ -171,7 +191,7 @@
  * \brief hold objects of type ns3::Address
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Address);
+ATTRIBUTE_HELPER_HEADER (Address);
 
 bool operator == (const Address &a, const Address &b);
 bool operator != (const Address &a, const Address &b);
--- a/src/node/ipv4-address.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/ipv4-address.h	Tue May 27 15:01:11 2008 -0700
@@ -142,7 +142,6 @@
   static Ipv4Address GetBroadcast (void);
   static Ipv4Address GetLoopback (void);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Ipv4Address);
 private:
   Address ConvertTo (void) const;
   static uint8_t GetType (void);
@@ -180,7 +179,6 @@
   static Ipv4Mask GetLoopback (void);
   static Ipv4Mask GetZero (void);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Ipv4Mask);
 private:
   uint32_t m_mask;
 };
@@ -194,8 +192,8 @@
  * \brief hold objects of type ns3::Ipv4Mask
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Ipv4Address);
-ATTRIBUTE_HELPER_HEADER_2 (Ipv4Mask);
+ATTRIBUTE_HELPER_HEADER (Ipv4Address);
+ATTRIBUTE_HELPER_HEADER (Ipv4Mask);
 
 std::ostream& operator<< (std::ostream& os, Ipv4Address const& address);
 std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
--- a/src/node/mac48-address.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/mac48-address.h	Tue May 27 15:01:11 2008 -0700
@@ -96,7 +96,6 @@
    */
   static Mac48Address GetBroadcast (void);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Mac48Address);
 private:
   /**
    * \returns a new Address instance
@@ -117,7 +116,7 @@
  * \brief hold objects of type ns3::Mac48Address
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Mac48Address);
+ATTRIBUTE_HELPER_HEADER (Mac48Address);
 
 bool operator == (const Mac48Address &a, const Mac48Address &b);
 bool operator != (const Mac48Address &a, const Mac48Address &b);
--- a/src/node/packet-socket.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/packet-socket.cc	Tue May 27 15:01:11 2008 -0700
@@ -24,12 +24,31 @@
 #include "ns3/log.h"
 #include "ns3/node.h"
 #include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
 
 NS_LOG_COMPONENT_DEFINE ("PacketSocket");
 
 namespace ns3 {
 
-PacketSocket::PacketSocket ()
+TypeId
+PacketSocket::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::PacketSocket")
+    .SetParent<Socket> ()
+    .AddConstructor<PacketSocket> ()
+    .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
+                     MakeTraceSourceAccessor (&PacketSocket::m_dropTrace))
+    .AddAttribute ("RcvBufSize",
+                   "PacketSocket maximum receive buffer size (bytes)",
+                   UintegerValue (0xffffffffl),
+                   MakeUintegerAccessor (&PacketSocket::m_rcvBufSize),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+PacketSocket::PacketSocket () : m_rxAvailable (0)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_state = STATE_OPEN;
@@ -41,6 +60,7 @@
 void 
 PacketSocket::SetNode (Ptr<Node> node)
 {
+  NS_LOG_FUNCTION_NOARGS ();
   m_node = node;
 }
 
@@ -211,11 +231,19 @@
       m_errno = ERROR_NOTCONN;
       return -1;
     }
-  return SendTo (m_destAddr, p);
+  return SendTo (p, m_destAddr);
+}
+
+// XXX must limit it to interface MTU
+uint32_t 
+PacketSocket::GetTxAvailable (void) const
+{
+  // Use 65536 for now
+  return 0xffff;
 }
 
 int
-PacketSocket::SendTo(const Address &address, Ptr<Packet> p)
+PacketSocket::SendTo(Ptr<Packet> p, const Address &address)
 {
   NS_LOG_FUNCTION_NOARGS ();
   PacketSocketAddress ad;
@@ -244,6 +272,11 @@
       m_errno = ERROR_AFNOSUPPORT;
       return -1;
     }
+  if (p->GetSize () > GetTxAvailable ())
+    {
+      m_errno = ERROR_MSGSIZE;
+      return -1;
+    }
   ad = PacketSocketAddress::ConvertFrom (address);
   
   bool error = false;
@@ -301,8 +334,56 @@
   address.SetSingleDevice (device->GetIfIndex ());
   address.SetProtocol (protocol);
 
-  NS_LOG_LOGIC ("UID is " << packet->GetUid() << " PacketSocket " << this);
-  NotifyDataReceived (packet, address);
+  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
+    {
+      SocketRxAddressTag tag;
+      tag.SetAddress (address);
+      packet->AddTag (tag);
+      m_deliveryQueue.push (packet);
+      m_rxAvailable += packet->GetSize ();
+      NS_LOG_LOGIC ("UID is " << packet->GetUid() << " PacketSocket " << this);
+      NotifyDataRecv ();
+    }
+  else
+    {
+      // In general, this case should not occur unless the
+      // receiving application reads data from this socket slowly
+      // in comparison to the arrival rate
+      //
+      // drop and trace packet
+      NS_LOG_WARN ("No receive buffer space available.  Drop.");
+      m_dropTrace (packet);
+    }
+}
+
+Ptr<Packet> 
+PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_deliveryQueue.empty() )
+    {
+      return 0;
+    }
+  Ptr<Packet> p = m_deliveryQueue.front ();
+  if (p->GetSize () <= maxSize)
+    {
+      m_deliveryQueue.pop ();
+      m_rxAvailable -= p->GetSize ();
+    }
+  else
+    {
+      p = 0;
+    }
+  return p;
+}
+
+uint32_t
+PacketSocket::GetRxAvailable (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  // We separately maintain this state to avoid walking the queue 
+  // every time this might be called
+  return m_rxAvailable;
 }
 
 }//namespace ns3
--- a/src/node/packet-socket.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/packet-socket.h	Tue May 27 15:01:11 2008 -0700
@@ -22,7 +22,9 @@
 #define PACKET_SOCKET_H
 
 #include <stdint.h>
+#include <queue>
 #include "ns3/callback.h"
+#include "ns3/traced-callback.h"
 #include "ns3/ptr.h"
 #include "ns3/socket.h"
 
@@ -71,6 +73,8 @@
 class PacketSocket : public Socket
 {
 public:
+  static TypeId GetTypeId (void);
+
   PacketSocket ();
   virtual ~PacketSocket ();
 
@@ -85,8 +89,12 @@
   virtual int ShutdownRecv (void);
   virtual int Connect(const Address &address);
   virtual int Send (Ptr<Packet> p);
-  virtual int SendTo(const Address &address,Ptr<Packet> p);
+  virtual uint32_t GetTxAvailable (void) const;
 
+  virtual int SendTo(Ptr<Packet> p, const Address &address);
+
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+  virtual uint32_t GetRxAvailable (void) const;
 
 private:
   void ForwardUp (Ptr<NetDevice> device, Ptr<Packet> packet, 
@@ -109,6 +117,15 @@
   bool m_isSingleDevice;
   uint32_t m_device;
   Address m_destAddr; /// Default destination address
+
+  std::queue<Ptr<Packet> > m_deliveryQueue;
+  uint32_t m_rxAvailable;
+  
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
+  
+  // Socket options (attributes)
+  uint32_t m_rcvBufSize;
+
 };
 
 }//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/socket-defaults.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,42 @@
+/* -*- 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
+ *
+ */
+#include "socket-defaults.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (SocketDefaults);
+
+TypeId SocketDefaults::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SocketDefaults")
+    .SetParent<Object> ()
+    .AddAttribute ("DefaultSndBufLimit",
+                   "Default maximum receive buffer size (bytes)",
+                   UintegerValue (0xffffffffl),
+                   MakeUintegerAccessor (&SocketDefaults::m_defaultSndBufLimit),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("DefaultRcvBufLimit",
+                   "Default maximum receive buffer size (bytes)",
+                   UintegerValue (0xffffffffl),
+                   MakeUintegerAccessor (&SocketDefaults::m_defaultRcvBufLimit),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/socket-defaults.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,42 @@
+/* -*- 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
+ */
+#ifndef SOCKET_DEFAULTS_H
+#define SOCKET_DEFAULTS_H
+
+#include "ns3/object.h"
+
+namespace ns3 {
+
+/**
+ * \brief Object to hold socket option defaults
+ *
+ * This class can be aggregated to a Node and can be used to store
+ * socket defaults for a Node.  
+ * 
+ */
+class SocketDefaults : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+private:
+  uint32_t m_defaultSndBufLimit;
+  uint32_t m_defaultRcvBufLimit;
+};
+
+} // namespace ns3
+
+#endif /* SOCKET_DEFAULTS_H */
--- a/src/node/socket.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/socket.cc	Tue May 27 15:01:11 2008 -0700
@@ -22,17 +22,34 @@
 
 #include "ns3/log.h"
 #include "ns3/packet.h"
+#include "node.h"
 #include "socket.h"
+#include "socket-factory.h"
 
 NS_LOG_COMPONENT_DEFINE ("Socket");
 
 namespace ns3 {
 
+Socket::Socket (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
 Socket::~Socket ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
+Ptr<Socket> 
+Socket::CreateSocket (Ptr<Node> node, TypeId tid)
+{
+  Ptr<Socket> s;
+  Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
+  s = socketFactory->CreateSocket ();
+  NS_ASSERT (s != 0);
+  return s;
+}
+
 void 
 Socket::SetCloseCallback (Callback<void,Ptr<Socket> > closeCompleted)
 {
@@ -80,7 +97,7 @@
 }
 
 void 
-Socket::SetRecvCallback (Callback<void, Ptr<Socket>, Ptr<Packet>,const Address&> receivedData)
+Socket::SetRecvCallback (Callback<void, Ptr<Socket> > receivedData)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_receivedData = receivedData;
@@ -107,7 +124,21 @@
   return Send (p);
 }
 
-int Socket::SendTo (const Address &address, const uint8_t* buf, uint32_t size)
+Ptr<Packet>
+Socket::Recv (void)
+{
+  return Recv (std::numeric_limits<uint32_t>::max(), 0);
+}
+
+int 
+Socket::Recv (uint8_t* buf, uint32_t size, uint32_t flags)
+{
+  Ptr<Packet> p = Recv (size, flags); // read up to "size" bytes
+  memcpy (buf, p->PeekData (), p->GetSize());
+  return p->GetSize ();
+}
+
+int Socket::SendTo (const uint8_t* buf, uint32_t size, const Address &address)
 {
   NS_LOG_FUNCTION_NOARGS ();
   Ptr<Packet> p;
@@ -119,7 +150,7 @@
     {
       p = Create<Packet> (size);
     }
-  return SendTo (address,p);
+  return SendTo (p, address);
 }
 
 void 
@@ -221,13 +252,127 @@
 }
 
 void 
-Socket::NotifyDataReceived (Ptr<Packet> p, const Address &from)
+Socket::NotifyDataRecv (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
   if (!m_receivedData.IsNull ())
     {
-      m_receivedData (this, p, from);
+      m_receivedData (this);
     }
 }
 
+/***************************************************************
+ *           Socket Tags
+ ***************************************************************/
+
+SocketRxAddressTag::SocketRxAddressTag ()  
+{
+}
+
+void 
+SocketRxAddressTag::SetAddress (Address addr)
+{
+  m_address = addr;
+}
+
+Address 
+SocketRxAddressTag::GetAddress (void) const
+{
+  return m_address;
+}
+
+
+TypeId
+SocketRxAddressTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SocketRxAddressTag")
+    .SetParent<Tag> ()
+    .AddConstructor<SocketRxAddressTag> ()
+    ;
+  return tid;
+}
+TypeId
+SocketRxAddressTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t
+SocketRxAddressTag::GetSerializedSize (void) const
+{
+  return m_address.GetSerializedSize ();
+}
+void
+SocketRxAddressTag::Serialize (TagBuffer i) const
+{
+  uint8_t len = m_address.GetSerializedSize ();
+  uint8_t* buffer = new uint8_t[len];
+  memset (buffer, 0, len);
+  m_address.Serialize (buffer, len);
+  i.Write (buffer, len);
+  delete [] buffer;
+}
+void
+SocketRxAddressTag::Deserialize (TagBuffer i)
+{
+  uint8_t type = i.ReadU8 (); 
+  uint8_t len = i.ReadU8 (); 
+  // Len is the length of the address starting from buffer[2]
+  NS_ASSERT (len >= 2);
+  uint8_t* buffer = new uint8_t[len];
+  memset (buffer, 0, len);
+  buffer[0] = type;
+  buffer[1] = len;
+  i.Read (buffer+2, len); // ReadU8 consumes a byte
+  m_address = Address::Deserialize (buffer);
+  delete [] buffer;
+}
+
+SocketIpTtlTag::SocketIpTtlTag ()  
+{
+}
+
+void 
+SocketIpTtlTag::SetTtl (uint8_t ttl)
+{
+  m_ttl = ttl;
+}
+
+uint8_t 
+SocketIpTtlTag::GetTtl (void) const
+{
+  return m_ttl;
+}
+
+
+TypeId
+SocketIpTtlTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SocketIpTtlTag")
+    .SetParent<Tag> ()
+    .AddConstructor<SocketIpTtlTag> ()
+    ;
+  return tid;
+}
+TypeId
+SocketIpTtlTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+uint32_t 
+SocketIpTtlTag::GetSerializedSize (void) const
+{ 
+  return 1;
+}
+void 
+SocketIpTtlTag::Serialize (TagBuffer i) const
+{ 
+  i.WriteU8 (m_ttl);
+}
+void 
+SocketIpTtlTag::Deserialize (TagBuffer i)
+{ 
+  m_ttl = i.ReadU8 ();
+}
+
 }//namespace ns3
--- a/src/node/socket.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/socket.h	Tue May 27 15:01:11 2008 -0700
@@ -25,29 +25,43 @@
 
 #include "ns3/callback.h"
 #include "ns3/ptr.h"
+#include "ns3/tag.h"
 #include "ns3/object.h"
 #include "address.h"
 #include <stdint.h>
 
 namespace ns3 {
 
+
 class Node;
 class Packet;
 
 /**
- * \brief Define a Socket API based on the BSD Socket API.
+ * \ingroup node
+ * \defgroup socket Socket
+ * \brief A low-level Socket API based loosely on the BSD Socket API.
  *
- * Contrary to the original BSD socket API, this API is asynchronous:
- * it does not contain blocking calls. It also uses class ns3::Packet
- * as a fancy byte buffer, allowing data to be passed across the API
- * using an ns3::Packet instead of a raw data pointer.  Other than that, 
- * it tries to stick to the BSD API to make it easier for those who know 
- * the BSD API to use this API.
+ * A few things to keep in mind about this type of socket:
+ * - it uses ns-3 API constructs such as class ns3::Address instead of
+ *   C-style structs
+ * - in contrast to the original BSD socket API, this API is asynchronous:
+ *   it does not contain blocking calls.  Sending and receiving operations
+ *   must make use of the callbacks provided. 
+ * - It also uses class ns3::Packet as a fancy byte buffer, allowing 
+ *   data to be passed across the API using an ns-3 Packet instead of 
+ *   a raw data pointer.  
+ * - Not all of the full POSIX sockets API is supported
+ *
+ * Other than that, it tries to stick to the BSD API to make it 
+ * easier for those who know the BSD API to use this API.  
+ * More details are provided in the ns-3 tutorial.
  */
 class Socket : public Object
 {
 public:
-  virtual ~Socket();
+
+  Socket (void);
+  virtual ~Socket (void);
 
   enum SocketErrno {
     ERROR_NOTERROR,
@@ -65,6 +79,17 @@
   };
 
   /**
+   * This method wraps the creation of sockets that is performed
+   * by a socket factory on a given node based on a TypeId.
+   * 
+   * \return A smart pointer to a newly created socket.
+   * 
+   * \param node The node on which to create the socket
+   * \param tid The TypeId of the socket to create
+   */
+  static Ptr<Socket> CreateSocket (Ptr<Node> node, TypeId tid);
+
+  /**
    * \return the errno associated to the last call which failed in this
    *         socket. Each socket's errno is initialized to zero
    *         when the socket is created.
@@ -151,13 +176,13 @@
    */
   void SetSendCallback (Callback<void, Ptr<Socket>, uint32_t> sendCb);
   /**
-   * \brief Receive data
-   * \param receivedData Invoked whenever new data is received.
+   * \brief Notify application when new data is available to be read.
    *
+   *        This callback is intended to notify a socket that would
+   *        have been blocked in a blocking socket model that data
+   *        is available to be read.
    */
-  void SetRecvCallback (Callback<void, Ptr<Socket>, Ptr<Packet>,
-                          const Address&> receivedData);
-
+  void SetRecvCallback (Callback<void, Ptr<Socket> >);
   /** 
    * \param address the address to try to allocate
    * \returns 0 on success, -1 on failure.
@@ -212,13 +237,54 @@
 
   /**
    * \brief Send data (or dummy data) to the remote host
-   * \param p packet to send
-   * \returns -1 in case of error or the number of bytes copied in the 
-   *          internal buffer and accepted for transmission.
+   *
+   * This function matches closely in semantics to the send() function
+   * call in the standard C library (libc):
+   *   ssize_t send (int s, const void *msg, size_t len, int flags);
+   * except that the function call is asynchronous.
+   * 
+   * In a typical blocking sockets model, this call would block upon
+   * lack of space to hold the message to be sent.  In ns-3 at this
+   * API, the call returns immediately in such a case, but the callback
+   * registered with SetSendCallback() is invoked when the socket
+   * has space (when it conceptually unblocks); this is an asynchronous
+   * I/O model for send().
+   * 
+   * This variant of Send() uses class ns3::Packet to encapsulate
+   * data, rather than providing a raw pointer and length field.  
+   * This allows an ns-3 application to attach tags if desired (such
+   * as a flow ID) and may allow the simulator to avoid some data
+   * copies.  Despite the appearance of sending Packets on a stream
+   * socket, just think of it as a fancy byte buffer with streaming
+   * semantics.    
+   *
+   * If either the message buffer within the Packet is too long to pass 
+   * atomically through the underlying protocol (for datagram sockets), 
+   * or the message buffer cannot entirely fit in the transmit buffer
+   * (for stream sockets), -1 is returned and SocketErrno is set 
+   * to ERROR_MSGSIZE.  If the packet does not fit, the caller can
+   * split the Packet (based on information obtained from 
+   * GetTxAvailable) and reattempt to send the data.
+   *
+   * \param p ns3::Packet to send
+   * \returns the number of bytes accepted for transmission if no error
+   *          occurs, and -1 otherwise.
    */
   virtual int Send (Ptr<Packet> p) = 0;
   
   /**
+   * \brief Returns the number of bytes which can be sent in a single call
+   * to Send. 
+   * 
+   * For datagram sockets, this returns the number of bytes that
+   * can be passed atomically through the underlying protocol.
+   *
+   * For stream sockets, this returns the available space in bytes
+   * left in the transmit buffer.
+   */
+  virtual uint32_t GetTxAvailable (void) const = 0;
+
+  /**
    * \brief Send data (or dummy data) to the remote host
    * \param buf A pointer to a raw byte buffer of some data to send.  If this 
    * is 0, we send dummy data whose size is specified by the second parameter
@@ -231,27 +297,66 @@
   
   /**
    * \brief Send data to a specified peer.
+   * \param p packet to send
    * \param address IP Address of remote host
-   * \param p packet to send
    * \returns -1 in case of error or the number of bytes copied in the 
    *          internal buffer and accepted for transmission.
    */
-  virtual int SendTo (const Address &address,Ptr<Packet> p) = 0;
+  virtual int SendTo (Ptr<Packet> p, const Address &address) = 0;
 
   /**
    * \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 
    * is 0, we send dummy data whose size is specified by the third parameter
    * \param size the number of bytes to copy from the buffer
+   * \param address IP Address of remote host
    * \returns -1 in case of error or the number of bytes copied in the 
    *          internal buffer and accepted for transmission.
    *
    * This is provided so as to have an API which is closer in appearance 
    * to that of real network or BSD sockets.
    */
-  int SendTo (const Address &address, const uint8_t* buf, uint32_t size);
+  int SendTo (const uint8_t* buf, uint32_t size, const Address &address); 
 
+  /**
+   * \brief Read a single packet from the socket
+   * \param maxSize reader will accept packet up to maxSize
+   * \param flags Socket recv flags
+   * \returns Ptr<Packet> of the next in-sequence packet.  Returns
+   * 0 if the socket cannot return a next in-sequence packet conforming
+   * to the maxSize and flags.
+   */
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags) = 0;
+  /**
+   * \brief Read a single packet from the socket
+   *
+   *      Overloaded version of Recv(maxSize, flags) with maxSize
+   *      implicitly set to maximum sized integer, and flags set to zero.
+   *
+   * \returns Ptr<Packet> of the next in-sequence packet.  Returns
+   * 0 if the socket cannot return a next in-sequence packet.
+   */
+   Ptr<Packet> Recv (void);
+  /**
+   * \brief Recv data (or dummy data) from the remote host
+   * \param buf A pointer to a raw byte buffer to write the data to. 
+   * If the underlying packet was carring null (fake) data, this buffer
+   * will be zeroed up to the length specified by the return value.
+   * \param size Number of bytes (at most) to copy to buf
+   * \param flags any flags to pass to the socket
+   * \returns number of bytes copied into buf
+   * 
+   * This is provided so as to have an API which is closer in appearance 
+   * to that of real network or BSD sockets.  
+   */
+  int Recv (uint8_t* buf, uint32_t size, uint32_t flags);
+  /**
+   * Return number of bytes which can be returned from one or 
+   * multiple calls to Recv.
+   * Must be possible to call this method from the Recv callback.
+   */
+  virtual uint32_t GetRxAvailable (void) const = 0;
+ 
 protected:
   void NotifyCloseCompleted (void);
   void NotifyConnectionSucceeded (void);
@@ -262,7 +367,7 @@
   void NotifyCloseRequested (void);
   void NotifyDataSent (uint32_t size);
   void NotifySend (uint32_t spaceAvailable);
-  void NotifyDataReceived (Ptr<Packet> p, const Address &from);
+  void NotifyDataRecv (void);
 
   Callback<void,Ptr<Socket> >    m_closeCompleted;
   Callback<void, Ptr<Socket> >   m_connectionSucceeded;
@@ -273,7 +378,50 @@
   Callback<void, Ptr<Socket>, const Address&>    m_newConnectionCreated;
   Callback<void, Ptr<Socket>, uint32_t>          m_dataSent;
   Callback<void, Ptr<Socket>, uint32_t >         m_sendCb;
-  Callback<void, Ptr<Socket>, Ptr<Packet>,const Address&> m_receivedData;
+  Callback<void, Ptr<Socket> > m_receivedData;
+
+};
+
+/**
+ * \brief This class implements a tag that carries the source address
+ * of a packet across the receiving socket interface.
+ */
+class SocketRxAddressTag : public Tag
+{
+public:
+  SocketRxAddressTag ();
+  void SetAddress (Address addr);
+  Address GetAddress (void) const;
+
+  static TypeId GetTypeId (void);  
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+
+private:
+  Address m_address;
+};
+
+/**
+ * \brief This class implements a tag that carries the socket-specific
+ * TTL of a packet to the IP layer
+ */
+class SocketIpTtlTag : public Tag
+{
+public:
+  SocketIpTtlTag ();
+  void SetTtl (uint8_t ttl);
+  uint8_t GetTtl (void) const;
+
+  static TypeId GetTypeId (void);  
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+
+private:
+  uint8_t m_ttl;
 };
 
 } //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp-socket-factory.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,37 @@
+/* -*- 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-socket-factory.h"
+#include "ns3/uinteger.h"
+#include "ns3/double.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpSocketFactory);
+
+TypeId
+TcpSocketFactory::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpSocketFactory")
+    .SetParent<SocketFactory> ()
+  ;
+  return tid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp-socket-factory.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,55 @@
+/* -*- 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_FACTORY_H
+#define TCP_SOCKET_FACTORY_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 socket factory implementations must provide an implementation 
+ * of CreateSocket
+ * below, and should make use of the default values configured below.
+ * 
+ * \see TcpSocketFactoryImpl
+ *
+ */
+class TcpSocketFactory : public SocketFactory
+{
+public:
+  static TypeId GetTypeId (void);
+
+  virtual Ptr<Socket> CreateSocket (void) = 0;
+
+};
+
+} // namespace ns3
+
+#endif /* TCP_SOCKET_FACTORY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp-socket.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,114 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/double.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/nstime.h"
+#include "tcp-socket.h"
+
+NS_LOG_COMPONENT_DEFINE ("TcpSocket");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpSocket);
+
+TypeId
+TcpSocket::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpSocket")
+    .SetParent<Socket> ()
+    .AddAttribute ("SndBufSize",
+                   "TcpSocket maximum transmit buffer size (bytes)",
+                   UintegerValue (0xffffffffl),
+                   MakeUintegerAccessor (&TcpSocket::GetSndBufSize,
+                                         &TcpSocket::SetSndBufSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RcvBufSize",
+                   "TcpSocket maximum receive buffer size (bytes)",
+                   UintegerValue (0xffffffffl),
+                   MakeUintegerAccessor (&TcpSocket::GetRcvBufSize,
+                                         &TcpSocket::SetRcvBufSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("SegmentSize",
+                   "TCP maximum segment size in bytes (may be adjusted based on MTU discovery)",
+                   UintegerValue (536),
+                   MakeUintegerAccessor (&TcpSocket::GetSegSize,
+                                         &TcpSocket::SetSegSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("AdvertisedWindowSize",
+                   "TCP advertised window size (bytes)",
+                   UintegerValue (0xffff),
+                   MakeUintegerAccessor (&TcpSocket::GetAdvWin,
+                                         &TcpSocket::SetAdvWin),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("SlowStartThreshold",
+                   "TCP slow start threshold (bytes)",
+                   UintegerValue (0xffff),
+                   MakeUintegerAccessor (&TcpSocket::GetSSThresh,
+                                         &TcpSocket::SetSSThresh),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("InitialCwnd",
+                   "TCP initial congestion window size (segments)",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&TcpSocket::GetInitialCwnd,
+                                         &TcpSocket::SetInitialCwnd),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("ConnTimeout",
+                   "TCP retransmission timeout when opening connection (seconds)",
+                   TimeValue (Seconds (3)),
+                   MakeTimeAccessor (&TcpSocket::GetConnTimeout,
+                                     &TcpSocket::SetConnTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("ConnCount",
+                   "Number of connection attempts (SYN retransmissions) before returning failure",
+                   UintegerValue (6),
+                   MakeUintegerAccessor (&TcpSocket::GetConnCount,
+                                         &TcpSocket::SetConnCount),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("DelAckTimeout",
+                   "Timeout value for TCP delayed acks, in seconds",
+                   TimeValue (Seconds (0.2)),
+                   MakeTimeAccessor (&TcpSocket::GetDelAckTimeout,
+                                       &TcpSocket::SetDelAckTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("DelAckCount",
+                   "Number of packets to wait before sending a TCP ack",
+                   UintegerValue (2),
+                   MakeUintegerAccessor (&TcpSocket::GetDelAckMaxCount,
+                                         &TcpSocket::SetDelAckMaxCount),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+TcpSocket::TcpSocket ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+TcpSocket::~TcpSocket ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp-socket.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,94 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation
+ *               2007 INRIA
+ *
+ * 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
+ *
+ * Authors: George F. Riley<riley@ece.gatech.edu>
+ *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef __TCP_SOCKET_H__
+#define __TCP_SOCKET_H__
+
+#include "socket.h"
+#include "ns3/traced-callback.h"
+#include "ns3/callback.h"
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+class Node;
+class Packet;
+
+/**
+ * \brief (abstract) base class of all TcpSockets
+ *
+ * This class exists solely for hosting TcpSocket attributes that can
+ * be reused across different implementations.
+ */
+class TcpSocket : public Socket
+{
+public:
+ static TypeId GetTypeId (void);
+ 
+  TcpSocket (void);
+  virtual ~TcpSocket (void);
+
+  virtual enum Socket::SocketErrno GetErrno (void) const = 0;
+  virtual Ptr<Node> GetNode (void) const = 0;
+  virtual int Bind () = 0;
+  virtual int Close (void) = 0;
+  virtual int ShutdownSend (void) = 0;
+  virtual int ShutdownRecv (void) = 0;
+  virtual int Connect (const Address &address) = 0;
+  virtual int Send (Ptr<Packet> p) = 0;
+  virtual uint32_t GetTxAvailable (void) const = 0;
+  virtual int SendTo (Ptr<Packet> p, const Address &address) = 0;
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags) = 0;
+  virtual uint32_t GetRxAvailable (void) const = 0;
+
+private:
+  // Indirect the attribute setting and getting through private virtual methods
+  virtual void SetSndBufSize (uint32_t size) = 0;
+  virtual uint32_t GetSndBufSize (void) const = 0;
+  virtual void SetRcvBufSize (uint32_t size) = 0;
+  virtual uint32_t GetRcvBufSize (void) const = 0;
+  virtual void SetSegSize (uint32_t size) = 0;
+  virtual uint32_t GetSegSize (void) const = 0;
+  virtual void SetAdvWin (uint32_t window) = 0;
+  virtual uint32_t GetAdvWin (void) const = 0;
+  virtual void SetSSThresh (uint32_t threshold) = 0;
+  virtual uint32_t GetSSThresh (void) const = 0;
+  virtual void SetInitialCwnd (uint32_t count) = 0;
+  virtual uint32_t GetInitialCwnd (void) const = 0;
+  virtual void SetConnTimeout (Time timeout) = 0;
+  virtual Time GetConnTimeout (void) const = 0;
+  virtual void SetConnCount (uint32_t count) = 0;
+  virtual uint32_t GetConnCount (void) const = 0;
+  virtual void SetDelAckTimeout (Time timeout) = 0;
+  virtual Time GetDelAckTimeout (void) const = 0;
+  virtual void SetDelAckMaxCount (uint32_t count) = 0;
+  virtual uint32_t GetDelAckMaxCount (void) const = 0;
+  
+};
+
+} //namespace ns3
+
+#endif /* TCP_SOCKET_H */
+
+
--- a/src/node/tcp.cc	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/* -*- 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"
-#include "ns3/uinteger.h"
-#include "ns3/double.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (Tcp);
-
-TypeId
-Tcp::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::Tcp")
-    .SetParent<SocketFactory> ()
-    .AddAttribute ("DefaultSegmentSize",
-                   "Default TCP maximum segment size in bytes (may be adjusted based on MTU discovery)",
-                   UintegerValue (536),
-                   MakeUintegerAccessor (&Tcp::m_defaultSegSize),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultAdvertisedWindowSize",
-                   "Default TCP advertised window size (bytes)",
-                   UintegerValue (0xffff),
-                   MakeUintegerAccessor (&Tcp::m_defaultAdvWin),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultSlowStartThreshold",
-                   "Default TCP slow start threshold (bytes)",
-                   UintegerValue (0xffff),
-                   MakeUintegerAccessor (&Tcp::m_defaultSsThresh),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultTxBufferSize",
-                   "Default TCP maximum transmit buffer size (bytes)",
-                   UintegerValue (0xffffffffl),
-                   MakeUintegerAccessor (&Tcp::m_defaultTxBuffer),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultRxBufferSize",
-                   "Default TCP maximum receive buffer size (bytes)",
-                   UintegerValue (0xffffffffl),
-                   MakeUintegerAccessor (&Tcp::m_defaultRxBuffer),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultInitialCongestionWindowSize",
-                   "Default TCP initial congestion window size (segments)",
-                   UintegerValue (1),
-                   MakeUintegerAccessor (&Tcp::m_defaultInitialCwnd),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultConnTimeout",
-                   "Default TCP retransmission timeout when opening connection (seconds)",
-                   UintegerValue (3),
-                   MakeUintegerAccessor (&Tcp::m_defaultConnTimeout),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultConnCount",
-                   "Default number of connection attempts (SYN retransmissions) before returning failure",
-                   UintegerValue (6),
-                   MakeUintegerAccessor (&Tcp::m_defaultConnCount),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultDelAckTimeout",
-                   "Default timeout value for TCP delayed acks, in seconds",
-                   DoubleValue (0.2),
-                   MakeDoubleAccessor (&Tcp::m_defaultDelAckTimeout),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("DefaultDelAckCount",
-                   "Default number of packets to wait before sending a TCP ack",
-                   UintegerValue (2),
-                   MakeUintegerAccessor (&Tcp::m_defaultDelAckCount),
-                   MakeUintegerChecker<uint32_t> ())
-     ;
-  return tid;
-}
-
-uint32_t 
-Tcp::GetDefaultSegSize (void) const
-{
-  return m_defaultSegSize;
-}
-uint32_t 
-Tcp::GetDefaultAdvWin (void) const
-{
-  return m_defaultAdvWin;
-}
-uint32_t 
-Tcp::GetDefaultSsThresh (void) const
-{
-  return m_defaultSsThresh;
-}
-uint32_t 
-Tcp::GetDefaultTxBuffer (void) const
-{
-  return m_defaultTxBuffer;
-}
-uint32_t 
-Tcp::GetDefaultRxBuffer (void) const
-{
-  return m_defaultRxBuffer;
-}
-uint32_t 
-Tcp::GetDefaultInitialCwnd (void) const
-{
-  return m_defaultInitialCwnd;
-}
-uint32_t 
-Tcp::GetDefaultConnTimeout (void) const
-{
-  return m_defaultConnTimeout;
-}
-uint32_t 
-Tcp::GetDefaultConnCount (void) const
-{
-  return m_defaultConnCount;
-}
-
-double
-Tcp::GetDefaultDelAckTimeout (void) const
-{
-  return m_defaultDelAckTimeout;
-}
-
-uint32_t
-Tcp::GetDefaultDelAckCount (void) const
-{
-  return m_defaultDelAckCount;
-}
-
-} // namespace ns3
--- a/src/node/tcp.h	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/* -*- 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 "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 TypeId GetTypeId (void);
-
-  virtual Ptr<Socket> CreateSocket (void) = 0;
-
-  uint32_t GetDefaultSegSize (void) const;
-  uint32_t GetDefaultAdvWin (void) const;
-  uint32_t GetDefaultSsThresh (void) const;
-  uint32_t GetDefaultTxBuffer (void) const;
-  uint32_t GetDefaultRxBuffer (void) const;
-  uint32_t GetDefaultInitialCwnd (void) const;
-  uint32_t GetDefaultConnTimeout (void) const;
-  uint32_t GetDefaultConnCount (void) const;
-  double   GetDefaultDelAckTimeout (void) const;
-  uint32_t GetDefaultDelAckCount (void) const;
-
-private:
-  uint32_t  m_defaultSegSize;
-  uint32_t  m_defaultAdvWin; 
-  uint32_t  m_defaultSsThresh;
-  uint32_t  m_defaultTxBuffer;
-  uint32_t  m_defaultRxBuffer;
-  uint32_t  m_defaultInitialCwnd;
-  uint32_t  m_defaultConnTimeout;
-  uint32_t  m_defaultConnCount;
-  double    m_defaultDelAckTimeout;
-  uint32_t  m_defaultDelAckCount;
-
-};
-
-} // namespace ns3
-
-#endif /* TCP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/udp-socket-factory.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,35 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "udp-socket-factory.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (UdpSocketFactory);
+
+TypeId UdpSocketFactory::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UdpSocketFactory")
+    .SetParent<SocketFactory> ()
+    ;
+  return tid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/udp-socket-factory.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,55 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef UDP_SOCKET_FACTORY_H
+#define UDP_SOCKET_FACTORY_H
+
+#include "socket-factory.h"
+
+namespace ns3 {
+
+class Socket;
+
+/**
+ * \brief API to create UDP socket instances 
+ *
+ * This abstract class defines the API for UDP socket factory.
+ * All UDP implementations must provide an implementation of CreateSocket
+ * below.
+ * 
+ * \see UdpSocketFactoryImpl
+ */
+class UdpSocketFactory : public SocketFactory
+{
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \return smart pointer to Socket
+   * 
+   * API for creating socket instances; must be implemented by UDP 
+   * implementations..
+   */
+  virtual Ptr<Socket> CreateSocket (void) = 0;
+
+};
+
+} // namespace ns3
+
+#endif /* UDP_SOCKET_FACTORY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/udp-socket.cc	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,70 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+#include "udp-socket.h"
+
+NS_LOG_COMPONENT_DEFINE ("UdpSocket");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (UdpSocket);
+
+TypeId
+UdpSocket::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::UdpSocket")
+    .SetParent<Socket> ()
+    .AddAttribute ("RcvBufSize",
+                   "UdpSocket maximum receive buffer size (bytes)",
+                   UintegerValue (0xffffffffl),
+                   MakeUintegerAccessor (&UdpSocket::GetRcvBufSize,
+                                         &UdpSocket::SetRcvBufSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("IpTtl",
+                   "socket-specific TTL for unicast IP packets (if non-zero)",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&UdpSocket::GetIpTtl,
+                                         &UdpSocket::SetIpTtl),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("IpMulticastTtl",
+                   "socket-specific TTL for multicast IP packets (if non-zero)",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&UdpSocket::GetIpMulticastTtl,
+                                         &UdpSocket::SetIpMulticastTtl),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+UdpSocket::UdpSocket ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+UdpSocket::~UdpSocket ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/udp-socket.h	Tue May 27 15:01:11 2008 -0700
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation
+ *               2007 INRIA
+ *
+ * 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
+ *
+ * Authors: George F. Riley<riley@ece.gatech.edu>
+ *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef __UDP_SOCKET_H__
+#define __UDP_SOCKET_H__
+
+#include "socket.h"
+#include "ns3/traced-callback.h"
+#include "ns3/callback.h"
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+
+namespace ns3 {
+
+class Node;
+class Packet;
+
+/**
+ * \brief (abstract) base class of all UdpSockets
+ *
+ * This class exists solely for hosting UdpSocket attributes that can
+ * be reused across different implementations.
+ */
+class UdpSocket : public Socket
+{
+public:
+ static TypeId GetTypeId (void);
+ 
+  UdpSocket (void);
+  virtual ~UdpSocket (void);
+
+  virtual enum Socket::SocketErrno GetErrno (void) const = 0;
+  virtual Ptr<Node> GetNode (void) const = 0;
+  virtual int Bind () = 0;
+  virtual int Close (void) = 0;
+  virtual int ShutdownSend (void) = 0;
+  virtual int ShutdownRecv (void) = 0;
+  virtual int Connect (const Address &address) = 0;
+  virtual int Send (Ptr<Packet> p) = 0;
+  virtual uint32_t GetTxAvailable (void) const = 0;
+  virtual int SendTo (Ptr<Packet> p, const Address &address) = 0;
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags) = 0;
+  virtual uint32_t GetRxAvailable (void) const = 0;
+
+private:
+  // Indirect the attribute setting and getting through private virtual methods
+  virtual void SetRcvBufSize (uint32_t size) = 0;
+  virtual uint32_t GetRcvBufSize (void) const = 0;
+  virtual void SetIpTtl (uint32_t ipTtl) = 0;
+  virtual uint32_t GetIpTtl (void) const = 0;
+  virtual void SetIpMulticastTtl (uint32_t ipTtl) = 0;
+  virtual uint32_t GetIpMulticastTtl (void) const = 0;
+  
+};
+
+} //namespace ns3
+
+#endif /* UDP_SOCKET_H */
+
+
--- a/src/node/udp.cc	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "udp.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (Udp);
-
-TypeId Udp::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::Udp")
-    .SetParent<SocketFactory> ();
-  return tid;
-}
-
-Udp::Udp ()
-{}
-
-} // namespace ns3
--- a/src/node/udp.h	Sun May 25 14:58:22 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef UDP_H
-#define UDP_H
-
-#include "socket-factory.h"
-
-namespace ns3 {
-
-class Socket;
-
-/**
- * \brief API to create UDP socket instances 
- *
- * This abstract class defines the API for UDP sockets.
- * This class also can hold 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 UDP implementations must provide an implementation of CreateSocket
- * below.
- * 
- * \see UdpImpl
- */
-class Udp : public SocketFactory
-{
-public:
-  static TypeId GetTypeId (void);
-
-  Udp ();
-
-  /**
-   * \return smart pointer to Socket
-   * 
-   * API for creating socket instances; must be implemented by UDP 
-   * implementations..
-   */
-  virtual Ptr<Socket> CreateSocket (void) = 0;
-};
-
-} // namespace ns3
-
-#endif /* UDP_H */
--- a/src/node/wscript	Sun May 25 14:58:22 2008 -0700
+++ b/src/node/wscript	Tue May 27 15:01:11 2008 -0700
@@ -25,8 +25,10 @@
         'socket-factory.cc',
         'packet-socket-factory.cc',
         'packet-socket.cc',
-        'udp.cc',
-        'tcp.cc',
+        'udp-socket.cc',
+        'udp-socket-factory.cc',
+        'tcp-socket.cc',
+        'tcp-socket-factory.cc',
         'ipv4.cc',
         'application.cc',
         'simple-channel.cc',
@@ -57,8 +59,10 @@
         'socket.h',
         'socket-factory.h',
         'packet-socket-factory.h',
-        'udp.h',
-        'tcp.h',
+        'udp-socket.h',
+        'udp-socket-factory.h',
+        'tcp-socket.h',
+        'tcp-socket-factory.h',
         'ipv4.h',
         'application.h',
         'simple-channel.h',
--- a/src/routing/olsr/olsr-agent-impl.cc	Sun May 25 14:58:22 2008 -0700
+++ b/src/routing/olsr/olsr-agent-impl.cc	Tue May 27 15:01:11 2008 -0700
@@ -31,7 +31,7 @@
 
 #include "olsr-agent-impl.h"
 #include "ns3/socket-factory.h"
-#include "ns3/udp.h"
+#include "ns3/udp-socket-factory.h"
 #include "ns3/simulator.h"
 #include "ns3/log.h"
 #include "ns3/random-variable.h"
@@ -258,9 +258,7 @@
   // Add OLSR as routing protocol, with slightly higher priority than
   // static routing.
   m_ipv4->AddRoutingProtocol (m_routingTable, 10);
-
-  Ptr<SocketFactory> socketFactory = GetObject<SocketFactory> (Udp::GetTypeId ());
-
+  
   Ipv4Address loopback ("127.0.0.1");
   for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
     {
@@ -281,7 +279,8 @@
         }
 
       // Create a socket to listen only on this interface
-      Ptr<Socket> socket = socketFactory->CreateSocket ();
+      Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), 
+        UdpSocketFactory::GetTypeId()); 
       socket->SetRecvCallback (MakeCallback (&AgentImpl::RecvOlsr,  this));
       if (socket->Bind (InetSocketAddress (addr, OLSR_PORT_NUMBER)))
         {
@@ -307,10 +306,17 @@
 //
 // \brief Processes an incoming %OLSR packet following RFC 3626 specification.
 void
-AgentImpl::RecvOlsr (Ptr<Socket> socket,
-                     Ptr<Packet> receivedPacket,
-                     const Address &sourceAddress)
+AgentImpl::RecvOlsr (Ptr<Socket> socket)
 {
+  Ptr<Packet> receivedPacket;
+  receivedPacket = socket->Recv ();
+
+  SocketRxAddressTag tag;
+  bool found;
+  found = receivedPacket->FindFirstMatchingTag (tag);
+  NS_ASSERT (found);
+  Address sourceAddress = tag.GetAddress ();
+
   InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
   Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 ();
   Ipv4Address receiverIfaceAddr = m_socketAddresses[socket];
--- a/src/routing/olsr/olsr-agent-impl.h	Sun May 25 14:58:22 2008 -0700
+++ b/src/routing/olsr/olsr-agent-impl.h	Tue May 27 15:01:11 2008 -0700
@@ -98,9 +98,7 @@
   /// Increments message sequence number and returns the new value.
   inline uint16_t GetMessageSequenceNumber ();
 	
-  void RecvOlsr (Ptr<Socket> socket,
-                 Ptr<Packet> receivedPacket,
-                 const Address &sourceAddress);
+  void RecvOlsr (Ptr<Socket> socket);
 
   void MprComputation ();
   void RoutingTableComputation ();
--- a/utils/print-introspected-doxygen.cc	Sun May 25 14:58:22 2008 -0700
+++ b/utils/print-introspected-doxygen.cc	Tue May 27 15:01:11 2008 -0700
@@ -236,8 +236,8 @@
   NodeContainer c; c.Create (1);
 
   StaticInformation info;
-  info.RecordAggregationInfo ("ns3::Node", "ns3::Tcp");
-  info.RecordAggregationInfo ("ns3::Node", "ns3::Udp");
+  info.RecordAggregationInfo ("ns3::Node", "ns3::TcpSocketFactory");
+  info.RecordAggregationInfo ("ns3::Node", "ns3::UdpSocketFactory");
   info.RecordAggregationInfo ("ns3::Node", "ns3::PacketSocketFactory");
   info.RecordAggregationInfo ("ns3::Node", "ns3::olsr::Agent");
   info.RecordAggregationInfo ("ns3::Node", "ns3::MobilityModel");