Fixes to tcp and to the ipv4endpointdemux to allow forking to work correctly
authorRaj Bhattacharjea <raj.b@gatech.edu>
Wed, 12 Mar 2008 14:52:29 -0400
changeset 2363 fec623ea779b
parent 2362 d02b7fd0e577
child 2364 a78056f7a7b4
Fixes to tcp and to the ipv4endpointdemux to allow forking to work correctly
src/applications/packet-sink/packet-sink.cc
src/applications/packet-sink/packet-sink.h
src/internet-node/ipv4-end-point-demux.cc
src/internet-node/tcp-l4-protocol.cc
src/internet-node/tcp-socket.cc
src/internet-node/tcp-socket.h
--- a/src/applications/packet-sink/packet-sink.cc	Wed Mar 12 11:55:08 2008 -0400
+++ b/src/applications/packet-sink/packet-sink.cc	Wed Mar 12 14:52:29 2008 -0400
@@ -83,9 +83,9 @@
 
   m_socket->SetRecvCallback (MakeCallback(&PacketSink::Receive, this));
   m_socket->SetAcceptCallback (
-            MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
+            MakeCallback (&PacketSink::AcceptConnectionRequest, this),
             MakeNullCallback<void, Ptr<Socket>, const Address&> (),
-            MakeCallback(&PacketSink::CloseConnection, this) );
+            MakeCallback (&PacketSink::CloseConnection, this) );
 }
 
 void PacketSink::StopApplication()     // Called at time specified by Stop
@@ -116,6 +116,11 @@
   socket->Close ();
 }
 
