1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2007 Georgia Tech Research Corporation
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Author: Raj Bhattacharjea <raj.b@gatech.edu>
23 #include "ns3/inet-socket-address.h"
26 #include "tcp-socket.h"
27 #include "tcp-l4-protocol.h"
28 #include "ipv4-end-point.h"
29 #include "ipv4-l4-demux.h"
30 #include "ns3/simulation-singleton.h"
31 #include "tcp-typedefs.h"
32 #include "ns3/simulator.h"
33 #include "ns3/packet.h"
37 NS_LOG_COMPONENT_DEFINE ("TcpSocket");
43 TcpSocket::TcpSocket ()
44 : m_skipRetxResched (false),
49 m_errno (ERROR_NOTERROR),
50 m_shutdownSend (false),
51 m_shutdownRecv (false),
54 m_closeNotified (false),
55 m_closeRequestNotified (false),
56 m_closeOnEmpty (false),
57 m_pendingClose (false),
65 m_lastMeasuredRtt (Seconds(0.0))
72 TcpSocket::TcpSocket(const TcpSocket& sock)
73 : Socket(sock), //copy the base class callbacks
74 m_skipRetxResched (sock.m_skipRetxResched),
75 m_dupAckCount (sock.m_dupAckCount),
79 m_remoteAddress (sock.m_remoteAddress),
80 m_remotePort (sock.m_remotePort),
81 m_localAddress (sock.m_localAddress),
82 m_localPort (sock.m_localPort),
83 m_errno (sock.m_errno),
84 m_shutdownSend (sock.m_shutdownSend),
85 m_shutdownRecv (sock.m_shutdownRecv),
86 m_connected (sock.m_connected),
87 m_state (sock.m_state),
88 m_closeNotified (sock.m_closeNotified),
89 m_closeRequestNotified (sock.m_closeRequestNotified),
90 m_closeOnEmpty (sock.m_closeOnEmpty),
91 m_pendingClose (sock.m_pendingClose),
92 m_nextTxSequence (sock.m_nextTxSequence),
93 m_highTxMark (sock.m_highTxMark),
94 m_highestRxAck (sock.m_highestRxAck),
95 m_lastRxAck (sock.m_lastRxAck),
96 m_nextRxSequence (sock.m_nextRxSequence),
98 m_segmentSize (sock.m_segmentSize),
99 m_rxWindowSize (sock.m_rxWindowSize),
100 m_advertisedWindowSize (sock.m_advertisedWindowSize),
101 m_cWnd (sock.m_cWnd),
102 m_ssThresh (sock.m_ssThresh),
103 m_initialCWnd (sock.m_initialCWnd),
105 m_lastMeasuredRtt (Seconds(0.0)),
106 m_cnTimeout (sock.m_cnTimeout),
107 m_cnCount (sock.m_cnCount)
110 NS_LOG_LOGIC("Invoked the copy constructor");
111 //copy the pending data if necessary
112 if(sock.m_pendingData)
114 m_pendingData = sock.m_pendingData->Copy();
116 //copy the rtt if necessary
119 m_rtt = sock.m_rtt->Copy();
121 //can't "copy" the endpoint just yes, must do this when we know the peer info
122 //too; this is in SYN_ACK_TX
125 TcpSocket::~TcpSocket ()
132 NS_ASSERT (m_tcp != 0);
134 * Note that this piece of code is a bit tricky:
135 * when DeAllocate is called, it will call into
136 * Ipv4EndPointDemux::Deallocate which triggers
137 * a delete of the associated endPoint which triggers
138 * in turn a call to the method ::Destroy below
139 * will will zero the m_endPoint field.
141 NS_ASSERT (m_endPoint != 0);
142 m_tcp->DeAllocate (m_endPoint);
143 NS_ASSERT (m_endPoint == 0);
146 delete m_pendingData; //prevents leak
151 TcpSocket::SetNode (Ptr<Node> node)
154 Ptr<Tcp> t = node->GetObject<Tcp> ();
155 m_segmentSize = t->GetDefaultSegSize ();
156 m_rxWindowSize = t->GetDefaultAdvWin ();
157 m_advertisedWindowSize = t->GetDefaultAdvWin ();
158 m_cWnd = t->GetDefaultInitialCwnd () * m_segmentSize;
159 m_ssThresh = t->GetDefaultSsThresh ();
160 m_initialCWnd = t->GetDefaultInitialCwnd ();
161 m_cnTimeout = Seconds (t->GetDefaultConnTimeout ());
162 m_cnCount = t->GetDefaultConnCount ();
166 TcpSocket::SetTcp (Ptr<TcpL4Protocol> tcp)
171 TcpSocket::SetRtt (Ptr<RttEstimator> rtt)
177 enum Socket::SocketErrno
178 TcpSocket::GetErrno (void) const
185 TcpSocket::GetNode (void) const
192 TcpSocket::Destroy (void)
198 m_retxEvent.Cancel ();
201 TcpSocket::FinishBind (void)
208 m_endPoint->SetRxCallback (MakeCallback (&TcpSocket::ForwardUp, Ptr<TcpSocket>(this)));
209 m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, Ptr<TcpSocket>(this)));
210 m_localAddress = m_endPoint->GetLocalAddress ();
211 m_localPort = m_endPoint->GetLocalPort ();
216 TcpSocket::Bind (void)
219 m_endPoint = m_tcp->Allocate ();
220 return FinishBind ();
223 TcpSocket::Bind (const Address &address)
226 NS_LOG_PARAMS (this<<address);
227 if (!InetSocketAddress::IsMatchingType (address))
231 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
232 Ipv4Address ipv4 = transport.GetIpv4 ();
233 uint16_t port = transport.GetPort ();
234 if (ipv4 == Ipv4Address::GetAny () && port == 0)
236 m_endPoint = m_tcp->Allocate ();
237 NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
239 else if (ipv4 == Ipv4Address::GetAny () && port != 0)
241 m_endPoint = m_tcp->Allocate (port);
242 NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
244 else if (ipv4 != Ipv4Address::GetAny () && port == 0)
246 m_endPoint = m_tcp->Allocate (ipv4);
247 NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
249 else if (ipv4 != Ipv4Address::GetAny () && port != 0)
251 m_endPoint = m_tcp->Allocate (ipv4, port);
252 NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
255 return FinishBind ();
259 TcpSocket::ShutdownSend (void)
262 m_shutdownSend = true;
266 TcpSocket::ShutdownRecv (void)
269 m_shutdownRecv = false;
274 TcpSocket::Close (void)
277 if (m_state == CLOSED)
281 if (m_pendingData && m_pendingData->Size() != 0)
282 { // App close with pending data must wait until all data transmitted
283 m_closeOnEmpty = true;
284 NS_LOG_LOGIC("Socket " << this <<
285 " deferring close, state " << m_state);
289 Actions_t action = ProcessEvent (APP_CLOSE);
290 ProcessAction (action);
296 TcpSocket::Connect (const Address & address)
299 NS_LOG_PARAMS (this << address);
304 NS_ASSERT (m_endPoint == 0);
307 NS_ASSERT (m_endPoint != 0);
309 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
310 m_remoteAddress = transport.GetIpv4 ();
311 m_remotePort = transport.GetPort ();
313 uint32_t localIfIndex;
314 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
316 if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
318 m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
322 m_errno = ERROR_NOROUTETOHOST;
326 Actions_t action = ProcessEvent (APP_CONNECT);
327 bool success = ProcessAction (action);
335 TcpSocket::Send (const Ptr<Packet> p) //p here is just data, no headers
336 { // TCP Does not deal with packets from app, just data
337 return Send(p->PeekData(), p->GetSize());
340 int TcpSocket::Send (const uint8_t* buf, uint32_t size)
343 NS_LOG_PARAMS (this << buf << size);
344 if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
345 { // Ok to buffer some data to send
348 m_pendingData = new PendingData (); // Create if non-existent
349 m_firstPendingSequence = m_nextTxSequence; // Note seq of first
351 //PendingData::Add always copies the data buffer, never modifies
352 m_pendingData->Add (size,buf);
353 NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() <<
354 " state " << m_state);
355 Actions_t action = ProcessEvent (APP_SEND);
356 NS_LOG_DEBUG(" action " << action);
357 if (!ProcessAction (action))
359 return -1; // Failed, return zero
365 m_errno = ERROR_NOTCONN;
370 int TcpSocket::DoSendTo (Ptr<Packet> p, const Address &address)
373 NS_LOG_PARAMS (this << p << address);
374 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
375 Ipv4Address ipv4 = transport.GetIpv4 ();
376 uint16_t port = transport.GetPort ();
377 return DoSendTo (p, ipv4, port);
380 int TcpSocket::DoSendTo (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port)
383 NS_LOG_PARAMS (this << p << ipv4 << port);
388 NS_ASSERT (m_endPoint == 0);
391 NS_ASSERT (m_endPoint != 0);
395 m_errno = ERROR_SHUTDOWN;
398 m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv4,
399 m_endPoint->GetLocalPort (), port);
400 NotifyDataSent (p->GetSize ());
405 TcpSocket::SendTo (const Address &address, Ptr<Packet> p)
408 NS_LOG_PARAMS (this << address << p);
411 m_errno = ERROR_NOTCONN;
416 return Send (p); //drop the address according to BSD manpages
421 TcpSocket::Listen (uint32_t q)
424 NS_LOG_PARAMS (this << q);
425 Actions_t action = ProcessEvent (APP_LISTEN);
426 ProcessAction (action);
431 TcpSocket::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
433 NS_LOG_DEBUG("Socket " << this << " got forward up" <<
434 " dport " << m_endPoint->GetLocalPort() <<
435 " daddr " << m_endPoint->GetLocalAddress() <<
436 " sport " << m_endPoint->GetPeerPort() <<
437 " saddr " << m_endPoint->GetPeerAddress());
440 NS_LOG_PARAMS (this << packet << ipv4 << port);
446 packet->RemoveHeader (tcpHeader);
448 if (tcpHeader.GetFlags () & TcpHeader::ACK)
450 Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
451 if (m != Seconds (0.0))
453 m_lastMeasuredRtt = m;
457 Events_t event = SimulationSingleton<TcpStateMachine>::Get ()->FlagsEvent (tcpHeader.GetFlags () );
458 Actions_t action = ProcessEvent (event); //updates the state
459 Address address = InetSocketAddress (ipv4, port);
460 NS_LOG_DEBUG("Socket " << this <<
461 " processing pkt action, " << action <<
462 " current state " << m_state);
463 ProcessPacketAction (action, packet, tcpHeader, address);
466 Actions_t TcpSocket::ProcessEvent (Events_t e)
469 NS_LOG_PARAMS (this << e);
470 States_t saveState = m_state;
471 NS_LOG_LOGIC ("TcpSocket " << this << " processing event " << e);
472 // simulation singleton is a way to get a single global static instance of a
473 // class intended to be a singleton; see simulation-singleton.h
474 SA stateAction = SimulationSingleton<TcpStateMachine>::Get ()->Lookup (m_state,e);
476 if (stateAction.action == RST_TX)
478 NS_LOG_LOGIC ("TcpSocket " << this << " sending RST from state "
479 << saveState << " event " << e);
481 bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED
483 m_state = stateAction.state;
484 NS_LOG_LOGIC ("TcpSocket " << this << " moved from state " << saveState
485 << " to state " <<m_state);
486 NS_LOG_LOGIC ("TcpSocket " << this << " pendingData " << m_pendingData);
488 //extra event logic is here for RX events
490 if (saveState == SYN_SENT && m_state == ESTABLISHED)
491 // this means the application side has completed its portion of
494 Simulator::ScheduleNow(&TcpSocket::ConnectionSucceeded, this);
495 //NotifyConnectionSucceeded ();
497 m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
498 NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
501 if (needCloseNotify && !m_closeNotified)
503 NS_LOG_LOGIC ("TcpSocket " << this << " transition to CLOSED from "
504 << m_state << " event " << e << " closeNot " << m_closeNotified
505 << " action " << stateAction.action);
506 NotifyCloseCompleted ();
507 m_closeNotified = true;
508 NS_LOG_LOGIC ("TcpSocket " << this << " calling Closed from PE"
509 << " origState " << saveState
511 NS_LOG_LOGIC ("TcpSocket " << this << " transition to CLOSED from "
512 << m_state << " event " << e
513 << " set CloseNotif ");
515 return stateAction.action;
518 void TcpSocket::SendEmptyPacket (uint8_t flags)
521 NS_LOG_PARAMS (this << flags);
522 Ptr<Packet> p = Create<Packet> ();
525 header.SetFlags (flags);
526 header.SetSequenceNumber (m_nextTxSequence);
527 header.SetAckNumber (m_nextRxSequence);
528 header.SetSourcePort (m_endPoint->GetLocalPort ());
529 header.SetDestinationPort (m_remotePort);
530 header.SetWindowSize (m_advertisedWindowSize);
531 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
533 Time rto = m_rtt->RetransmitTimeout ();
534 if (flags & TcpHeader::SYN)
537 m_cnTimeout = m_cnTimeout + m_cnTimeout;
540 if (m_retxEvent.IsExpired () ) //no outstanding timer
542 NS_LOG_LOGIC ("Schedule retransmission timeout at time "
543 << Simulator::Now ().GetSeconds () << " to expire at time "
544 << (Simulator::Now () + rto).GetSeconds ());
545 m_retxEvent = Simulator::Schedule (rto, &TcpSocket::ReTxTimeout, this);
549 bool TcpSocket::ProcessAction (Actions_t a)
550 { // These actions do not require a packet or any TCP Headers
552 NS_LOG_PARAMS (this << a);
556 NS_LOG_LOGIC ("TcpSocket " << this <<" Action: NO_ACT");
559 SendEmptyPacket (TcpHeader::ACK);
562 NS_ASSERT (false); // This should be processed in ProcessPacketAction
565 NS_LOG_LOGIC ("TcpSocket " << this <<" Action RST_TX");
566 SendEmptyPacket (TcpHeader::RST);
569 NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_TX");
570 // TCP SYN Flag consumes one byte
571 // is the above correct? we're SENDING a syn, not acking back -- Raj
572 // commented out for now
573 // m_nextTxSequence+= 1;
574 SendEmptyPacket (TcpHeader::SYN);
577 NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
578 // TCP SYN Flag consumes one byte
580 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
583 NS_LOG_LOGIC ("TcpSocket " << this <<" Action FIN_TX");
584 SendEmptyPacket (TcpHeader::FIN);
587 NS_LOG_LOGIC ("TcpSocket " << this <<" Action FIN_ACK_TX");
588 SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
591 NS_ASSERT (false); // This should be processed in ProcessPacketAction
594 NS_ASSERT (false); // This should be processed in ProcessPacketAction
597 NS_LOG_LOGIC ("TcpSocket " << this <<" Action RETX");
600 NS_LOG_LOGIC ("TcpSocket " << this <<" Action TX_DATA");
604 NS_ASSERT (false); // This should be processed in ProcessPacketAction
605 NS_LOG_LOGIC ("TcpSocket " << this <<" Action PEER_CLOSE");
608 NS_LOG_LOGIC ("TcpSocket " << this <<" Action APP_CLOSED");
611 NS_LOG_LOGIC ("TcpSocket " << this <<" Action CANCEL_TM");
614 NS_LOG_LOGIC ("TcpSocket " << this <<" Action APP_NOTIFY");
617 NS_ASSERT (false); // This should be processed in ProcessPacketAction
620 NS_LOG_LOGIC ("TcpSocket " << this <<" Action LAST_ACTION");
626 bool TcpSocket::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
627 const TcpHeader& tcpHeader,
628 const Address& fromAddress)
631 NS_LOG_PARAMS (this << a << p << fromAddress);
632 uint32_t localIfIndex;
633 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
637 NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
638 // m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
639 // m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
640 // if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
642 // m_localAddress = ipv4->GetAddress (localIfIndex);
644 if (m_state == LISTEN) //this means we should fork a new TcpSocket
646 NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this);
647 //notify the server that we got a SYN
648 // If server refuses connection do nothing
649 if (!NotifyConnectionRequest(fromAddress)) return true;
651 Ptr<TcpSocket> newSock = Copy ();
652 NS_LOG_LOGIC ("Cloned a TcpSocket " << newSock);
653 //this listening socket should do nothing more
654 Simulator::ScheduleNow (&TcpSocket::CompleteFork, newSock,
655 p, tcpHeader,fromAddress);
658 // This is the cloned endpoint
659 m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
660 if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
662 m_localAddress = ipv4->GetAddress (localIfIndex);
663 m_endPoint->SetLocalAddress (m_localAddress);
664 // Leave local addr in the portmap to any, as the path from
665 // remote can change and packets can arrive on different interfaces
666 //m_endPoint->SetLocalAddress (Ipv4Address::GetAny());
668 // TCP SYN consumes one byte
669 m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
670 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
673 NS_LOG_LOGIC ("TcpSocket " << this <<" Action ACK_TX_1");
674 // TCP SYN consumes one byte
675 m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
676 NS_LOG_DEBUG ("TcpSocket " << this << " ACK_TX_1" <<
677 " nextRxSeq " << m_nextRxSequence);
678 SendEmptyPacket (TcpHeader::ACK);
679 m_rxWindowSize = tcpHeader.GetWindowSize ();
680 m_nextTxSequence = tcpHeader.GetAckNumber ();
681 if (tcpHeader.GetAckNumber () > m_highestRxAck)
683 m_highestRxAck = tcpHeader.GetAckNumber ();
688 NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_ACK_TX");
689 if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing
693 if (tcpHeader.GetAckNumber () == m_highestRxAck &&
694 tcpHeader.GetAckNumber () < m_nextTxSequence)
696 DupAck (tcpHeader, ++m_dupAckCount);
699 if (tcpHeader.GetAckNumber () > m_highestRxAck)
703 NewAck (tcpHeader.GetAckNumber ());
706 NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_SEQ_RX");
707 NewRx (p, tcpHeader, fromAddress); // Process new data received
711 // First we have to be sure the FIN packet was not received
712 // out of sequence. If so, note pending close and process
714 if (tcpHeader.GetSequenceNumber () != m_nextRxSequence)
715 { // process close later
716 m_pendingClose = true;
717 NS_LOG_LOGIC ("TcpSocket " << this << " setting pendingClose"
718 << " rxseq " << tcpHeader.GetSequenceNumber ()
719 << " nextRxSeq " << m_nextRxSequence);
720 NewRx (p, tcpHeader, fromAddress);
723 // Now we need to see if any data came with the FIN
725 if (p->GetSize () != 0)
727 NewRx (p, tcpHeader, fromAddress);
729 States_t saveState = m_state; // Used to see if app responds
730 NS_LOG_LOGIC ("TcpSocket " << this
731 << " peer close, state " << m_state);
732 if (!m_closeRequestNotified)
734 NS_LOG_LOGIC ("TCP " << this
735 << " calling AppCloseRequest");
737 m_closeRequestNotified = true;
739 NS_LOG_LOGIC ("TcpSocket " << this
740 << " peer close, state after " << m_state);
741 if (m_state == saveState)
742 { // Need to ack, the application will close later
743 SendEmptyPacket (TcpHeader::ACK);
744 // Also need to re-tx the ack if we
746 if (m_state == LAST_ACK)
748 NS_LOG_LOGIC ("TcpSocket " << this << " scheduling LATO1");
749 m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
750 &TcpSocket::LastAckTimeout,this);
755 NS_LOG_LOGIC ("TcpSocket " << this <<" Action SERV_NOTIFY");
756 NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
757 NotifyNewConnectionCreated (this, fromAddress);
758 m_connected = true; // ! This is bogus; fix when we clone the tcp
759 m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
760 //treat the connection orientation final ack as a newack
761 CommonNewAck (tcpHeader.GetAckNumber (), true);
769 void TcpSocket::CompleteFork(Ptr<Packet> p, const TcpHeader& h, const Address& fromAddress)
771 // Get port and address from peer (connecting host)
772 m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
773 m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
774 m_endPoint = m_tcp->Allocate (m_localAddress,
778 //the cloned socket with be in listen state, so manually change state
780 //equivalent to FinishBind
781 m_endPoint->SetRxCallback (MakeCallback (&TcpSocket::ForwardUp, Ptr<TcpSocket>(this)));
782 m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, Ptr<TcpSocket>(this)));
783 ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress);
786 void TcpSocket::ConnectionSucceeded()
787 { // We would preferred to have scheduled an event directly to
788 // NotifyConnectionSucceeded, but (sigh) these are protected
789 // and we can get the address of it :(
790 NotifyConnectionSucceeded();
793 bool TcpSocket::SendPendingData (bool withAck)
796 NS_LOG_PARAMS (this << withAck);
797 NS_LOG_LOGIC ("ENTERING SendPendingData");
800 return false; // No data exists
802 uint32_t nPacketsSent = 0;
803 while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence))
805 uint32_t w = AvailableWindow ();// Get available window size
806 NS_LOG_LOGIC ("TcpSocket " << this << " SendPendingData"
808 << " rxwin " << m_rxWindowSize
809 << " cWnd " << m_cWnd
810 << " segsize " << m_segmentSize
811 << " nextTxSeq " << m_nextTxSequence
812 << " highestRxAck " << m_highestRxAck
813 << " pd->Size " << m_pendingData->Size ()
814 << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence));
816 if (w < m_segmentSize && m_pendingData->Size () > w)
820 uint32_t s = std::min (w, m_segmentSize); // Send no more than window
821 Ptr<Packet> p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence,
823 NS_LOG_LOGIC("TcpSocket " << this << " sendPendingData"
824 << " txseq " << m_nextTxSequence
826 << " datasize " << p->GetSize() );
830 flags |= TcpHeader::ACK;
832 uint32_t sz = p->GetSize (); // Size of packet
833 uint32_t remainingData = m_pendingData->SizeFromSeq(
834 m_firstPendingSequence,
835 m_nextTxSequence + SequenceNumber (sz));
836 if (m_closeOnEmpty && (remainingData == 0))
838 flags = TcpHeader::FIN;
839 m_state = FIN_WAIT_1;
843 header.SetFlags (flags);
844 header.SetSequenceNumber (m_nextTxSequence);
845 header.SetAckNumber (m_nextRxSequence);
846 header.SetSourcePort (m_endPoint->GetLocalPort());
847 header.SetDestinationPort (m_remotePort);
850 m_errno = ERROR_SHUTDOWN;
854 Time rto = m_rtt->RetransmitTimeout ();
855 if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
857 NS_LOG_LOGIC ("Schedule retransmission timeout at time " <<
858 Simulator::Now ().GetSeconds () << " to expire at time " <<
859 (Simulator::Now () + rto).GetSeconds () );
860 m_retxEvent = Simulator::Schedule (rto,&TcpSocket::ReTxTimeout,this);
862 NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
863 m_tcp->SendPacket (p, header,
864 m_endPoint->GetLocalAddress (),
866 m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT
867 // Notify the application
868 Simulator::ScheduleNow(&TcpSocket::NotifyDataSent, this, p->GetSize ());
869 nPacketsSent++; // Count sent this loop
870 m_nextTxSequence += sz; // Advance next tx sequence
871 // Note the high water mark
872 m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
874 NS_LOG_LOGIC ("Sent "<<nPacketsSent<<" packets");
875 NS_LOG_LOGIC("RETURN SendPendingData");
876 return (nPacketsSent>0);
879 uint32_t TcpSocket::UnAckDataCount ()
882 return m_nextTxSequence - m_highestRxAck;
885 uint32_t TcpSocket::BytesInFlight ()
888 return m_highTxMark - m_highestRxAck;
891 uint32_t TcpSocket::Window ()
894 NS_LOG_LOGIC ("TcpSocket::Window() "<<this);
895 return std::min (m_rxWindowSize, m_cWnd);
898 uint32_t TcpSocket::AvailableWindow ()
901 uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
902 uint32_t win = Window ();
905 return 0; // No space available
907 return (win - unack); // Amount of window space available
910 void TcpSocket::NewRx (Ptr<Packet> p,
911 const TcpHeader& tcpHeader,
912 const Address& fromAddress)
915 NS_LOG_PARAMS (this << p << "tcpHeader " << fromAddress);
916 NS_LOG_LOGIC ("TcpSocket " << this << " NewRx,"
917 << " seq " << tcpHeader.GetSequenceNumber()
918 << " ack " << tcpHeader.GetAckNumber()
919 << " p.size is " << p->GetSize () );
920 NS_LOG_DEBUG ("TcpSocket " << this <<
922 " seq " << tcpHeader.GetSequenceNumber() <<
923 " ack " << tcpHeader.GetAckNumber() <<
924 " p.size is " << p->GetSize());
925 States_t origState = m_state;
926 uint32_t s = p->GetSize (); // Size of associated data
928 {// Nothing to do if no associated data
931 // Log sequence received if enabled
932 // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber);
933 // Three possibilities
934 // 1) Received seq is expected, deliver this and any buffered data
935 // 2) Received seq is < expected, just re-ack previous
936 // 3) Received seq is > expected, just re-ack previous and buffer data
937 if (tcpHeader.GetSequenceNumber () == m_nextRxSequence)
938 { // If seq is expected seq
939 // 1) Update nextRxSeq
940 // 2) Deliver to application this packet
941 // 3) See if any buffered can be delivered
943 m_nextRxSequence += s; // Advance next expected sequence
944 //bytesReceived += s; // Statistics
945 NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
946 NotifyDataReceived (p, fromAddress);
949 NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif");
951 NS_LOG_LOGIC ("TcpSocket " << this << " adv rxseq by " << s);
952 // Look for buffered data
953 UnAckData_t::iterator i;
954 // Note that the bufferedData list DOES contain the tcp header
955 while (!m_bufferedData.empty ())
956 { // Check the buffered data for delivery
957 NS_LOG_LOGIC("TCP " << this << " bufferedData.size() "
958 << m_bufferedData.size ()
959 << " time " << Simulator::Now ());
960 i = m_bufferedData.begin ();
961 Ptr<Packet> p1 = i->second;
962 SequenceNumber s1 = 0;
963 if (i->first > m_nextRxSequence)
965 break; // Not next expected
967 // already have the header as a param
968 //TCPHeader* h = dynamic_cast<TCPHeader*>(p1->PopPDU());
969 // Check non-null here...
970 uint8_t flags = tcpHeader.GetFlags (); // Flags (used below)
971 if (i->first < m_nextRxSequence)
972 { // remove already delivered data
974 // 1) seq + length <= nextRxSeq, just discard
975 // 2) seq + length > nextRxSeq, can deliver partial
977 if (i->first + s1 < m_nextRxSequence)
978 { // Just remove from list
979 //bufferedData.erase(i);
980 p1 = 0; // Nothing to deliver
983 { // Remove partial data to prepare for delivery
984 uint32_t dup = m_nextRxSequence - i->first;
985 i->second = p1->CreateFragment (0, p1->GetSize () - dup);
990 { // At this point i->first must equal nextRxSeq
991 if (i->first != m_nextRxSequence)
993 NS_FATAL_ERROR ("HuH? NexRx failure, first "
994 << i->first << " nextRxSeq " << m_nextRxSequence);
998 NotifyDataReceived (p1, fromAddress);
1000 NS_LOG_LOGIC ("TcpSocket " << this << " adv rxseq1 by " << s1 );
1001 m_nextRxSequence += s1; // Note data received
1002 m_bufferedData.erase (i); // Remove from list
1003 if (flags & TcpHeader::FIN)
1004 NS_LOG_LOGIC("TcpSocket " << this
1005 << " found FIN in buffered");
1008 if (m_pendingClose || (origState > ESTABLISHED))
1009 { // See if we can close now
1010 if (m_bufferedData.empty())
1012 ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress);
1016 else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence)
1017 { // Need to buffer this one
1018 NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () );
1019 UnAckData_t::iterator i =
1020 m_bufferedData.find (tcpHeader.GetSequenceNumber () );
1021 if (i != m_bufferedData.end () )
1023 i->second = 0; // relase reference to already buffered
1025 // Save for later delivery
1026 m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;
1030 NS_LOG_LOGIC("TCP " << this
1031 << " got seq " << tcpHeader.GetSequenceNumber ()
1032 << " expected " << m_nextRxSequence
1033 << " flags " << tcpHeader.GetFlags ());
1035 // Now send a new ack packet acknowledging all received and delivered data
1036 SendEmptyPacket (TcpHeader::ACK);
1040 void TcpSocket::CommonNewAck (SequenceNumber ack, bool skipTimer)
1041 { // CommonNewAck is called only for "New" (non-duplicate) acks
1042 // and MUST be called by any subclass, from the NewAck function
1043 // Always cancel any pending re-tx timer on new acknowledgement
1045 NS_LOG_PARAMS (this << ack << skipTimer);
1046 //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
1049 m_retxEvent.Cancel ();
1051 NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack
1052 << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed
1053 m_highestRxAck = ack; // Note the highest recieved Ack
1054 if (ack > m_nextTxSequence)
1056 m_nextTxSequence = ack; // If advanced
1058 // See if all pending ack'ed; if so we can delete the data
1060 { // Data exists, see if can be deleted
1061 if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0)
1062 { // All pending acked, can be deleted
1063 m_pendingData->Clear ();
1064 delete m_pendingData;
1066 // Insure no re-tx timer
1067 m_retxEvent.Cancel ();
1070 // Try to send more data
1074 Ptr<TcpSocket> TcpSocket::Copy ()
1076 return CopyObject<TcpSocket> (this);
1079 void TcpSocket::NewAck (SequenceNumber seq)
1080 { // New acknowledgement up to sequence number "seq"
1081 // Adjust congestion window in response to new ack's received
1083 NS_LOG_PARAMS (this << seq);
1084 NS_LOG_LOGIC ("TcpSocket " << this << " NewAck "
1086 << " cWnd " << m_cWnd
1087 << " ssThresh " << m_ssThresh);
1088 if (m_cWnd < m_ssThresh)
1089 { // Slow start mode, add one segSize to cWnd
1090 m_cWnd += m_segmentSize;
1091 NS_LOG_LOGIC ("TcpSocket " << this << " NewCWnd SlowStart, cWnd " << m_cWnd
1092 << " sst " << m_ssThresh);
1095 { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd
1096 double adder = ((double) m_segmentSize * m_segmentSize) / m_cWnd;
1101 m_cWnd += (uint32_t) adder;
1102 NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd
1103 << " sst " << m_ssThresh);
1105 CommonNewAck (seq, false); // Complete newAck processing
1108 void TcpSocket::DupAck (const TcpHeader& t, uint32_t count)
1111 NS_LOG_PARAMS (this << "t " << count);
1112 NS_LOG_LOGIC ("TcpSocket " << this << " DupAck " << t.GetAckNumber ()
1113 << ", count " << count
1114 << ", time " << Simulator::Now ());
1116 { // Count of three indicates triple duplicate ack
1117 m_ssThresh = Window () / 2; // Per RFC2581
1118 m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
1119 NS_LOG_LOGIC("TcpSocket " << this << "Tahoe TDA, time " << Simulator::Now ()
1120 << " seq " << t.GetAckNumber ()
1121 << " in flight " << BytesInFlight ()
1122 << " new ssthresh " << m_ssThresh);
1124 m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart)
1125 // For Tahoe, we also reset nextTxSeq
1126 m_nextTxSequence = m_highestRxAck;
1131 void TcpSocket::ReTxTimeout ()
1132 { // Retransmit timeout
1134 NS_LOG_PARAMS (this);
1135 m_ssThresh = Window () / 2; // Per RFC2581
1136 m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
1137 // Set cWnd to segSize on timeout, per rfc2581
1138 // Collapse congestion window (re-enter slowstart)
1139 m_cWnd = m_segmentSize;
1140 m_nextTxSequence = m_highestRxAck; // Start from highest Ack
1141 m_rtt->IncreaseMultiplier (); // Double timeout value for next retx timer
1142 Retransmit (); // Retransmit the packet
1145 void TcpSocket::LastAckTimeout ()
1147 m_lastAckEvent.Cancel ();
1148 if (m_state == LAST_ACK)
1150 Actions_t action = ProcessEvent (TIMEOUT);
1151 ProcessAction (action);
1153 if (!m_closeNotified)
1155 m_closeNotified = true;
1159 void TcpSocket::Retransmit ()
1162 NS_LOG_PARAMS (this);
1163 uint8_t flags = TcpHeader::NONE;
1164 if (m_state == SYN_SENT)
1168 SendEmptyPacket (TcpHeader::SYN);
1173 NotifyConnectionFailed ();
1179 if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2)
1180 { // Must have lost FIN, re-send
1181 SendEmptyPacket (TcpHeader::FIN);
1185 Ptr<Packet> p = m_pendingData->CopyFromSeq (m_segmentSize,
1186 m_firstPendingSequence,
1188 // Calculate remaining data for COE check
1189 uint32_t remainingData = m_pendingData->SizeFromSeq (
1190 m_firstPendingSequence,
1191 m_nextTxSequence + SequenceNumber(p->GetSize ()));
1192 if (m_closeOnEmpty && remainingData == 0)
1193 { // Add the FIN flag
1194 flags = flags | TcpHeader::FIN;
1197 NS_LOG_LOGIC ("TcpSocket " << this << " retxing seq " << m_highestRxAck);
1198 if (m_retxEvent.IsExpired () )
1200 Time rto = m_rtt->RetransmitTimeout ();
1201 NS_LOG_LOGIC ("Schedule retransmission timeout at time "
1202 << Simulator::Now ().GetSeconds () << " to expire at time "
1203 << (Simulator::Now () + rto).GetSeconds ());
1204 m_retxEvent = Simulator::Schedule (rto,&TcpSocket::ReTxTimeout,this);
1206 m_rtt->SentSeq (m_highestRxAck,p->GetSize ());
1207 // And send the packet
1208 TcpHeader tcpHeader;
1209 tcpHeader.SetSequenceNumber (m_nextTxSequence);
1210 tcpHeader.SetAckNumber (m_nextRxSequence);
1211 tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
1212 tcpHeader.SetDestinationPort (m_remotePort);
1213 tcpHeader.SetFlags (flags);
1214 tcpHeader.SetWindowSize (m_advertisedWindowSize);
1216 m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),