A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
tcp-socket-base.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 Georgia Tech Research Corporation
4  * Copyright (c) 2010 Adrian Sai-wah Tam
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
20  */
21 
22 #define NS_LOG_APPEND_CONTEXT \
23  if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
24 
25 #include "ns3/abort.h"
26 #include "ns3/node.h"
27 #include "ns3/inet-socket-address.h"
28 #include "ns3/inet6-socket-address.h"
29 #include "ns3/log.h"
30 #include "ns3/ipv4.h"
31 #include "ns3/ipv6.h"
32 #include "ns3/ipv4-interface-address.h"
33 #include "ns3/ipv4-route.h"
34 #include "ns3/ipv6-route.h"
35 #include "ns3/ipv4-routing-protocol.h"
36 #include "ns3/ipv6-routing-protocol.h"
37 #include "ns3/simulation-singleton.h"
38 #include "ns3/simulator.h"
39 #include "ns3/packet.h"
40 #include "ns3/uinteger.h"
41 #include "ns3/double.h"
42 #include "ns3/trace-source-accessor.h"
43 #include "tcp-socket-base.h"
44 #include "tcp-l4-protocol.h"
45 #include "ipv4-end-point.h"
46 #include "ipv6-end-point.h"
47 #include "ipv6-l3-protocol.h"
48 #include "tcp-header.h"
49 #include "rtt-estimator.h"
50 
51 #include <algorithm>
52 
53 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
54 
55 namespace ns3 {
56 
57 NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
58 
59 TypeId
61 {
62  static TypeId tid = TypeId ("ns3::TcpSocketBase")
63  .SetParent<TcpSocket> ()
64 // .AddAttribute ("TcpState", "State in TCP state machine",
65 // TypeId::ATTR_GET,
66 // EnumValue (CLOSED),
67 // MakeEnumAccessor (&TcpSocketBase::m_state),
68 // MakeEnumChecker (CLOSED, "Closed"))
69  .AddAttribute ("MaxSegLifetime",
70  "Maximum segment lifetime in seconds, use for TIME_WAIT state transition to CLOSED state",
71  DoubleValue (120), /* RFC793 says MSL=2 minutes*/
72  MakeDoubleAccessor (&TcpSocketBase::m_msl),
73  MakeDoubleChecker<double> (0))
74  .AddAttribute ("MaxWindowSize", "Max size of advertised window",
75  UintegerValue (65535),
76  MakeUintegerAccessor (&TcpSocketBase::m_maxWinSize),
77  MakeUintegerChecker<uint16_t> ())
78  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
79  CallbackValue (),
80  MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback),
81  MakeCallbackChecker ())
82  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
83  CallbackValue (),
84  MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback6),
85  MakeCallbackChecker ())
86  .AddTraceSource ("RTO",
87  "Retransmission timeout",
89  .AddTraceSource ("RTT",
90  "Last RTT sample",
92  .AddTraceSource ("NextTxSequence",
93  "Next sequence number to send (SND.NXT)",
95  .AddTraceSource ("HighestSequence",
96  "Highest sequence number ever sent in socket's life time",
98  .AddTraceSource ("State",
99  "TCP state",
101  .AddTraceSource ("RWND",
102  "Remote side's flow control window",
104  ;
105  return tid;
106 }
107 
109  : m_dupAckCount (0),
110  m_delAckCount (0),
111  m_endPoint (0),
112  m_endPoint6 (0),
113  m_node (0),
114  m_tcp (0),
115  m_rtt (0),
116  m_nextTxSequence (0),
117  // Change this for non-zero initial sequence number
118  m_highTxMark (0),
119  m_rxBuffer (0),
120  m_txBuffer (0),
121  m_state (CLOSED),
122  m_errno (ERROR_NOTERROR),
123  m_closeNotified (false),
124  m_closeOnEmpty (false),
125  m_shutdownSend (false),
126  m_shutdownRecv (false),
127  m_connected (false),
128  m_segmentSize (0),
129  // For attribute initialization consistency (quiet valgrind)
130  m_rWnd (0)
131 {
132  NS_LOG_FUNCTION (this);
133 }
134 
136  : TcpSocket (sock),
137  //copy object::m_tid and socket::callbacks
138  m_dupAckCount (sock.m_dupAckCount),
139  m_delAckCount (0),
140  m_delAckMaxCount (sock.m_delAckMaxCount),
141  m_noDelay (sock.m_noDelay),
142  m_cnRetries (sock.m_cnRetries),
143  m_delAckTimeout (sock.m_delAckTimeout),
144  m_persistTimeout (sock.m_persistTimeout),
145  m_cnTimeout (sock.m_cnTimeout),
146  m_endPoint (0),
147  m_endPoint6 (0),
148  m_node (sock.m_node),
149  m_tcp (sock.m_tcp),
150  m_rtt (0),
151  m_nextTxSequence (sock.m_nextTxSequence),
152  m_highTxMark (sock.m_highTxMark),
153  m_rxBuffer (sock.m_rxBuffer),
154  m_txBuffer (sock.m_txBuffer),
155  m_state (sock.m_state),
156  m_errno (sock.m_errno),
157  m_closeNotified (sock.m_closeNotified),
158  m_closeOnEmpty (sock.m_closeOnEmpty),
159  m_shutdownSend (sock.m_shutdownSend),
160  m_shutdownRecv (sock.m_shutdownRecv),
161  m_connected (sock.m_connected),
162  m_msl (sock.m_msl),
163  m_segmentSize (sock.m_segmentSize),
164  m_maxWinSize (sock.m_maxWinSize),
165  m_rWnd (sock.m_rWnd)
166 {
167  NS_LOG_FUNCTION (this);
168  NS_LOG_LOGIC ("Invoked the copy constructor");
169  // Copy the rtt estimator if it is set
170  if (sock.m_rtt)
171  {
172  m_rtt = sock.m_rtt->Copy ();
173  }
174  // Reset all callbacks to null
175  Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
176  Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
177  Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
178  SetConnectCallback (vPS, vPS);
179  SetDataSentCallback (vPSUI);
180  SetSendCallback (vPSUI);
181  SetRecvCallback (vPS);
182 }
183 
185 {
186  NS_LOG_FUNCTION (this);
187  m_node = 0;
188  if (m_endPoint != 0)
189  {
190  NS_ASSERT (m_tcp != 0);
191  /*
192  * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
193  * DestroyCallback is set to TcpSocketBase::Destroy. If we called
194  * m_tcp->DeAllocate, it wil destroy its Ipv4EndpointDemux::DeAllocate,
195  * which in turn destroys my m_endPoint, and in turn invokes
196  * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
197  */
198  NS_ASSERT (m_endPoint != 0);
199  m_tcp->DeAllocate (m_endPoint);
200  NS_ASSERT (m_endPoint == 0);
201  }
202  if (m_endPoint6 != 0)
203  {
204  NS_ASSERT (m_tcp != 0);
205  NS_ASSERT (m_endPoint6 != 0);
206  m_tcp->DeAllocate (m_endPoint6);
207  NS_ASSERT (m_endPoint6 == 0);
208  }
209  m_tcp = 0;
210  CancelAllTimers ();
211 }
212 
213 /* Associate a node with this TCP socket */
214 void
216 {
217  m_node = node;
218 }
219 
220 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
221 void
223 {
224  m_tcp = tcp;
225 }
226 
227 /* Set an RTT estimator with this socket */
228 void
230 {
231  m_rtt = rtt;
232 }
233 
234 /* Inherit from Socket class: Returns error code */
237 {
238  return m_errno;
239 }
240 
241 /* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
244 {
245  return NS3_SOCK_STREAM;
246 }
247 
248 /* Inherit from Socket class: Returns associated node */
249 Ptr<Node>
251 {
253  return m_node;
254 }
255 
256 /* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
257 int
259 {
260  NS_LOG_FUNCTION (this);
261  m_endPoint = m_tcp->Allocate ();
262  if (0 == m_endPoint)
263  {
265  return -1;
266  }
267 
268  if (std::find(m_tcp->m_sockets.begin(), m_tcp->m_sockets.end(), this) == m_tcp->m_sockets.end())
269  {
270  m_tcp->m_sockets.push_back (this);
271  }
272  return SetupCallback ();
273 }
274 
275 int
277 {
278  NS_LOG_FUNCTION (this);
279  m_endPoint6 = m_tcp->Allocate6 ();
280  if (0 == m_endPoint6)
281  {
283  return -1;
284  }
285 
286  if (std::find(m_tcp->m_sockets.begin(), m_tcp->m_sockets.end(), this) == m_tcp->m_sockets.end())
287  {
288  m_tcp->m_sockets.push_back (this);
289  }
290  return SetupCallback ();
291 }
292 
293 /* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
294 int
296 {
297  NS_LOG_FUNCTION (this << address);
298  if (InetSocketAddress::IsMatchingType (address))
299  {
301  Ipv4Address ipv4 = transport.GetIpv4 ();
302  uint16_t port = transport.GetPort ();
303  if (ipv4 == Ipv4Address::GetAny () && port == 0)
304  {
305  m_endPoint = m_tcp->Allocate ();
306  }
307  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
308  {
309  m_endPoint = m_tcp->Allocate (port);
310  }
311  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
312  {
313  m_endPoint = m_tcp->Allocate (ipv4);
314  }
315  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
316  {
317  m_endPoint = m_tcp->Allocate (ipv4, port);
318  }
319  if (0 == m_endPoint)
320  {
322  return -1;
323  }
324  }
325  else if (Inet6SocketAddress::IsMatchingType (address))
326  {
328  Ipv6Address ipv6 = transport.GetIpv6 ();
329  uint16_t port = transport.GetPort ();
330  if (ipv6 == Ipv6Address::GetAny () && port == 0)
331  {
332  m_endPoint6 = m_tcp->Allocate6 ();
333  }
334  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
335  {
336  m_endPoint6 = m_tcp->Allocate6 (port);
337  }
338  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
339  {
340  m_endPoint6 = m_tcp->Allocate6 (ipv6);
341  }
342  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
343  {
344  m_endPoint6 = m_tcp->Allocate6 (ipv6, port);
345  }
346  if (0 == m_endPoint6)
347  {
349  return -1;
350  }
351  }
352  else
353  {
355  return -1;
356  }
357 
358  if (std::find(m_tcp->m_sockets.begin(), m_tcp->m_sockets.end(), this) == m_tcp->m_sockets.end())
359  {
360  m_tcp->m_sockets.push_back (this);
361  }
362  NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
363 
364  return SetupCallback ();
365 }
366 
367 /* Inherit from Socket class: Initiate connection to a remote address:port */
368 int
370 {
371  NS_LOG_FUNCTION (this << address);
372 
373  // If haven't do so, Bind() this socket first
374  if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0)
375  {
376  if (m_endPoint == 0)
377  {
378  if (Bind () == -1)
379  {
380  NS_ASSERT (m_endPoint == 0);
381  return -1; // Bind() failed
382  }
383  NS_ASSERT (m_endPoint != 0);
384  }
386  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
387  m_endPoint6 = 0;
388 
389  // Get the appropriate local address and port number from the routing protocol and set up endpoint
390  if (SetupEndpoint () != 0)
391  { // Route to destination does not exist
392  return -1;
393  }
394  }
395  else if (Inet6SocketAddress::IsMatchingType (address) && m_endPoint == 0)
396  {
397  // If we are operating on a v4-mapped address, translate the address to
398  // a v4 address and re-call this function
400  Ipv6Address v6Addr = transport.GetIpv6 ();
401  if (v6Addr.IsIpv4MappedAddress () == true)
402  {
403  Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
404  return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
405  }
406 
407  if (m_endPoint6 == 0)
408  {
409  if (Bind6 () == -1)
410  {
411  NS_ASSERT (m_endPoint6 == 0);
412  return -1; // Bind() failed
413  }
414  NS_ASSERT (m_endPoint6 != 0);
415  }
416  m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
417  m_endPoint = 0;
418 
419  // Get the appropriate local address and port number from the routing protocol and set up endpoint
420  if (SetupEndpoint6 () != 0)
421  { // Route to destination does not exist
422  return -1;
423  }
424  }
425  else
426  {
428  return -1;
429  }
430 
431  // Re-initialize parameters in case this socket is being reused after CLOSE
432  m_rtt->Reset ();
434 
435  // DoConnect() will do state-checking and send a SYN packet
436  return DoConnect ();
437 }
438 
439 /* Inherit from Socket class: Listen on the endpoint for an incoming connection */
440 int
442 {
443  NS_LOG_FUNCTION (this);
444  // Linux quits EINVAL if we're not in CLOSED state, so match what they do
445  if (m_state != CLOSED)
446  {
448  return -1;
449  }
450  // In other cases, set the state to LISTEN and done
451  NS_LOG_INFO ("CLOSED -> LISTEN");
452  m_state = LISTEN;
453  return 0;
454 }
455 
456 /* Inherit from Socket class: Kill this socket and signal the peer (if any) */
457 int
459 {
460  NS_LOG_FUNCTION (this);
464  if (m_rxBuffer.Size () != 0)
465  {
466  NS_LOG_INFO ("Socket " << this << " << unread rx data during close. Sending reset");
467  SendRST ();
468  return 0;
469  }
470 
472  { // App close with pending data must wait until all data transmitted
473  if (m_closeOnEmpty == false)
474  {
475  m_closeOnEmpty = true;
476  NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
477  }
478  return 0;
479  }
480  return DoClose ();
481 }
482 
483 /* Inherit from Socket class: Signal a termination of send */
484 int
486 {
487  NS_LOG_FUNCTION (this);
488 
489  //this prevents data from being added to the buffer
490  m_shutdownSend = true;
491  m_closeOnEmpty = true;
492  //if buffer is already empty, send a fin now
493  //otherwise fin will go when buffer empties.
494  if (m_txBuffer.Size () == 0)
495  {
496  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
497  {
498  NS_LOG_INFO("Emtpy tx buffer, send fin");
500 
501  if (m_state == ESTABLISHED)
502  { // On active close: I am the first one to send FIN
503  NS_LOG_INFO ("ESTABLISHED -> FIN_WAIT_1");
505  }
506  else
507  { // On passive close: Peer sent me FIN already
508  NS_LOG_INFO ("CLOSE_WAIT -> LAST_ACK");
509  m_state = LAST_ACK;
510  }
511  }
512  }
513 
514  return 0;
515 }
516 
517 /* Inherit from Socket class: Signal a termination of receive */
518 int
520 {
521  NS_LOG_FUNCTION (this);
522  m_shutdownRecv = true;
523  return 0;
524 }
525 
526 /* Inherit from Socket class: Send a packet. Parameter flags is not used.
527  Packet has no TCP header. Invoked by upper-layer application */
528 int
529 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
530 {
531  NS_LOG_FUNCTION (this << p);
532  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
534  {
535  // Store the packet into Tx buffer
536  if (!m_txBuffer.Add (p))
537  { // TxBuffer overflow, send failed
539  return -1;
540  }
541  if (m_shutdownSend)
542  {
544  return -1;
545  }
546  // Submit the data to lower layers
547  NS_LOG_LOGIC ("txBufSize=" << m_txBuffer.Size () << " state " << TcpStateName[m_state]);
548  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
549  { // Try to send the data out
551  }
552  return p->GetSize ();
553  }
554  else
555  { // Connection not established yet
557  return -1; // Send failure
558  }
559 }
560 
561 /* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
562 int
564 {
565  return Send (p, flags); // SendTo() and Send() are the same
566 }
567 
568 /* Inherit from Socket class: Return data to upper-layer application. Parameter flags
569  is not used. Data is returned as a packet of size no larger than maxSize */
571 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
572 {
573  NS_LOG_FUNCTION (this);
574  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
575  if (m_rxBuffer.Size () == 0 && m_state == CLOSE_WAIT)
576  {
577  return Create<Packet> (); // Send EOF on connection close
578  }
579  Ptr<Packet> outPacket = m_rxBuffer.Extract (maxSize);
580  if (outPacket != 0 && outPacket->GetSize () != 0)
581  {
582  SocketAddressTag tag;
583  if (m_endPoint != 0)
584  {
586  }
587  else if (m_endPoint6 != 0)
588  {
590  }
591  outPacket->AddPacketTag (tag);
592  }
593  return outPacket;
594 }
595 
596 /* Inherit from Socket class: Recv and return the remote's address */
598 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
599 {
600  NS_LOG_FUNCTION (this << maxSize << flags);
601  Ptr<Packet> packet = Recv (maxSize, flags);
602  // Null packet means no data to read, and an empty packet indicates EOF
603  if (packet != 0 && packet->GetSize () != 0)
604  {
605  if (m_endPoint != 0)
606  {
608  }
609  else if (m_endPoint6 != 0)
610  {
612  }
613  else
614  {
615  fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
616  }
617  }
618  return packet;
619 }
620 
621 /* Inherit from Socket class: Get the max number of bytes an app can send */
622 uint32_t
624 {
625  NS_LOG_FUNCTION (this);
626  return m_txBuffer.Available ();
627 }
628 
629 /* Inherit from Socket class: Get the max number of bytes an app can read */
630 uint32_t
632 {
633  NS_LOG_FUNCTION (this);
634  return m_rxBuffer.Available ();
635 }
636 
637 /* Inherit from Socket class: Return local address:port */
638 int
640 {
641  NS_LOG_FUNCTION (this);
642  if (m_endPoint != 0)
643  {
645  }
646  else if (m_endPoint6 != 0)
647  {
649  }
650  else
651  { // It is possible to call this method on a socket without a name
652  // in which case, behavior is unspecified
653  // Should this return an InetSocketAddress or an Inet6SocketAddress?
654  address = InetSocketAddress (Ipv4Address::GetZero (), 0);
655  }
656  return 0;
657 }
658 
659 /* Inherit from Socket class: Bind this socket to the specified NetDevice */
660 void
662 {
663  NS_LOG_FUNCTION (netdevice);
664  Socket::BindToNetDevice (netdevice); // Includes sanity check
665  if (m_endPoint == 0 && m_endPoint6 == 0)
666  {
667  if (Bind () == -1)
668  {
669  NS_ASSERT ((m_endPoint == 0 && m_endPoint6 == 0));
670  return;
671  }
672  NS_ASSERT ((m_endPoint != 0 && m_endPoint6 != 0));
673  }
674 
675  if (m_endPoint != 0)
676  {
677  m_endPoint->BindToNetDevice (netdevice);
678  }
679  // No BindToNetDevice() for Ipv6EndPoint
680  return;
681 }
682 
683 /* Clean up after Bind. Set up callback functions in the end-point. */
684 int
686 {
687  NS_LOG_FUNCTION (this);
688 
689  if (m_endPoint == 0 && m_endPoint6 == 0)
690  {
691  return -1;
692  }
693  if (m_endPoint != 0)
694  {
698  }
699  if (m_endPoint6 != 0)
700  {
704  }
705 
706  return 0;
707 }
708 
709 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
710 int
712 {
713  NS_LOG_FUNCTION (this);
714 
715  // A new connection is allowed only if this socket does not have a connection
717  { // send a SYN packet and change state into SYN_SENT
719  NS_LOG_INFO (TcpStateName[m_state] << " -> SYN_SENT");
720  m_state = SYN_SENT;
721  }
722  else if (m_state != TIME_WAIT)
723  { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
724  // exists. We send RST, tear down everything, and close this socket.
725  SendRST ();
726  CloseAndNotify ();
727  }
728  return 0;
729 }
730 
731 /* Do the action to close the socket. Usually send a packet with appropriate
732  flags depended on the current m_state. */
733 int
735 {
736  NS_LOG_FUNCTION (this);
737  switch (m_state)
738  {
739  case SYN_RCVD:
740  case ESTABLISHED:
741  // send FIN to close the peer
743  NS_LOG_INFO ("ESTABLISHED -> FIN_WAIT_1");
745  break;
746  case CLOSE_WAIT:
747  // send FIN+ACK to close the peer
749  NS_LOG_INFO ("CLOSE_WAIT -> LAST_ACK");
750  m_state = LAST_ACK;
751  break;
752  case SYN_SENT:
753  case CLOSING:
754  // Send RST if application closes in SYN_SENT and CLOSING
755  SendRST ();
756  CloseAndNotify ();
757  break;
758  case LISTEN:
759  case LAST_ACK:
760  // In these three states, move to CLOSED and tear down the end point
761  CloseAndNotify ();
762  break;
763  case CLOSED:
764  case FIN_WAIT_1:
765  case FIN_WAIT_2:
766  case TIME_WAIT:
767  default: /* mute compiler */
768  // Do nothing in these four states
769  break;
770  }
771  return 0;
772 }
773 
774 /* Peacefully close the socket by notifying the upper layer and deallocate end point */
775 void
777 {
778  NS_LOG_FUNCTION (this);
779 
780  if (!m_closeNotified)
781  {
783  }
784 
785  if (m_state != TIME_WAIT)
786  {
788  }
789 
790  m_closeNotified = true;
791  NS_LOG_INFO (TcpStateName[m_state] << " -> CLOSED");
792  CancelAllTimers ();
793  m_state = CLOSED;
794 }
795 
796 
797 /* Tell if a sequence number range is out side the range that my rx buffer can
798  accpet */
799 bool
801 {
802  if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
803  { // Rx buffer in these states are not initialized.
804  return false;
805  }
806  if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
807  { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
808  // sequence number must equals to m_rxBuffer.NextRxSequence ()
809  return (m_rxBuffer.NextRxSequence () != head);
810  }
811 
812  // In all other cases, check if the sequence number is in range
813  return (tail < m_rxBuffer.NextRxSequence () || m_rxBuffer.MaxRxSequence () <= head);
814 }
815 
816 /* Function called by the L3 protocol when it received a packet to pass on to
817  the TCP. This function is registered as the "RxCallback" function in
818  SetupCallback(), which invoked by Bind(), and CompleteFork() */
819 void
821  Ptr<Ipv4Interface> incomingInterface)
822 {
823  DoForwardUp (packet, header, port, incomingInterface);
824 }
825 
826 void
827 TcpSocketBase::ForwardUp6 (Ptr<Packet> packet, Ipv6Header header, uint16_t port, Ptr<Ipv6Interface> incomingInterface)
828 {
829  DoForwardUp (packet, header, port);
830 }
831 
832 void
833 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
834  uint8_t icmpType, uint8_t icmpCode,
835  uint32_t icmpInfo)
836 {
837  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
838  (uint32_t)icmpCode << icmpInfo);
839  if (!m_icmpCallback.IsNull ())
840  {
841  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
842  }
843 }
844 
845 void
846 TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
847  uint8_t icmpType, uint8_t icmpCode,
848  uint32_t icmpInfo)
849 {
850  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
851  (uint32_t)icmpCode << icmpInfo);
852  if (!m_icmpCallback6.IsNull ())
853  {
854  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
855  }
856 }
857 
858 /* The real function to handle the incoming packet from lower layers. This is
859  wrapped by ForwardUp() so that this function can be overloaded by daughter
860  classes. */
861 void
863  Ptr<Ipv4Interface> incomingInterface)
864 {
865  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
867  ":" << m_endPoint->GetPeerPort () <<
868  " to " << m_endPoint->GetLocalAddress () <<
869  ":" << m_endPoint->GetLocalPort ());
870  Address fromAddress = InetSocketAddress (header.GetSource (), port);
871  Address toAddress = InetSocketAddress (header.GetDestination (), m_endPoint->GetLocalPort ());
872 
873  // Peel off TCP header and do validity checking
874  TcpHeader tcpHeader;
875  packet->RemoveHeader (tcpHeader);
876  if (tcpHeader.GetFlags () & TcpHeader::ACK)
877  {
878  EstimateRtt (tcpHeader);
879  }
880  ReadOptions (tcpHeader);
881 
882  // Update Rx window size, i.e. the flow control window
883  if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0)
884  { // persist probes end
885  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
887  }
888  m_rWnd = tcpHeader.GetWindowSize ();
889 
890  // Discard fully out of range data packets
891  if (packet->GetSize ()
892  && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
893  {
894  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
895  " received packet of seq [" << tcpHeader.GetSequenceNumber () <<
896  ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
897  ") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
898  m_rxBuffer.MaxRxSequence () << ")");
899  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
900  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
901  {
903  }
904  return;
905  }
906 
907  // TCP state machine code in different process functions
908  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
909  switch (m_state)
910  {
911  case ESTABLISHED:
912  ProcessEstablished (packet, tcpHeader);
913  break;
914  case LISTEN:
915  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
916  break;
917  case TIME_WAIT:
918  // Do nothing
919  break;
920  case CLOSED:
921  // Send RST if the incoming packet is not a RST
922  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
923  { // Since m_endPoint is not configured yet, we cannot use SendRST here
924  TcpHeader h;
928  h.SetSourcePort (tcpHeader.GetDestinationPort ());
929  h.SetDestinationPort (tcpHeader.GetSourcePort ());
931  AddOptions (h);
932  m_tcp->SendPacket (Create<Packet> (), h, header.GetDestination (), header.GetSource (), m_boundnetdevice);
933  }
934  break;
935  case SYN_SENT:
936  ProcessSynSent (packet, tcpHeader);
937  break;
938  case SYN_RCVD:
939  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
940  break;
941  case FIN_WAIT_1:
942  case FIN_WAIT_2:
943  case CLOSE_WAIT:
944  ProcessWait (packet, tcpHeader);
945  break;
946  case CLOSING:
947  ProcessClosing (packet, tcpHeader);
948  break;
949  case LAST_ACK:
950  ProcessLastAck (packet, tcpHeader);
951  break;
952  default: // mute compiler
953  break;
954  }
955 }
956 
957 void
959 {
960  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
962  ":" << m_endPoint6->GetPeerPort () <<
963  " to " << m_endPoint6->GetLocalAddress () <<
964  ":" << m_endPoint6->GetLocalPort ());
965  Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port);
967 
968  // Peel off TCP header and do validity checking
969  TcpHeader tcpHeader;
970  packet->RemoveHeader (tcpHeader);
971  if (tcpHeader.GetFlags () & TcpHeader::ACK)
972  {
973  EstimateRtt (tcpHeader);
974  }
975  ReadOptions (tcpHeader);
976 
977  // Update Rx window size, i.e. the flow control window
978  if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0)
979  { // persist probes end
980  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
982  }
983  m_rWnd = tcpHeader.GetWindowSize ();
984 
985  // Discard fully out of range packets
986  if (packet->GetSize ()
987  && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
988  {
989  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
990  " received packet of seq [" << tcpHeader.GetSequenceNumber () <<
991  ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
992  ") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
993  m_rxBuffer.MaxRxSequence () << ")");
994  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
995  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
996  {
998  }
999  return;
1000  }
1001 
1002  // TCP state machine code in different process functions
1003  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1004  switch (m_state)
1005  {
1006  case ESTABLISHED:
1007  ProcessEstablished (packet, tcpHeader);
1008  break;
1009  case LISTEN:
1010  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1011  break;
1012  case TIME_WAIT:
1013  // Do nothing
1014  break;
1015  case CLOSED:
1016  // Send RST if the incoming packet is not a RST
1017  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1018  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1019  TcpHeader h;
1023  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1024  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1026  AddOptions (h);
1027  m_tcp->SendPacket (Create<Packet> (), h, header.GetDestinationAddress (), header.GetSourceAddress (), m_boundnetdevice);
1028  }
1029  break;
1030  case SYN_SENT:
1031  ProcessSynSent (packet, tcpHeader);
1032  break;
1033  case SYN_RCVD:
1034  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1035  break;
1036  case FIN_WAIT_1:
1037  case FIN_WAIT_2:
1038  case CLOSE_WAIT:
1039  ProcessWait (packet, tcpHeader);
1040  break;
1041  case CLOSING:
1042  ProcessClosing (packet, tcpHeader);
1043  break;
1044  case LAST_ACK:
1045  ProcessLastAck (packet, tcpHeader);
1046  break;
1047  default: // mute compiler
1048  break;
1049  }
1050 }
1051 
1052 /* Received a packet upon ESTABLISHED state. This function is mimicking the
1053  role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1054 void
1056 {
1057  NS_LOG_FUNCTION (this << tcpHeader);
1058 
1059  // Extract the flags. PSH and URG are not honoured.
1060  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1061 
1062  // Different flags are different events
1063  if (tcpflags == TcpHeader::ACK)
1064  {
1065  ReceivedAck (packet, tcpHeader);
1066  }
1067  else if (tcpflags == TcpHeader::SYN)
1068  { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1069  // respond with a SYN+ACK. But it is not a legal state transition as of
1070  // RFC793. Thus this is ignored.
1071  }
1072  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1073  { // No action for received SYN+ACK, it is probably a duplicated packet
1074  }
1075  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1076  { // Received FIN or FIN+ACK, bring down this socket nicely
1077  PeerClose (packet, tcpHeader);
1078  }
1079  else if (tcpflags == 0)
1080  { // No flags means there is only data
1081  ReceivedData (packet, tcpHeader);
1082  if (m_rxBuffer.Finished ())
1083  {
1084  PeerClose (packet, tcpHeader);
1085  }
1086  }
1087  else
1088  { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1089  if (tcpflags != TcpHeader::RST)
1090  { // this must be an invalid flag, send reset
1091  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1092  SendRST ();
1093  }
1094  CloseAndNotify ();
1095  }
1096 }
1097 
1098 /* Process the newly received ACK */
1099 void
1101 {
1102  NS_LOG_FUNCTION (this << tcpHeader);
1103 
1104  // Received ACK. Compare the ACK number against highest unacked seqno
1105  if (0 == (tcpHeader.GetFlags () & TcpHeader::ACK))
1106  { // Ignore if no ACK flag
1107  }
1108  else if (tcpHeader.GetAckNumber () < m_txBuffer.HeadSequence ())
1109  { // Case 1: Old ACK, ignored.
1110  NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber ());
1111  }
1112  else if (tcpHeader.GetAckNumber () == m_txBuffer.HeadSequence ())
1113  { // Case 2: Potentially a duplicated ACK
1114  if (tcpHeader.GetAckNumber () < m_nextTxSequence && packet->GetSize() == 0)
1115  {
1116  NS_LOG_LOGIC ("Dupack of " << tcpHeader.GetAckNumber ());
1117  DupAck (tcpHeader, ++m_dupAckCount);
1118  }
1119  // otherwise, the ACK is precisely equal to the nextTxSequence
1120  NS_ASSERT (tcpHeader.GetAckNumber () <= m_nextTxSequence);
1121  }
1122  else if (tcpHeader.GetAckNumber () > m_txBuffer.HeadSequence ())
1123  { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer
1124  NS_LOG_LOGIC ("New ack of " << tcpHeader.GetAckNumber ());
1125  NewAck (tcpHeader.GetAckNumber ());
1126  m_dupAckCount = 0;
1127  }
1128  // If there is any data piggybacked, store it into m_rxBuffer
1129  if (packet->GetSize () > 0)
1130  {
1131  ReceivedData (packet, tcpHeader);
1132  }
1133 }
1134 
1135 /* Received a packet upon LISTEN state. */
1136 void
1138  const Address& fromAddress, const Address& toAddress)
1139 {
1140  NS_LOG_FUNCTION (this << tcpHeader);
1141 
1142  // Extract the flags. PSH and URG are not honoured.
1143  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1144 
1145  // Fork a socket if received a SYN. Do nothing otherwise.
1146  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
1147  if (tcpflags != TcpHeader::SYN)
1148  {
1149  return;
1150  }
1151 
1152  // Call socket's notify function to let the server app know we got a SYN
1153  // If the server app refuses the connection, do nothing
1154  if (!NotifyConnectionRequest (fromAddress))
1155  {
1156  return;
1157  }
1158  // Clone the socket, simulate fork
1159  Ptr<TcpSocketBase> newSock = Fork ();
1160  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
1162  packet, tcpHeader, fromAddress, toAddress);
1163 }
1164 
1165 /* Received a packet upon SYN_SENT */
1166 void
1168 {
1169  NS_LOG_FUNCTION (this << tcpHeader);
1170 
1171  // Extract the flags. PSH and URG are not honoured.
1172  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1173 
1174  if (tcpflags == 0)
1175  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
1176  NS_LOG_INFO ("SYN_SENT -> ESTABLISHED");
1177  m_state = ESTABLISHED;
1178  m_connected = true;
1179  m_retxEvent.Cancel ();
1181  ReceivedData (packet, tcpHeader);
1183  }
1184  else if (tcpflags == TcpHeader::ACK)
1185  { // Ignore ACK in SYN_SENT
1186  }
1187  else if (tcpflags == TcpHeader::SYN)
1188  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
1189  NS_LOG_INFO ("SYN_SENT -> SYN_RCVD");
1190  m_state = SYN_RCVD;
1194  }
1195  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK)
1196  && m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
1197  { // Handshake completed
1198  NS_LOG_INFO ("SYN_SENT -> ESTABLISHED");
1199  m_state = ESTABLISHED;
1200  m_connected = true;
1201  m_retxEvent.Cancel ();
1208  // Always respond to first data packet to speed up the connection.
1209  // Remove to get the behaviour of old NS-3 code.
1211  }
1212  else
1213  { // Other in-sequence input
1214  if (tcpflags != TcpHeader::RST)
1215  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
1216  NS_LOG_LOGIC ("Illegal flag " << std::hex << static_cast<uint32_t> (tcpflags) << std::dec << " received. Reset packet is sent.");
1217  SendRST ();
1218  }
1219  CloseAndNotify ();
1220  }
1221 }
1222 
1223 /* Received a packet upon SYN_RCVD */
1224 void
1226  const Address& fromAddress, const Address& toAddress)
1227 {
1228  NS_LOG_FUNCTION (this << tcpHeader);
1229 
1230  // Extract the flags. PSH and URG are not honoured.
1231  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1232 
1233  if (tcpflags == 0
1234  || (tcpflags == TcpHeader::ACK
1235  && m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
1236  { // If it is bare data, accept it and move to ESTABLISHED state. This is
1237  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
1238  // handshake is completed nicely.
1239  NS_LOG_INFO ("SYN_RCVD -> ESTABLISHED");
1240  m_state = ESTABLISHED;
1241  m_connected = true;
1242  m_retxEvent.Cancel ();
1245  if (m_endPoint)
1246  {
1247  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1248  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1249  }
1250  else if (m_endPoint6)
1251  {
1252  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1253  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1254  }
1255  // Always respond to first data packet to speed up the connection.
1256  // Remove to get the behaviour of old NS-3 code.
1258  ReceivedAck (packet, tcpHeader);
1259  NotifyNewConnectionCreated (this, fromAddress);
1260  // As this connection is established, the socket is available to send data now
1261  if (GetTxAvailable () > 0)
1262  {
1264  }
1265  }
1266  else if (tcpflags == TcpHeader::SYN)
1267  { // Probably the peer lost my SYN+ACK
1270  }
1271  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1272  {
1273  if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSequence ())
1274  { // In-sequence FIN before connection complete. Set up connection and close.
1275  m_connected = true;
1276  m_retxEvent.Cancel ();
1279  if (m_endPoint)
1280  {
1281  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1282  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1283  }
1284  else if (m_endPoint6)
1285  {
1286  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1287  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1288  }
1289  PeerClose (packet, tcpHeader);
1290  }
1291  }
1292  else
1293  { // Other in-sequence input
1294  if (tcpflags != TcpHeader::RST)
1295  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
1296  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1297  if (m_endPoint)
1298  {
1299  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1300  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1301  }
1302  else if (m_endPoint6)
1303  {
1304  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1305  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1306  }
1307  SendRST ();
1308  }
1309  CloseAndNotify ();
1310  }
1311 }
1312 
1313 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
1314 void
1316 {
1317  NS_LOG_FUNCTION (this << tcpHeader);
1318 
1319  // Extract the flags. PSH and URG are not honoured.
1320  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1321 
1322  if (packet->GetSize () > 0 && tcpflags != TcpHeader::ACK)
1323  { // Bare data, accept it
1324  ReceivedData (packet, tcpHeader);
1325  }
1326  else if (tcpflags == TcpHeader::ACK)
1327  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
1328  ReceivedAck (packet, tcpHeader);
1329  if (m_state == FIN_WAIT_1 && m_txBuffer.Size () == 0
1330  && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
1331  { // This ACK corresponds to the FIN sent
1332  NS_LOG_INFO ("FIN_WAIT_1 -> FIN_WAIT_2");
1333  m_state = FIN_WAIT_2;
1334  }
1335  }
1336  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1337  { // Got FIN, respond with ACK and move to next state
1338  if (tcpflags & TcpHeader::ACK)
1339  { // Process the ACK first
1340  ReceivedAck (packet, tcpHeader);
1341  }
1343  }
1344  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1345  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
1346  return;
1347  }
1348  else
1349  { // This is a RST or bad flags
1350  if (tcpflags != TcpHeader::RST)
1351  {
1352  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1353  SendRST ();
1354  }
1355  CloseAndNotify ();
1356  return;
1357  }
1358 
1359  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
1360  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer.Finished ())
1361  {
1362  if (m_state == FIN_WAIT_1)
1363  {
1364  NS_LOG_INFO ("FIN_WAIT_1 -> CLOSING");
1365  m_state = CLOSING;
1366  if (m_txBuffer.Size () == 0
1367  && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
1368  { // This ACK corresponds to the FIN sent
1369  TimeWait ();
1370  }
1371  }
1372  else if (m_state == FIN_WAIT_2)
1373  {
1374  TimeWait ();
1375  }
1377  if (!m_shutdownRecv)
1378  {
1379  NotifyDataRecv ();
1380  }
1381  }
1382 }
1383 
1384 /* Received a packet upon CLOSING */
1385 void
1387 {
1388  NS_LOG_FUNCTION (this << tcpHeader);
1389 
1390  // Extract the flags. PSH and URG are not honoured.
1391  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1392 
1393  if (tcpflags == TcpHeader::ACK)
1394  {
1395  if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSequence ())
1396  { // This ACK corresponds to the FIN sent
1397  TimeWait ();
1398  }
1399  }
1400  else
1401  { // CLOSING state means simultaneous close, i.e. no one is sending data to
1402  // anyone. If anything other than ACK is received, respond with a reset.
1403  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1404  { // FIN from the peer as well. We can close immediately.
1406  }
1407  else if (tcpflags != TcpHeader::RST)
1408  { // Receive of SYN or SYN+ACK or bad flags or pure data
1409  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1410  SendRST ();
1411  }
1412  CloseAndNotify ();
1413  }
1414 }
1415 
1416 /* Received a packet upon LAST_ACK */
1417 void
1419 {
1420  NS_LOG_FUNCTION (this << tcpHeader);
1421 
1422  // Extract the flags. PSH and URG are not honoured.
1423  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1424 
1425  if (tcpflags == 0)
1426  {
1427  ReceivedData (packet, tcpHeader);
1428  }
1429  else if (tcpflags == TcpHeader::ACK)
1430  {
1431  if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSequence ())
1432  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
1433  CloseAndNotify ();
1434  }
1435  }
1436  else if (tcpflags == TcpHeader::FIN)
1437  { // Received FIN again, the peer probably lost the FIN+ACK
1439  }
1440  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
1441  {
1442  CloseAndNotify ();
1443  }
1444  else
1445  { // Received a SYN or SYN+ACK or bad flags
1446  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1447  SendRST ();
1448  CloseAndNotify ();
1449  }
1450 }
1451 
1452 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
1453 void
1455 {
1456  NS_LOG_FUNCTION (this << tcpHeader);
1457 
1458  // Ignore all out of range packets
1459  if (tcpHeader.GetSequenceNumber () < m_rxBuffer.NextRxSequence ()
1460  || tcpHeader.GetSequenceNumber () > m_rxBuffer.MaxRxSequence ())
1461  {
1462  return;
1463  }
1464  // For any case, remember the FIN position in rx buffer first
1466  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
1467  // If there is any piggybacked data, process it
1468  if (p->GetSize ())
1469  {
1470  ReceivedData (p, tcpHeader);
1471  }
1472  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
1473  if (!m_rxBuffer.Finished ())
1474  {
1475  return;
1476  }
1477 
1478  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
1479  if (m_state == FIN_WAIT_1)
1480  {
1481  NS_LOG_INFO ("FIN_WAIT_1 -> CLOSING");
1482  m_state = CLOSING;
1483  return;
1484  }
1485 
1486  DoPeerClose (); // Change state, respond with ACK
1487 }
1488 
1489 /* Received a in-sequence FIN. Close down this socket. */
1490 void
1492 {
1494 
1495  // Move the state to CLOSE_WAIT
1496  NS_LOG_INFO (TcpStateName[m_state] << " -> CLOSE_WAIT");
1497  m_state = CLOSE_WAIT;
1498 
1499  if (!m_closeNotified)
1500  {
1501  // The normal behaviour for an application is that, when the peer sent a in-sequence
1502  // FIN, the app should prepare to close. The app has two choices at this point: either
1503  // respond with ShutdownSend() call to declare that it has nothing more to send and
1504  // the socket can be closed immediately; or remember the peer's close request, wait
1505  // until all its existing data are pushed into the TCP socket, then call Close()
1506  // explicitly.
1507  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
1508  NotifyNormalClose ();
1509  m_closeNotified = true;
1510  }
1511  if (m_shutdownSend)
1512  { // The application declares that it would not sent any more, close this socket
1513  Close ();
1514  }
1515  else
1516  { // Need to ack, the application will close later
1518  }
1519  if (m_state == LAST_ACK)
1520  {
1521  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
1522  m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
1524  }
1525 }
1526 
1527 /* Kill this socket. This is a callback function configured to m_endpoint in
1528  SetupCallback(), invoked when the endpoint is destroyed. */
1529 void
1531 {
1532  NS_LOG_FUNCTION (this);
1533  m_endPoint = 0;
1534  if (m_tcp != 0)
1535  {
1536  std::vector<Ptr<TcpSocketBase> >::iterator it
1537  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1538  if (it != m_tcp->m_sockets.end ())
1539  {
1540  m_tcp->m_sockets.erase (it);
1541  }
1542  }
1543  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1544  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1545  CancelAllTimers ();
1546 }
1547 
1548 /* Kill this socket. This is a callback function configured to m_endpoint in
1549  SetupCallback(), invoked when the endpoint is destroyed. */
1550 void
1552 {
1553  NS_LOG_FUNCTION (this);
1554  m_endPoint6 = 0;
1555  if (m_tcp != 0)
1556  {
1557  std::vector<Ptr<TcpSocketBase> >::iterator it
1558  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1559  if (it != m_tcp->m_sockets.end ())
1560  {
1561  m_tcp->m_sockets.erase (it);
1562  }
1563  }
1564  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1565  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1566  CancelAllTimers ();
1567 }
1568 
1569 /* Send an empty packet with specified TCP flags */
1570 void
1572 {
1573  NS_LOG_FUNCTION (this << (uint32_t)flags);
1574  Ptr<Packet> p = Create<Packet> ();
1575  TcpHeader header;
1577 
1578  /*
1579  * Add tags for each socket option.
1580  * Note that currently the socket adds both IPv4 tag and IPv6 tag
1581  * if both options are set. Once the packet got to layer three, only
1582  * the corresponding tags will be read.
1583  */
1584  if (IsManualIpTos ())
1585  {
1586  SocketIpTosTag ipTosTag;
1587  ipTosTag.SetTos (GetIpTos ());
1588  p->AddPacketTag (ipTosTag);
1589  }
1590 
1591  if (IsManualIpv6Tclass ())
1592  {
1593  SocketIpv6TclassTag ipTclassTag;
1594  ipTclassTag.SetTclass (GetIpv6Tclass ());
1595  p->AddPacketTag (ipTclassTag);
1596  }
1597 
1598  if (IsManualIpTtl ())
1599  {
1600  SocketIpTtlTag ipTtlTag;
1601  ipTtlTag.SetTtl (GetIpTtl ());
1602  p->AddPacketTag (ipTtlTag);
1603  }
1604 
1605  if (IsManualIpv6HopLimit ())
1606  {
1607  SocketIpv6HopLimitTag ipHopLimitTag;
1608  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
1609  p->AddPacketTag (ipHopLimitTag);
1610  }
1611 
1612  if (m_endPoint == 0 && m_endPoint6 == 0)
1613  {
1614  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
1615  return;
1616  }
1617  if (flags & TcpHeader::FIN)
1618  {
1619  flags |= TcpHeader::ACK;
1620  }
1621  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
1622  {
1623  ++s;
1624  }
1625 
1626  header.SetFlags (flags);
1627  header.SetSequenceNumber (s);
1628  header.SetAckNumber (m_rxBuffer.NextRxSequence ());
1629  if (m_endPoint != 0)
1630  {
1631  header.SetSourcePort (m_endPoint->GetLocalPort ());
1632  header.SetDestinationPort (m_endPoint->GetPeerPort ());
1633  }
1634  else
1635  {
1636  header.SetSourcePort (m_endPoint6->GetLocalPort ());
1637  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
1638  }
1639  header.SetWindowSize (AdvertisedWindowSize ());
1640  AddOptions (header);
1641  m_rto = m_rtt->RetransmitTimeout ();
1642  bool hasSyn = flags & TcpHeader::SYN;
1643  bool hasFin = flags & TcpHeader::FIN;
1644  bool isAck = flags == TcpHeader::ACK;
1645  if (hasSyn)
1646  {
1647  if (m_cnCount == 0)
1648  { // No more connection retries, give up
1649  NS_LOG_LOGIC ("Connection failed.");
1650  CloseAndNotify ();
1651  return;
1652  }
1653  else
1654  { // Exponential backoff of connection time out
1655  int backoffCount = 0x1 << (m_cnRetries - m_cnCount);
1656  m_rto = m_cnTimeout * backoffCount;
1657  m_cnCount--;
1658  }
1659  }
1660  if (m_endPoint != 0)
1661  {
1662  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
1664  }
1665  else
1666  {
1667  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
1669  }
1670  if (flags & TcpHeader::ACK)
1671  { // If sending an ACK, cancel the delay ACK as well
1672  m_delAckEvent.Cancel ();
1673  m_delAckCount = 0;
1674  }
1675  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
1676  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
1677  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
1678  << Simulator::Now ().GetSeconds () << " to expire at time "
1679  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
1681  }
1682 }
1683 
1684 /* This function closes the endpoint completely. Called upon RST_TX action. */
1685 void
1687 {
1688  NS_LOG_FUNCTION (this);
1690  NotifyErrorClose ();
1691  DeallocateEndPoint ();
1692 }
1693 
1694 /* Deallocate the end point and cancel all the timers */
1695 void
1697 {
1698  if (m_endPoint != 0)
1699  {
1700  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
1701  m_tcp->DeAllocate (m_endPoint);
1702  m_endPoint = 0;
1703  std::vector<Ptr<TcpSocketBase> >::iterator it
1704  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1705  if (it != m_tcp->m_sockets.end ())
1706  {
1707  m_tcp->m_sockets.erase (it);
1708  }
1709  CancelAllTimers ();
1710  }
1711  if (m_endPoint6 != 0)
1712  {
1713  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
1714  m_tcp->DeAllocate (m_endPoint6);
1715  m_endPoint6 = 0;
1716  std::vector<Ptr<TcpSocketBase> >::iterator it
1717  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1718  if (it != m_tcp->m_sockets.end ())
1719  {
1720  m_tcp->m_sockets.erase (it);
1721  }
1722  CancelAllTimers ();
1723  }
1724 }
1725 
1726 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
1727 int
1729 {
1730  NS_LOG_FUNCTION (this);
1731  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
1732  NS_ASSERT (ipv4 != 0);
1733  if (ipv4->GetRoutingProtocol () == 0)
1734  {
1735  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
1736  }
1737  // Create a dummy packet, then ask the routing function for the best output
1738  // interface's address
1739  Ipv4Header header;
1741  Socket::SocketErrno errno_;
1742  Ptr<Ipv4Route> route;
1744  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
1745  if (route == 0)
1746  {
1747  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
1748  NS_LOG_ERROR (errno_);
1749  m_errno = errno_;
1750  return -1;
1751  }
1752  NS_LOG_LOGIC ("Route exists");
1753  m_endPoint->SetLocalAddress (route->GetSource ());
1754  return 0;
1755 }
1756 
1757 int
1759 {
1760  NS_LOG_FUNCTION (this);
1762  NS_ASSERT (ipv6 != 0);
1763  if (ipv6->GetRoutingProtocol () == 0)
1764  {
1765  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
1766  }
1767  // Create a dummy packet, then ask the routing function for the best output
1768  // interface's address
1769  Ipv6Header header;
1771  Socket::SocketErrno errno_;
1772  Ptr<Ipv6Route> route;
1774  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
1775  if (route == 0)
1776  {
1777  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
1778  NS_LOG_ERROR (errno_);
1779  m_errno = errno_;
1780  return -1;
1781  }
1782  NS_LOG_LOGIC ("Route exists");
1783  m_endPoint6->SetLocalAddress (route->GetSource ());
1784  return 0;
1785 }
1786 
1787 /* This function is called only if a SYN received in LISTEN state. After
1788  TcpSocketBase cloned, allocate a new end point to handle the incoming
1789  connection and send a SYN+ACK to complete the handshake. */
1790 void
1792  const Address& fromAddress, const Address& toAddress)
1793 {
1794  // Get port and address from peer (connecting host)
1795  if (InetSocketAddress::IsMatchingType (toAddress))
1796  {
1797  m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
1798  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
1799  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1800  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1801  m_endPoint6 = 0;
1802  }
1803  else if (Inet6SocketAddress::IsMatchingType (toAddress))
1804  {
1805  m_endPoint6 = m_tcp->Allocate6 (Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
1806  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
1807  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1808  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1809  m_endPoint = 0;
1810  }
1811  m_tcp->m_sockets.push_back (this);
1812 
1813  // Change the cloned socket from LISTEN state to SYN_RCVD
1814  NS_LOG_INFO ("LISTEN -> SYN_RCVD");
1815  m_state = SYN_RCVD;
1817  SetupCallback ();
1818  // Set the sequence number and send SYN+ACK
1821 }
1822 
1823 void
1825 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
1826  // be called as a scheduled event
1828  // The if-block below was moved from ProcessSynSent() to here because we need
1829  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
1830  // reflect the behaviour in the real world.
1831  if (GetTxAvailable () > 0)
1832  {
1834  }
1835 }
1836 
1837 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
1838  TCP header, and send to TcpL4Protocol */
1839 uint32_t
1840 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
1841 {
1842  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
1843 
1844  Ptr<Packet> p = m_txBuffer.CopyFromSequence (maxSize, seq);
1845  uint32_t sz = p->GetSize (); // Size of packet
1846  uint8_t flags = withAck ? TcpHeader::ACK : 0;
1847  uint32_t remainingData = m_txBuffer.SizeFromSequence (seq + SequenceNumber32 (sz));
1848 
1849  /*
1850  * Add tags for each socket option.
1851  * Note that currently the socket adds both IPv4 tag and IPv6 tag
1852  * if both options are set. Once the packet got to layer three, only
1853  * the corresponding tags will be read.
1854  */
1855  if (IsManualIpTos ())
1856  {
1857  SocketIpTosTag ipTosTag;
1858  ipTosTag.SetTos (GetIpTos ());
1859  p->AddPacketTag (ipTosTag);
1860  }
1861 
1862  if (IsManualIpv6Tclass ())
1863  {
1864  SocketIpv6TclassTag ipTclassTag;
1865  ipTclassTag.SetTclass (GetIpv6Tclass ());
1866  p->AddPacketTag (ipTclassTag);
1867  }
1868 
1869  if (IsManualIpTtl ())
1870  {
1871  SocketIpTtlTag ipTtlTag;
1872  ipTtlTag.SetTtl (GetIpTtl ());
1873  p->AddPacketTag (ipTtlTag);
1874  }
1875 
1876  if (IsManualIpv6HopLimit ())
1877  {
1878  SocketIpv6HopLimitTag ipHopLimitTag;
1879  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
1880  p->AddPacketTag (ipHopLimitTag);
1881  }
1882 
1883  if (m_closeOnEmpty && (remainingData == 0))
1884  {
1885  flags |= TcpHeader::FIN;
1886  if (m_state == ESTABLISHED)
1887  { // On active close: I am the first one to send FIN
1888  NS_LOG_INFO ("ESTABLISHED -> FIN_WAIT_1");
1889  m_state = FIN_WAIT_1;
1890  }
1891  else if (m_state == CLOSE_WAIT)
1892  { // On passive close: Peer sent me FIN already
1893  NS_LOG_INFO ("CLOSE_WAIT -> LAST_ACK");
1894  m_state = LAST_ACK;
1895  }
1896  }
1897  TcpHeader header;
1898  header.SetFlags (flags);
1899  header.SetSequenceNumber (seq);
1901  if (m_endPoint)
1902  {
1903  header.SetSourcePort (m_endPoint->GetLocalPort ());
1905  }
1906  else
1907  {
1908  header.SetSourcePort (m_endPoint6->GetLocalPort ());
1910  }
1911  header.SetWindowSize (AdvertisedWindowSize ());
1912  AddOptions (header);
1913  if (m_retxEvent.IsExpired () )
1914  { // Schedule retransmit
1915  m_rto = m_rtt->RetransmitTimeout ();
1916  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
1917  Simulator::Now ().GetSeconds () << " to expire at time " <<
1918  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
1920  }
1921  NS_LOG_LOGIC ("Send packet via TcpL4Protocol with flags 0x" << std::hex << static_cast<uint32_t> (flags) << std::dec);
1922  if (m_endPoint)
1923  {
1924  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
1926  }
1927  else
1928  {
1929  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
1931  }
1932  m_rtt->SentSeq (seq, sz); // notify the RTT
1933  // Notify the application of the data being sent unless this is a retransmit
1934  if (seq == m_nextTxSequence)
1935  {
1937  }
1938  // Update highTxMark
1939  m_highTxMark = std::max (seq + sz, m_highTxMark.Get ());
1940  return sz;
1941 }
1942 
1943 /* Send as much pending data as possible according to the Tx window. Note that
1944  * this function did not implement the PSH flag
1945  */
1946 bool
1948 {
1949  NS_LOG_FUNCTION (this << withAck);
1950  if (m_txBuffer.Size () == 0)
1951  {
1952  return false; // Nothing to send
1953 
1954  }
1955  if (m_endPoint == 0 && m_endPoint6 == 0)
1956  {
1957  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
1958  return false; // Is this the right way to handle this condition?
1959  }
1960  uint32_t nPacketsSent = 0;
1962  {
1963  uint32_t w = AvailableWindow (); // Get available window size
1964  NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" <<
1965  " w " << w <<
1966  " rxwin " << m_rWnd <<
1967  " segsize " << m_segmentSize <<
1968  " nextTxSeq " << m_nextTxSequence <<
1969  " highestRxAck " << m_txBuffer.HeadSequence () <<
1970  " pd->Size " << m_txBuffer.Size () <<
1971  " pd->SFS " << m_txBuffer.SizeFromSequence (m_nextTxSequence));
1972  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
1974  {
1975  break; // No more
1976  }
1977  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
1978  // in the buffer and the amount of data to send is less than one segment
1979  if (!m_noDelay && UnAckDataCount () > 0
1981  {
1982  NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send.");
1983  break;
1984  }
1985  uint32_t s = std::min (w, m_segmentSize); // Send no more than window
1986  uint32_t sz = SendDataPacket (m_nextTxSequence, s, withAck);
1987  nPacketsSent++; // Count sent this loop
1988  m_nextTxSequence += sz; // Advance next tx sequence
1989  }
1990  NS_LOG_LOGIC ("SendPendingData sent " << nPacketsSent << " packets");
1991  return (nPacketsSent > 0);
1992 }
1993 
1994 uint32_t
1996 {
1997  NS_LOG_FUNCTION (this);
1999 }
2000 
2001 uint32_t
2003 {
2004  NS_LOG_FUNCTION (this);
2005  return m_highTxMark.Get () - m_txBuffer.HeadSequence ();
2006 }
2007 
2008 uint32_t
2010 {
2011  NS_LOG_FUNCTION (this);
2012  return m_rWnd;
2013 }
2014 
2015 uint32_t
2017 {
2019  uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
2020  uint32_t win = Window (); // Number of bytes allowed to be outstanding
2021  NS_LOG_LOGIC ("UnAckCount=" << unack << ", Win=" << win);
2022  return (win < unack) ? 0 : (win - unack);
2023 }
2024 
2025 uint16_t
2027 {
2028  return std::min (m_rxBuffer.MaxBufferSize () - m_rxBuffer.Size (), (uint32_t)m_maxWinSize);
2029 }
2030 
2031 // Receipt of new packet, put into Rx buffer
2032 void
2034 {
2035  NS_LOG_FUNCTION (this << tcpHeader);
2036  NS_LOG_LOGIC ("seq " << tcpHeader.GetSequenceNumber () <<
2037  " ack " << tcpHeader.GetAckNumber () <<
2038  " pkt size " << p->GetSize () );
2039 
2040  // Put into Rx buffer
2041  SequenceNumber32 expectedSeq = m_rxBuffer.NextRxSequence ();
2042  if (!m_rxBuffer.Add (p, tcpHeader))
2043  { // Insert failed: No data or RX buffer full
2045  return;
2046  }
2047  // Now send a new ACK packet acknowledging all received and delivered data
2048  if (m_rxBuffer.Size () > m_rxBuffer.Available () || m_rxBuffer.NextRxSequence () > expectedSeq + p->GetSize ())
2049  { // A gap exists in the buffer, or we filled a gap: Always ACK
2051  }
2052  else
2053  { // In-sequence packet: ACK if delayed ack count allows
2055  {
2056  m_delAckEvent.Cancel ();
2057  m_delAckCount = 0;
2059  }
2060  else if (m_delAckEvent.IsExpired ())
2061  {
2064  NS_LOG_LOGIC (this << " scheduled delayed ACK at " << (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
2065  }
2066  }
2067  // Notify app to receive if necessary
2068  if (expectedSeq < m_rxBuffer.NextRxSequence ())
2069  { // NextRxSeq advanced, we have something to send to the app
2070  if (!m_shutdownRecv)
2071  {
2072  NotifyDataRecv ();
2073  }
2074  // Handle exceptions
2075  if (m_closeNotified)
2076  {
2077  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
2078  }
2079  // If we received FIN before and now completed all "holes" in rx buffer,
2080  // invoke peer close procedure
2081  if (m_rxBuffer.Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
2082  {
2083  DoPeerClose ();
2084  }
2085  }
2086 }
2087 
2088 /* Called by ForwardUp() to estimate RTT */
2089 void
2091 {
2092  // Use m_rtt for the estimation. Note, RTT of duplicated acknowledgement
2093  // (which should be ignored) is handled by m_rtt. Once timestamp option
2094  // is implemented, this function would be more elaborated.
2095  Time nextRtt = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
2096 
2097  //nextRtt will be zero for dup acks. Don't want to update lastRtt in that case
2098  //but still needed to do list clearing that is done in AckSeq.
2099  if(nextRtt != Time (0))
2100  {
2101  m_lastRtt = nextRtt;
2102  NS_LOG_FUNCTION(this << m_lastRtt);
2103  }
2104 
2105 }
2106 
2107 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
2108 // when the three-way handshake completed. This cancels retransmission timer
2109 // and advances Tx window
2110 void
2112 {
2113  NS_LOG_FUNCTION (this << ack);
2114 
2115  if (m_state != SYN_RCVD)
2116  { // Set RTO unless the ACK is received in SYN_RCVD state
2117  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2118  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2119  m_retxEvent.Cancel ();
2120  // On recieving a "New" ack we restart retransmission timer .. RFC 2988
2121  m_rto = m_rtt->RetransmitTimeout ();
2122  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
2123  Simulator::Now ().GetSeconds () << " to expire at time " <<
2124  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2126  }
2127  if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
2128  { // Zero window: Enter persist state to send 1 byte to probe
2129  NS_LOG_LOGIC (this << "Enter zerowindow persist state");
2130  NS_LOG_LOGIC (this << "Cancelled ReTxTimeout event which was set to expire at " <<
2131  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2132  m_retxEvent.Cancel ();
2133  NS_LOG_LOGIC ("Schedule persist timeout at time " <<
2134  Simulator::Now ().GetSeconds () << " to expire at time " <<
2135  (Simulator::Now () + m_persistTimeout).GetSeconds ());
2138  }
2139  // Note the highest ACK and tell app to send more
2140  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
2141  " numberAck " << (ack - m_txBuffer.HeadSequence ())); // Number bytes ack'ed
2142  m_txBuffer.DiscardUpTo (ack);
2143  if (GetTxAvailable () > 0)
2144  {
2146  }
2147  if (ack > m_nextTxSequence)
2148  {
2149  m_nextTxSequence = ack; // If advanced
2150  }
2151  if (m_txBuffer.Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
2152  { // No retransmit timer if no data to retransmit
2153  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2154  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2155  m_retxEvent.Cancel ();
2156  }
2157  // Try to send more data
2159 }
2160 
2161 // Retransmit timeout
2162 void
2164 {
2165  NS_LOG_FUNCTION (this);
2166  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
2167  // If erroneous timeout in closed/timed-wait state, just return
2168  if (m_state == CLOSED || m_state == TIME_WAIT)
2169  {
2170  return;
2171  }
2172  // If all data are received (non-closing socket and nothing to send), just return
2174  {
2175  return;
2176  }
2177 
2178  Retransmit ();
2179 }
2180 
2181 void
2183 {
2184  m_delAckCount = 0;
2186 }
2187 
2188 void
2190 {
2191  NS_LOG_FUNCTION (this);
2192 
2194  if (m_state == LAST_ACK)
2195  {
2196  CloseAndNotify ();
2197  }
2198  if (!m_closeNotified)
2199  {
2200  m_closeNotified = true;
2201  }
2202 }
2203 
2204 // Send 1-byte data to probe for the window size at the receiver when
2205 // the local knowledge tells that the receiver has zero window size
2206 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
2207 void
2209 {
2210  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
2211  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
2213  TcpHeader tcpHeader;
2214  tcpHeader.SetSequenceNumber (m_nextTxSequence);
2215  tcpHeader.SetAckNumber (m_rxBuffer.NextRxSequence ());
2216  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
2217  if (m_endPoint != 0)
2218  {
2219  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
2220  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
2221  }
2222  else
2223  {
2224  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
2225  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
2226  }
2227  AddOptions (tcpHeader);
2228 
2229  if (m_endPoint != 0)
2230  {
2231  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
2233  }
2234  else
2235  {
2236  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
2238  }
2239  NS_LOG_LOGIC ("Schedule persist timeout at time "
2240  << Simulator::Now ().GetSeconds () << " to expire at time "
2241  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
2243 }
2244 
2245 void
2247 {
2248  m_nextTxSequence = m_txBuffer.HeadSequence (); // Start from highest Ack
2249  m_rtt->IncreaseMultiplier (); // Double the timeout value for next retx timer
2250  m_dupAckCount = 0;
2251  DoRetransmit (); // Retransmit the packet
2252 }
2253 
2254 void
2256 {
2257  NS_LOG_FUNCTION (this);
2258  // Retransmit SYN packet
2259  if (m_state == SYN_SENT)
2260  {
2261  if (m_cnCount > 0)
2262  {
2264  }
2265  else
2266  {
2268  }
2269  return;
2270  }
2271  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
2272  if (m_txBuffer.Size () == 0)
2273  {
2274  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
2275  { // Must have lost FIN, re-send
2277  }
2278  return;
2279  }
2280  // Retransmit a data packet: Call SendDataPacket
2281  NS_LOG_LOGIC ("TcpSocketBase " << this << " retxing seq " << m_txBuffer.HeadSequence ());
2282  uint32_t sz = SendDataPacket (m_txBuffer.HeadSequence (), m_segmentSize, true);
2283  // In case of RTO, advance m_nextTxSequence
2284  m_nextTxSequence = std::max (m_nextTxSequence.Get (), m_txBuffer.HeadSequence () + sz);
2285 
2286 }
2287 
2288 void
2290 {
2291  m_retxEvent.Cancel ();
2293  m_delAckEvent.Cancel ();
2296 }
2297 
2298 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
2299 void
2301 {
2302  NS_LOG_INFO (TcpStateName[m_state] << " -> TIME_WAIT");
2303  m_state = TIME_WAIT;
2304  CancelAllTimers ();
2305  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
2306  // according to RFC793, p.28
2307  m_timewaitEvent = Simulator::Schedule (Seconds (2 * m_msl),
2309 }
2310 
2311 /* Below are the attribute get/set functions */
2312 
2313 void
2315 {
2317 }
2318 
2319 uint32_t
2321 {
2322  return m_txBuffer.MaxBufferSize ();
2323 }
2324 
2325 void
2327 {
2329 }
2330 
2331 uint32_t
2333 {
2334  return m_rxBuffer.MaxBufferSize ();
2335 }
2336 
2337 void
2339 {
2340  m_segmentSize = size;
2341  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
2342 }
2343 
2344 uint32_t
2346 {
2347  return m_segmentSize;
2348 }
2349 
2350 void
2352 {
2353  m_cnTimeout = timeout;
2354 }
2355 
2356 Time
2358 {
2359  return m_cnTimeout;
2360 }
2361 
2362 void
2364 {
2365  m_cnRetries = count;
2366 }
2367 
2368 uint32_t
2370 {
2371  return m_cnRetries;
2372 }
2373 
2374 void
2376 {
2378 }
2379 
2380 Time
2382 {
2383  return m_delAckTimeout;
2384 }
2385 
2386 void
2388 {
2389  m_delAckMaxCount = count;
2390 }
2391 
2392 uint32_t
2394 {
2395  return m_delAckMaxCount;
2396 }
2397 
2398 void
2400 {
2401  m_noDelay = noDelay;
2402 }
2403 
2404 bool
2406 {
2407  return m_noDelay;
2408 }
2409 
2410 void
2412 {
2414 }
2415 
2416 Time
2418 {
2419  return m_persistTimeout;
2420 }
2421 
2422 bool
2424 {
2425  // Broadcast is not implemented. Return true only if allowBroadcast==false
2426  return (!allowBroadcast);
2427 }
2428 
2429 bool
2431 {
2432  return false;
2433 }
2434 
2435 /* Placeholder function for future extension that reads more from the TCP header */
2436 void
2438 {
2439 }
2440 
2441 /* Placeholder function for future extension that changes the TCP header */
2442 void
2444 {
2445 }
2446 
2447 } // namespace ns3
static Time GetDelayLeft(const EventId &id)
Definition: simulator.cc:189
Ipv6Address GetLocalAddress()
Get the local address.
void PeerClose(Ptr< Packet > p, const TcpHeader &tcpHeader)
Received a FIN from peer, notify rx buffer.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void SetTclass(uint8_t tclass)
Set the tag's Tclass.
Definition: socket.cc:816
void ProcessListen(Ptr< Packet > packet, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Received a packet upon LISTEN state.
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
virtual int Listen(void)
Listen for incoming connections.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
bool IsManualIpTtl(void) const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:382
Doxygen introspection did not find any typical Config paths.
Definition: ipv6-header.h:33
an Inet address class
virtual int GetSockName(Address &address) const
Get socket address.
Ipv4Address GetIpv4(void) const
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
static Ipv4Address GetAny(void)
uint32_t Size(void) const
Returns total number of bytes in this Tx buffer.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void ProcessWait(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon CLOSE_WAIT, FIN_WAIT_1, FIN_WAIT_2.
SequenceNumber32 GetSequenceNumber() const
Definition: tcp-header.cc:96
virtual uint8_t GetIpTtl(void) const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:470
virtual uint16_t AdvertisedWindowSize(void)
The amount of Rx window announced to the peer.
Callback template class.
Definition: callback.h:924
bool Add(Ptr< Packet > p, TcpHeader const &tcph)
Insert a packet into the buffer and update the availBytes counter to reflect the number of bytes read...
bool m_noDelay
Set to true to disable Nagle's algorithm.
virtual uint32_t GetSegSize(void) const
Get the segment size.
uint8_t GetIpTos(void) const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:403
uint32_t SendDataPacket(SequenceNumber32 seq, uint32_t maxSize, bool withAck)
Extract at most maxSize bytes from the TxBuffer at sequence seq, add the TCP header, and send to TcpL4Protocol.
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer...
Definition: socket.h:1044
void DiscardUpTo(const SequenceNumber32 &seq)
Discard data up to but not including this sequence number.
(abstract) base class of all TcpSockets
Definition: tcp-socket.h:64
Ipv4EndPoint * m_endPoint
the IPv4 endpoint
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
uint8_t GetFlags() const
Definition: tcp-header.cc:108
virtual ~TcpSocketBase(void)
TracedValue< Time > m_lastRtt
Last RTT sample collected.
void NotifyDataRecv(void)
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:304
virtual int ShutdownRecv(void)
uint32_t SizeFromSequence(const SequenceNumber32 &seq) const
Returns the number of bytes from the buffer in the range [seq, tailSequence)
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv4Header, uint16_t, Ptr< Ipv4Interface > > callback)
Set the reception callback.
TcpSocketBase(void)
Create an unbound TCP socket.
EventId m_retxEvent
Retransmission event.
SequenceNumber32 HeadSequence(void) const
Returns the first byte's sequence number.
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:174
IPv6 layer implementation.
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
SequenceNumber32 GetAckNumber() const
Definition: tcp-header.cc:100
void ForwardUp6(Ptr< Packet > packet, Ipv6Header header, uint16_t port, Ptr< Ipv6Interface > incomingInterface)
Called by the L3 protocol when it received a packet to pass on to TCP.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:841
void SetAddress(Address addr)
Set the tag's address.
Definition: socket.cc:522
virtual void SetPersistTimeout(Time timeout)
Set the timout for persistent connection.
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
virtual bool GetAllowBroadcast(void) const
Query whether broadcast datagram transmissions are allowed.
EventId m_timewaitEvent
TIME_WAIT expiration event: Move this socket to CLOSED state.
void NotifyConnectionFailed(void)
Notify through the callback (if set) that the connection has not been established due to an error...
Definition: socket.cc:226
static TypeId GetTypeId(void)
Get the type ID.
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
uint32_t Available() const
Get the actual number of bytes available to be read.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
void SendRST(void)
Send reset and tear down this socket.
uint32_t MaxBufferSize(void) const
Returns the Tx window size.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
uint16_t m_maxWinSize
Maximum window size to advertise.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
bool IsManualIpTos(void) const
Checks if the socket has a specific IPv4 ToS set.
Definition: socket.cc:370
Callback< void, Ipv4Address, uint8_t, uint8_t, uint8_t, uint32_t > m_icmpCallback
ICMP callback.
void CancelAllTimers(void)
Cancel all timer when endpoint is deleted.
void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:223
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:495
Time m_cnTimeout
Timeout for connection retry.
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
uint32_t m_segmentSize
Segment size.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
EventId m_lastAckEvent
Last ACK timeout event.
void ConnectionSucceeded(void)
Schedule-friendly wrapper for Socket::NotifyConnectionSucceeded()
void SetFinSequence(const SequenceNumber32 &s)
Set the FIN Sequence number (i.e., the one closing the connection)
void SetTos(uint8_t tos)
Set the tag's TOS.
Definition: socket.cc:760
TracedValue< SequenceNumber32 > m_nextTxSequence
Next seqnum to be sent (SND.NXT), ReTx pushes it back.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received an ACK packet.
ns3::Time timeout
uint32_t m_cnCount
Count of remaining connection retries.
T Get(void) const
Definition: traced-value.h:99
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:996
virtual Time GetPersistTimeout(void) const
Get the timout for persistent connection.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
void DoPeerClose(void)
FIN is in sequence, notify app and respond with a FIN.
bool NotifyConnectionRequest(const Address &from)
Notify through the callback (if set) that an incoming connection is being requested by a remote host...
Definition: socket.cc:256
SequenceNumber32 NextRxSequence(void) const
Get Next Rx Sequence number.
virtual void PersistTimeout(void)
Send 1 byte probe to get an updated window size.
TracedValue< TcpStates_t > m_state
TCP state.
uint32_t m_delAckMaxCount
Number of packet to fire an ACK before delay timeout.
uint16_t port
Definition: dsdv-manet.cc:44
a polymophic address class
Definition: address.h:86
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
uint16_t GetPeerPort()
Get the peer port.
AttributeValue form of a Callback.
Definition: callback.h:1662
uint32_t m_cnRetries
Number of connection retries before giving up.
virtual uint32_t GetRcvBufSize(void) const
Get the receive buffer size.
uint32_t m_delAckCount
Delayed ACK counter.
virtual bool GetTcpNoDelay(void) const
Check if Nagle's algorithm is enabled or not.
void ForwardIcmp6(Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Called by the L3 protocol when it received an ICMPv6 packet to pass on to TCP.
virtual int Bind(void)
Allocate a local IPv4 endpoint for this socket.
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number
SequenceNumber32 MaxRxSequence(void) const
Get the lowest sequence number that this TcpRxBuffer cannot accept.
TcpTxBuffer m_txBuffer
Tx buffer.
virtual void Retransmit(void)
Halving cwnd and call DoRetransmit()
Packet header for IPv4.
Definition: ipv4-header.h:31
void SetLocalAddress(Ipv6Address addr)
Set the local address.
virtual void ReadOptions(const TcpHeader &tcpHeader)
Read option from incoming packets.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
virtual void EstimateRtt(const TcpHeader &tcpHeader)
Take into account the packet for RTT estimation.
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Definition: tcp-header.cc:63
virtual uint32_t UnAckDataCount(void)
Return count of number of unacked bytes.
void ForwardUp(Ptr< Packet > packet, Ipv4Header header, uint16_t port, Ptr< Ipv4Interface > incomingInterface)
Called by the L3 protocol when it received a packet to pass on to TCP.
static const char *const TcpStateName[LAST_STATE]
Literal names of TCP states for use in log messages.
Definition: tcp-socket.h:80
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:582
virtual uint32_t GetSndBufSize(void) const
Get the send buffer size.
virtual enum SocketType GetSocketType(void) const
uint16_t GetLocalPort()
Get the local port.
Hold an unsigned integer type.
Definition: uinteger.h:46
Ipv6EndPoint * m_endPoint6
the IPv6 endpoint
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Ptr< SampleEmitter > s
bool OutOfRange(SequenceNumber32 head, SequenceNumber32 tail) const
Check if a sequence number range is within the rx window.
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
Ipv4Address GetLocalAddress(void)
Get the local address.
An Inet6 address class.
virtual void SetTcpNoDelay(bool noDelay)
Enable/Disable Nagle's algorithm.
This class implements a tag that carries an address of a packet across the socket interface...
Definition: socket.h:948
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1242
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:376
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:284
virtual uint32_t GetConnCount(void) const
Get the number of connection retries before giving up.
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:127
enum SocketErrno m_errno
Socket error code.
Ipv4Address GetSource(void) const
Definition: ipv4-route.cc:56
void SetNextRxSequence(const SequenceNumber32 &s)
Set the Next Sequence number.
A base class for implementation of a stream socket using TCP.
Ptr< RttEstimator > m_rtt
Round trip time estimator.
bool m_closeNotified
Told app to close socket.
void ProcessSynSent(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon SYN_SENT.
int SetupCallback(void)
Common part of the two Bind(), i.e.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
virtual void SetTcp(Ptr< TcpL4Protocol > tcp)
Set the associated TCP L4 protocol.
Ptr< TcpL4Protocol > m_tcp
the associated TCP L4 protocol
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:642
void SetMaxBufferSize(uint32_t n)
Set the Tx window size.
void ProcessSynRcvd(Ptr< Packet > packet, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Received a packet upon SYN_RCVD.
virtual int ShutdownSend(void)
void SetDestinationPort(uint16_t port)
Definition: tcp-header.cc:59
void NotifyConnectionSucceeded(void)
Notify through the callback (if set) that the connection has been established.
Definition: socket.cc:216
uint32_t Available(void) const
Returns the available capacity in this Tx window.
void SetFlags(uint8_t flags)
Definition: tcp-header.cc:75
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
void SetMaxBufferSize(uint32_t s)
Set the Maximum buffer size.
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:388
virtual void SetDelAckMaxCount(uint32_t count)
Set the number of packet to fire an ACK before delay timeout.
void NotifyNormalClose(void)
Notify through the callback (if set) that the connection has been closed.
Definition: socket.cc:236
int DoConnect(void)
Perform the real connection tasks: Send SYN if allowed, RST if invalid.
void CompleteFork(Ptr< Packet > p, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Complete a connection by forking the socket.
virtual void AddOptions(TcpHeader &tcpHeader)
Add option to outgoing packets.
Ptr< Packet > Extract(uint32_t maxSize)
Extract data from the head of the buffer as indicated by nextRxSeq.
uint32_t m_dupAckCount
Dupack counter.
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ptr< Node > m_node
the associated node
void NotifyNewConnectionCreated(Ptr< Socket > socket, const Address &from)
Notify through the callback (if set) that a new connection has been created.
Definition: socket.cc:274
void TimeWait(void)
Move from CLOSING or FIN_WAIT_2 to TIME_WAIT state.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Header for the Transmission Control Protocol.
Definition: tcp-header.h:43
virtual void SetNode(Ptr< Node > node)
Set the associated node.
void SetIcmpCallback(Callback< void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
void SetSourcePort(uint16_t port)
Definition: tcp-header.cc:55
virtual uint32_t BytesInFlight(void)
Return total bytes in flight.
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1189
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:445
void Destroy(void)
Kill this socket by zeroing its attributes (IPv4)
bool Add(Ptr< Packet > p)
Append a data packet to the end of the buffer.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Schedule an event to expire Now.
Definition: simulator.h:986
virtual int Close(void)
Close a socket.
static Ipv4Address GetZero(void)
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer informations (address and port).
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
virtual uint32_t AvailableWindow(void)
Return unfilled portion of window.
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:120
virtual Ptr< TcpSocketBase > Fork(void)=0
Call CopyObject<> to clone me.
virtual void DupAck(const TcpHeader &tcpHeader, uint32_t count)=0
Received dupack (duplicate ACK)
virtual void SetRtt(Ptr< RttEstimator > rtt)
Set the associated RTT estimator.
double m_msl
Max segment lifetime.
virtual void ReTxTimeout(void)
Call Retransmit() upon RTO event.
TracedValue< SequenceNumber32 > m_highTxMark
Highest seqno ever sent, regardless of ReTx.
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:329
void SendEmptyPacket(uint8_t flags)
Send a empty packet that carries a flag, e.g.
Time m_delAckTimeout
Time to delay an ACK.
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call) ...
Definition: socket.cc:113
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
void SetLocalAddress(Ipv4Address address)
Set the local address.
virtual void SetSndBufSize(uint32_t size)
Set the send buffer size.
virtual void SetDelAckTimeout(Time timeout)
Set the time to delay an ACK.
virtual void NewAck(SequenceNumber32 const &seq)
Update buffers w.r.t.
void DeallocateEndPoint(void)
Deallocate m_endPoint and m_endPoint6.
TcpRxBuffer m_rxBuffer
Rx buffer (reordering buffer)
Describes an IPv6 address.
Definition: ipv6-address.h:46
uint32_t MaxBufferSize(void) const
Get the Maximum buffer size.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
void ProcessEstablished(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon ESTABLISHED state.
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:911
bool m_connected
Connection established.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:136
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if cond is true.
Definition: abort.h:101
TracedValue< Time > m_rto
Retransmit timeout.
uint16_t GetLocalPort(void)
Get the local port.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:203
void SetAckNumber(SequenceNumber32 ackNumber)
Definition: tcp-header.cc:67
Ipv6Address GetPeerAddress()
Get the peer address.
int DoClose(void)
Close a socket by sending RST, FIN, or FIN+ACK, depend on the current state.
virtual void SetConnCount(uint32_t count)
Set the number of connection retries before giving up.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
Ipv4Address GetPeerAddress(void)
Get the peer address.
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv6Header, uint16_t, Ptr< Ipv6Interface > > callback)
Set the reception callback.
static bool IsMatchingType(const Address &addr)
If the address match.
uint16_t GetPeerPort(void)
Get the peer port.
uint16_t GetPort(void) const
Get the port.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::cancel method.
Definition: event-id.cc:47
virtual uint32_t Window(void)
Return the max possible number of unacked bytes.
virtual enum SocketErrno GetErrno(void) const
Get last error number.
void ProcessLastAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon LAST_ACK.
Ipv4Address GetIpv4MappedAddress() const
Return the Ipv4 address.
virtual void SetSegSize(uint32_t size)
Set the segment size.
void ProcessClosing(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon CLOSING.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:193
uint16_t GetPort(void) const
virtual void ReceivedData(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Recv of a data, put into buffer, call L7 to get it if necessary.
void SetConnectCallback(Callback< void, Ptr< Socket > > connectionSucceeded, Callback< void, Ptr< Socket > > connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:83
void CloseAndNotify(void)
Peacefully close the socket by notifying the upper layer and deallocate end point.
Callback< void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t > m_icmpCallback6
ICMPv6 callback.
tuple address
Definition: first.py:37
virtual Ptr< Node > GetNode(void) const
Return the node this socket is associated with.
virtual void SetRcvBufSize(uint32_t size)
Set the receive buffer size.
bool m_shutdownRecv
Receive no longer allowed.
virtual Time GetDelAckTimeout(void) const
Get the time to delay an ACK.
virtual void DelAckTimeout(void)
Action upon delay ACK timeout, i.e.
virtual void LastAckTimeout(void)
Timeout at LAST_ACK, close the connection.
uint32_t Size(void) const
Get the actual buffer occupancy.
void SetWindowSize(uint16_t windowSize)
Definition: tcp-header.cc:79
Hold a floating point type.
Definition: double.h:41
virtual void DoForwardUp(Ptr< Packet > packet, Ipv4Header header, uint16_t port, Ptr< Ipv4Interface > incomingInterface)
Called by TcpSocketBase::ForwardUp().
virtual int Bind6(void)
Allocate a local IPv6 endpoint for this socket.
indicates whether the socket has IP_TOS set.
Definition: socket.h:1142
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::isExpired method.
Definition: event-id.cc:53
Ptr< T > GetObject(void) const
Definition: object.h:362
void SetIcmpCallback(Callback< void, Ipv4Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
bool IsIpv4MappedAddress() const
If the address is an IPv4-mapped address.
EventId m_delAckEvent
Delayed ACK timeout event.
a unique identifier for an interface.
Definition: type-id.h:49
bool m_shutdownSend
Send no longer allowed.
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
int SetupEndpoint6(void)
Configure the endpoint v6 to a local address.
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:294
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
bool SendPendingData(bool withAck=false)
Send as much pending data as possible according to the Tx window.
void ForwardIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Called by the L3 protocol when it received an ICMP packet to pass on to TCP.
TracedValue< uint32_t > m_rWnd
Flow control window at remote side.
static bool IsMatchingType(const Address &address)
void NotifyErrorClose(void)
Notify through the callback (if set) that the connection has been closed due to an error...
Definition: socket.cc:246
virtual void DoRetransmit(void)
Retransmit the oldest packet.
bool m_closeOnEmpty
Close socket upon tx buffer emptied.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
virtual uint32_t GetDelAckMaxCount(void) const
Get the number of packet to fire an ACK before delay timeout.
virtual void SetConnTimeout(Time timeout)
Set the connection timeout.
EventId m_persistEvent
Persist event: Send 1 byte to probe for a non-zero Rx window.
void SetPeer(Ipv6Address addr, uint16_t port)
Set the peer informations (address and port).
int SetupEndpoint(void)
Configure the endpoint to a local address.
virtual Time GetConnTimeout(void) const
Get the connection timeout.
bool Finished(void)
Check if the buffer did receive all the data (and the connection is closed)
void Destroy6(void)
Kill this socket by zeroing its attributes (IPv6)
void SetHeadSequence(const SequenceNumber32 &seq)
Set the m_firstByteSeq to seq.
Time m_persistTimeout
Time between sending 1-byte probes.
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
virtual uint32_t GetRxAvailable(void) const
Return number of bytes which can be returned from one or multiple calls to Recv.
Ptr< Packet > CopyFromSequence(uint32_t numBytes, const SequenceNumber32 &seq)
Copy data of size numBytes into a packet, data from the range [seq, seq+numBytes) ...