+bool PacketSink::AcceptConnectionRequest (Ptr<Socket> socket, const Address &from)
+{
+  return true;
+}
+
 Ptr<TraceResolver> 
 PacketSink::GetTraceResolver (void) const
 {
--- a/src/applications/packet-sink/packet-sink.h	Wed Mar 12 11:55:08 2008 -0400
+++ b/src/applications/packet-sink/packet-sink.h	Wed Mar 12 14:52:29 2008 -0400
@@ -79,6 +79,7 @@
 
   virtual void Receive (Ptr<Socket> socket, Ptr<Packet> packet, const Address& from);
   virtual void CloseConnection (Ptr<Socket> socket);
+  virtual bool AcceptConnectionRequest (Ptr<Socket> socket, const Address &from);
 
   Ptr<Socket>     m_socket;       // Associated socket
   Address         m_local;        // Local address to bind to
--- a/src/internet-node/ipv4-end-point-demux.cc	Wed Mar 12 11:55:08 2008 -0400
+++ b/src/internet-node/ipv4-end-point-demux.cc	Wed Mar 12 14:52:29 2008 -0400
@@ -185,10 +185,11 @@
                            Ptr<Ipv4Interface> incomingInterface)
 {
   NS_LOG_FUNCTION;
-  uint32_t genericity = 3;
-  Ipv4EndPoint *generic = 0;
-  EndPoints retval;
-
+  EndPoints retval1; // Matches exact on local port, wildcards on others
+  EndPoints retval2; // Matches exact on local port/adder, wildcards on others
+  EndPoints retval3; // Matches all but local address
+  EndPoints retval4; // Exact match on all 4
+  
   //NS_LOG_PARAMS (this << daddr << dport << saddr << sport);
   NS_LOG_PARAMS_BEGIN ();
   NS_LOG_PARAM (this);
@@ -198,9 +199,106 @@
   NS_LOG_PARAM (sport);
   NS_LOG_PARAM (incomingInterface);
   NS_LOG_PARAMS_END ();
-
+  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
   for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
     {
+      Ipv4EndPoint* endP = *i;
+      NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
+                    << " daddr=" << endP->GetLocalAddress ()
+                    << " sport=" << endP->GetPeerPort ()
+                    << " saddr=" << endP->GetPeerAddress ());
+      if (endP->GetLocalPort () != dport) 
+        {
+          NS_LOG_LOGIC ("Skipping endpoint " << &endP
+                        << " because endpoint dport "
+                        << endP->GetLocalPort ()
+                        << " does not match packet dport " << dport);
+          continue;
+        }
+      bool isBroadcast = (daddr.IsBroadcast () ||
+         daddr.IsSubnetDirectedBroadcast (
+             incomingInterface->GetNetworkMask ()));
+      Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress ();
+      NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast
+                    << " localInterface="<< endP->GetLocalInterface ());
+      bool localAddressMatchesWildCard = 
+        (endP->GetLocalAddress() == Ipv4Address::GetAny()) &&
+        (endP->GetLocalInterface() == Ipv4Address::GetAny());
+      bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
+
+      if (isBroadcast)
+        {
+          std::cout  << "Found bcast, localaddr " << endP->GetLocalAddress() 
+                     << std::endl;
+        }
+
+      if (isBroadcast && (endP->GetLocalAddress() != Ipv4Address::GetAny()))
+        {
+          localAddressMatchesExact = (endP->GetLocalAddress () ==
+                                      incomingInterfaceAddr);
+        }
+      // if no match here, keep looking
+      if (!(localAddressMatchesExact || localAddressMatchesWildCard))
+        continue; 
+      bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
+      bool remotePeerMatchesWildCard = endP->GetPeerPort() == 0;
+      bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
+      bool remoteAddressMatchesWildCard = endP->GetPeerAddress () ==
+        Ipv4Address::GetAny();
+      // If remote does not match either with exact or wildcard,
+      // skip this one
+      if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
+        continue;
+      if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
+        continue;
+      
+      // Now figure out which return list to add this one to
+      if (localAddressMatchesWildCard &&
+          remotePeerMatchesWildCard &&
+          remoteAddressMatchesWildCard)
+        { // Only local port matches exactly
+          retval1.push_back(endP);
+        }
+      if ((localAddressMatchesExact || ((isBroadcast && localAddressMatchesWildCard)))&&
+          remotePeerMatchesWildCard &&
+           remoteAddressMatchesWildCard)
+        { // Only local port and local address matches exactly
+          retval2.push_back(endP);
+        }
+      if (localAddressMatchesWildCard &&
+          remotePeerMatchesExact &&
+          remoteAddressMatchesExact)
+        { // All but local address
+          retval3.push_back(endP);
+        }
+      if (localAddressMatchesExact &&
+          remotePeerMatchesExact &&
+          remoteAddressMatchesExact)
+        { // All 4 match
+          retval4.push_back(endP);
+        }
+    }
+
+  // Here we find the most exact match
+  // first some debug
+#ifdef JUST_DEBUG
+  if (!retval4.empty()) std::cout << "Matches 4" << std::endl;
+  else if (!retval3.empty()) std::cout << "Matches 3" << std::endl;
+  else if (!retval2.empty()) std::cout << "Matches 2" << std::endl;
+  else if (!retval1.empty()) std::cout << "Matches 1" << std::endl;
+#endif
+  // end debug
+  if (!retval4.empty()) return retval4;
+  if (!retval3.empty()) return retval3;
+  if (!retval2.empty()) return retval2;
+  return retval1;  // might be empty if no matches
+  
+#ifdef REMOVE_FOR_TESTING  
+  uint32_t genericity = 3;
+  Ipv4EndPoint *generic = 0;
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+    {
+      //Ipv4EndPoint* endP = *i;
       NS_LOG_DEBUG ("Looking at endpoint dport=" << (*i)->GetLocalPort ()
                     << " daddr=" << (*i)->GetLocalAddress ()
                     << " sport=" << (*i)->GetPeerPort ()
@@ -271,6 +369,7 @@
       retval.push_back (generic);
     }
   return retval;
+#endif
 }
 
 uint16_t
--- a/src/internet-node/tcp-l4-protocol.cc	Wed Mar 12 11:55:08 2008 -0400
+++ b/src/internet-node/tcp-l4-protocol.cc	Wed Mar 12 14:52:29 2008 -0400
@@ -36,6 +36,7 @@
 
 #include <vector>
 #include <sstream>
+#include <iomanip>
 
 NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol");
 
@@ -177,7 +178,7 @@
   aT[FIN_WAIT_2][APP_LISTEN]  = SA (CLOSED,      RST_TX);
   aT[FIN_WAIT_2][APP_CONNECT] = SA (CLOSED,      RST_TX);
   aT[FIN_WAIT_2][APP_SEND]    = SA (CLOSED,      RST_TX);
-  aT[FIN_WAIT_2][SEQ_RECV]    = SA (FIN_WAIT_2,  NO_ACT);
+  aT[FIN_WAIT_2][SEQ_RECV]    = SA (FIN_WAIT_2,  NEW_SEQ_RX);
   aT[FIN_WAIT_2][APP_CLOSE]   = SA (FIN_WAIT_2,  NO_ACT);
   aT[FIN_WAIT_2][TIMEOUT]     = SA (FIN_WAIT_2,  NO_ACT);
   aT[FIN_WAIT_2][ACK_RX]      = SA (FIN_WAIT_2,  NEW_ACK);
@@ -341,7 +342,7 @@
 TcpL4Protocol::CreateSocket (void)
 {
   NS_LOG_FUNCTION;
-  Ptr<Socket> socket = Create<TcpSocket> (m_node, this);
+  Ptr<Socket> socket = CreateObject<TcpSocket> (m_node, this);
   return socket;
 }
 
@@ -408,6 +409,11 @@
   TcpHeader tcpHeader;
   //these two do a peek, so that the packet can be forwarded up
   packet->RemoveHeader (tcpHeader);
+  NS_LOG_LOGIC("TcpL4Protocol " << this
+               << " receiving seq " << tcpHeader.GetSequenceNumber()
+               << " ack " << tcpHeader.GetAckNumber()
+               << " flags "<< std::hex << (int)tcpHeader.GetFlags() << std::dec
+               << " data size " << packet->GetSize());
   packet->AddHeader (tcpHeader); 
   NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
   Ipv4EndPointDemux::EndPoints endPoints =
@@ -463,6 +469,11 @@
 TcpL4Protocol::SendPacket (Ptr<Packet> packet, TcpHeader outgoingHeader,
                                Ipv4Address saddr, Ipv4Address daddr)
 {
+  NS_LOG_LOGIC("TcpL4Protocol " << this
+              << " sending seq " << outgoingHeader.GetSequenceNumber()
+              << " ack " << outgoingHeader.GetAckNumber()
+              << " flags " << std::hex << (int)outgoingHeader.GetFlags() << std::dec
+              << " data size " << packet->GetSize());
   NS_LOG_FUNCTION;
   NS_LOG_PARAMS (this << packet << saddr << daddr);
   // XXX outgoingHeader cannot be logged
--- a/src/internet-node/tcp-socket.cc	Wed Mar 12 11:55:08 2008 -0400
+++ b/src/internet-node/tcp-socket.cc	Wed Mar 12 14:52:29 2008 -0400
@@ -84,8 +84,8 @@
     m_endPoint (0),
     m_node (sock.m_node),
     m_tcp (sock.m_tcp),
-    m_defaultAddress (sock.m_defaultAddress),
-    m_defaultPort (sock.m_defaultPort),
+    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),
@@ -266,15 +266,15 @@
     {
       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);
-  if (m_pendingData)
-    {
-      if (action == FIN_TX && m_pendingData->Size () != 0 )
-        {
-          m_closeOnEmpty = true;
-          return 0;
-        }
-    }
   ProcessAction (action);
   ShutdownSend ();
   return 0;
@@ -295,13 +295,13 @@
       NS_ASSERT (m_endPoint != 0);
     }
   InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  m_defaultAddress = transport.GetIpv4 ();
-  m_defaultPort = transport.GetPort ();
+  m_remoteAddress = transport.GetIpv4 ();
+  m_remotePort = transport.GetPort ();
   
   uint32_t localIfIndex;
   Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
 
-  if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
+  if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
     {
       m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
     }
@@ -321,30 +321,8 @@
 }
 int 
 TcpSocket::Send (const Ptr<Packet> p) //p here is just data, no headers
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << p);
-  if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
-    { // Ok to buffer some data to send
-      if (!m_pendingData)
-        {
-          m_pendingData = new PendingData (0);   // Create if non-existent
-          m_firstPendingSequence = m_nextTxSequence; // Note seq of first
-        }
-      //PendingData::Add always copies the data buffer, never modifies
-      m_pendingData->Add (p->GetSize (), p->PeekData ());
-      Actions_t action = ProcessEvent (APP_SEND);
-      if (!ProcessAction (action)) 
-        {
-          return -1; // Failed, return zero
-        }
-      return p->GetSize ();
-    }
-  else
-    {
-      m_errno = ERROR_NOTCONN;
-      return -1;
-    }
+{ // 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)
@@ -360,7 +338,10 @@
       }
       //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
@@ -437,6 +418,12 @@
 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;
   NS_LOG_PARAMS (this << packet << ipv4 << port);
   if (m_shutdownRecv)
@@ -458,6 +445,9 @@
   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);
 }
 
@@ -489,9 +479,10 @@
     // this means the application side has completed its portion of 
     // the handshaking
     {
-      NotifyConnectionSucceeded ();
+      Simulator::ScheduleNow(&TcpSocket::ConnectionSucceeded, this);
+      //NotifyConnectionSucceeded ();
       m_connected = true;
-      m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
+      m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
       NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
     }
 
@@ -523,10 +514,10 @@
   header.SetSequenceNumber (m_nextTxSequence);
   header.SetAckNumber (m_nextRxSequence);
   header.SetSourcePort (m_endPoint->GetLocalPort ());
-  header.SetDestinationPort (m_defaultPort);
+  header.SetDestinationPort (m_remotePort);
   header.SetWindowSize (m_advertisedWindowSize);
   m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), 
-    m_defaultAddress);
+    m_remoteAddress);
   Time rto = m_rtt->RetransmitTimeout ();
   if (flags & TcpHeader::SYN)
     {
@@ -632,56 +623,46 @@
   {
     case SYN_ACK_TX:
       NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
-      m_defaultPort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
-      m_defaultAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
-      if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
-	    {
-          m_localAddress = ipv4->GetAddress (localIfIndex);
-        }
+//      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
         {
-          //this isn't a smart pointer because if it were it'd go out of scope and
-          //get deleted; since execution will get back to this socket, it will
-          //eventually get passed back up to the application as a smart pointer
-          TcpSocket* newSock = new TcpSocket(*this);
-          //Ptr<TcpSocket> newSock = Create<TcpSocket>(*this);
+          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);
-          //the cloned socket with be in listen state, so manually change state
-          newSock->m_state = SYN_RCVD;
           //this listening socket should do nothing more
-          return newSock->ProcessPacketAction(SYN_ACK_TX, p, tcpHeader, fromAddress);
+          Simulator::ScheduleNow (&TcpSocket::CompleteFork, newSock,
+                                  p, tcpHeader,fromAddress);
+          return true;
         }
-
-      if (!m_endPoint) //no endpoint means this a cloned socket due to SYN_RX
-        {
-          //equivalent to Bind
-          m_endPoint = m_tcp->Allocate (m_localAddress,
-                                        m_localPort,
-                                        m_defaultAddress,
-                                        m_defaultPort,
-                                        Ipv4Address::GetAny()
-                                       );
-          //equivalent to FinishBind
-          m_endPoint->SetRxCallback (MakeCallback (&TcpSocket::ForwardUp, this));
-          m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, this));
-        }
-      else
-        {
-          m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
-          if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
-            {
-			  m_localAddress = ipv4->GetAddress (localIfIndex);
-              m_endPoint->SetLocalAddress (m_localAddress);
-            }
-        }
-      // TCP SYN consumes one byte
-      m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
-      SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+        // 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);
+      NS_LOG_DEBUG ("TcpSocket " << this << " ACK_TX_1" <<
+                    " nextRxSeq " << m_nextRxSequence);
       SendEmptyPacket (TcpHeader::ACK);
       m_rxWindowSize = tcpHeader.GetWindowSize ();
       m_nextTxSequence = tcpHeader.GetAckNumber ();
@@ -710,7 +691,7 @@
       NewAck (tcpHeader.GetAckNumber ());
       break;
     case NEW_SEQ_RX:
-      NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_SEQ_TX");
+      NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_SEQ_RX");
       NewRx (p, tcpHeader, fromAddress); // Process new data received
       break;
     case PEER_CLOSE:
@@ -740,7 +721,7 @@
         {
           NS_LOG_LOGIC ("TCP " << this 
               << " calling AppCloseRequest");
-          NotifyCloseRequested ();
+          NotifyHalfClose ();
           m_closeRequestNotified = true;
         }
       NS_LOG_LOGIC ("TcpSocket " << this 
@@ -763,7 +744,7 @@
       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_defaultAddress, m_defaultPort);
+      m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
       //treat the connection orientation final ack as a newack
       CommonNewAck (tcpHeader.GetAckNumber (), true);
       break;
@@ -773,6 +754,33 @@
   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,
+                                Ipv4Address::GetAny()
+                                );
+  //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, this));
+  m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, this));
+  ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress);
+  NotifyNewConnectionCreated(this, 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;
@@ -827,7 +835,7 @@
       header.SetSequenceNumber (m_nextTxSequence);
       header.SetAckNumber (m_nextRxSequence);
       header.SetSourcePort (m_endPoint->GetLocalPort());
-      header.SetDestinationPort (m_defaultPort);
+      header.SetDestinationPort (m_remotePort);
       if (m_shutdownSend)
         {
           m_errno = ERROR_SHUTDOWN;
@@ -845,7 +853,7 @@
       NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
       m_tcp->SendPacket (p, header,
                          m_endPoint->GetLocalAddress (),
-                         m_defaultAddress);
+                         m_remoteAddress);
       m_rtt->SentSeq(m_nextTxSequence, sz);       // notify the RTT
       // Notify the application
       Simulator::ScheduleNow(&TcpSocket::NotifyDataSent, this, p->GetSize ());
@@ -896,7 +904,15 @@
 {
   NS_LOG_FUNCTION;
   NS_LOG_PARAMS (this << p << "tcpHeader " << fromAddress);
-  NS_LOG_LOGIC ("TcpSocket " << this << " NewRx, p.size is " << p->GetSize () );
+  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)
@@ -918,7 +934,7 @@
       m_nextRxSequence += s;           // Advance next expected sequence
       //bytesReceived += s;       // Statistics
       NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
-	  NotifyDataReceived (p, fromAddress);
+      NotifyDataReceived (p, fromAddress);
       if (m_closeNotified)
         {
           NS_LOG_LOGIC ("Tcp " << this << " HuH?  Got data after closeNotif");
@@ -1046,6 +1062,11 @@
   SendPendingData();
 }
 
+Ptr<TcpSocket> TcpSocket::Copy ()
+{
+  return CreateObject<TcpSocket> (*this);
+}
+
 void TcpSocket::NewAck (SequenceNumber seq)
 { // New acknowledgement up to sequence number "seq"
   // Adjust congestion window in response to new ack's received
@@ -1179,12 +1200,12 @@
   tcpHeader.SetSequenceNumber (m_nextTxSequence);
   tcpHeader.SetAckNumber (m_nextRxSequence);
   tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
-  tcpHeader.SetDestinationPort (m_defaultPort);
+  tcpHeader.SetDestinationPort (m_remotePort);
   tcpHeader.SetFlags (flags);
   tcpHeader.SetWindowSize (m_advertisedWindowSize);
 
   m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
-    m_defaultAddress);
+    m_remoteAddress);
 }
 
 }//namespace ns3
--- a/src/internet-node/tcp-socket.h	Wed Mar 12 11:55:08 2008 -0400
+++ b/src/internet-node/tcp-socket.h	Wed Mar 12 14:52:29 2008 -0400
@@ -80,7 +80,9 @@
                                        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
@@ -90,6 +92,7 @@
   // 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); 
@@ -106,8 +109,8 @@
   Ipv4EndPoint *m_endPoint;
   Ptr<Node> m_node;
   Ptr<TcpL4Protocol> m_tcp;
-  Ipv4Address m_defaultAddress;
-  uint16_t m_defaultPort;
+  Ipv4Address m_remoteAddress;
+  uint16_t m_remotePort;
   //these two are so that the socket/endpoint cloning works
   Ipv4Address m_localAddress;
   uint16_t m_localPort;