A Discrete-Event Network Simulator
API
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/pointer.h"
43 #include "ns3/trace-source-accessor.h"
44 #include "tcp-socket-base.h"
45 #include "tcp-l4-protocol.h"
46 #include "ipv4-end-point.h"
47 #include "ipv6-end-point.h"
48 #include "ipv6-l3-protocol.h"
49 #include "tcp-header.h"
50 #include "tcp-option-winscale.h"
51 #include "tcp-option-ts.h"
52 #include "rtt-estimator.h"
53 
54 #include <math.h>
55 #include <algorithm>
56 
57 namespace ns3 {
58 
59 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
60 
61 NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
62 
63 TypeId
65 {
66  static TypeId tid = TypeId ("ns3::TcpSocketBase")
67  .SetParent<TcpSocket> ()
68  .SetGroupName ("Internet")
69 // .AddAttribute ("TcpState", "State in TCP state machine",
70 // TypeId::ATTR_GET,
71 // EnumValue (CLOSED),
72 // MakeEnumAccessor (&TcpSocketBase::m_state),
73 // MakeEnumChecker (CLOSED, "Closed"))
74  .AddAttribute ("MaxSegLifetime",
75  "Maximum segment lifetime in seconds, use for TIME_WAIT state transition to CLOSED state",
76  DoubleValue (120), /* RFC793 says MSL=2 minutes*/
78  MakeDoubleChecker<double> (0))
79  .AddAttribute ("MaxWindowSize", "Max size of advertised window",
80  UintegerValue (65535),
82  MakeUintegerChecker<uint16_t> ())
83  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
84  CallbackValue (),
87  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
88  CallbackValue (),
91  .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option",
92  BooleanValue (true),
95  .AddAttribute ("Timestamp", "Enable or disable Timestamp option",
96  BooleanValue (true),
99  .AddAttribute ("MinRto",
100  "Minimum retransmit timeout value",
101  TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, but Linux uses 200ms. See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
104  MakeTimeChecker ())
105  .AddAttribute ("ClockGranularity",
106  "Clock Granularity used in RTO calculations",
107  TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
110  MakeTimeChecker ())
111  .AddAttribute ("TxBuffer",
112  "TCP Tx buffer",
113  PointerValue (),
115  MakePointerChecker<TcpTxBuffer> ())
116  .AddAttribute ("RxBuffer",
117  "TCP Rx buffer",
118  PointerValue (),
120  MakePointerChecker<TcpRxBuffer> ())
121  .AddTraceSource ("RTO",
122  "Retransmission timeout",
124  "ns3::Time::TracedValueCallback")
125  .AddTraceSource ("RTT",
126  "Last RTT sample",
128  "ns3::Time::TracedValueCallback")
129  .AddTraceSource ("NextTxSequence",
130  "Next sequence number to send (SND.NXT)",
132  "ns3::SequenceNumber32TracedValueCallback")
133  .AddTraceSource ("HighestSequence",
134  "Highest sequence number ever sent in socket's life time",
136  "ns3::SequenceNumber32TracedValueCallback")
137  .AddTraceSource ("State",
138  "TCP state",
140  "ns3::TcpStatesTracedValueCallback")
141  .AddTraceSource ("RWND",
142  "Remote side's flow control window",
144  "ns3::TracedValue::Uint32Callback")
145  .AddTraceSource ("HighestRxSequence",
146  "Highest sequence number received from peer",
148  "ns3::SequenceNumber32TracedValueCallback")
149  .AddTraceSource ("HighestRxAck",
150  "Highest ack received from peer",
152  "ns3::SequenceNumber32TracedValueCallback")
153  ;
154  return tid;
155 }
156 
158  : m_dupAckCount (0),
159  m_delAckCount (0),
160  m_endPoint (0),
161  m_endPoint6 (0),
162  m_node (0),
163  m_tcp (0),
164  m_rtt (0),
165  m_nextTxSequence (0),
166  // Change this for non-zero initial sequence number
167  m_highTxMark (0),
168  m_rxBuffer (0),
169  m_txBuffer (0),
170  m_state (CLOSED),
171  m_errno (ERROR_NOTERROR),
172  m_closeNotified (false),
173  m_closeOnEmpty (false),
174  m_shutdownSend (false),
175  m_shutdownRecv (false),
176  m_connected (false),
177  m_segmentSize (0),
178  // For attribute initialization consistency (quiet valgrind)
179  m_rWnd (0),
180  m_highRxMark (0),
181  m_highRxAckMark (0),
182  m_sndScaleFactor (0),
183  m_rcvScaleFactor (0),
184  m_timestampEnabled (true),
185  m_timestampToEcho (0)
186 
187 {
188  NS_LOG_FUNCTION (this);
189  m_rxBuffer = CreateObject<TcpRxBuffer> ();
190  m_txBuffer = CreateObject<TcpTxBuffer> ();
191 }
192 
194  : TcpSocket (sock),
195  //copy object::m_tid and socket::callbacks
196  m_dupAckCount (sock.m_dupAckCount),
197  m_delAckCount (0),
198  m_delAckMaxCount (sock.m_delAckMaxCount),
199  m_noDelay (sock.m_noDelay),
200  m_cnRetries (sock.m_cnRetries),
201  m_delAckTimeout (sock.m_delAckTimeout),
202  m_persistTimeout (sock.m_persistTimeout),
203  m_cnTimeout (sock.m_cnTimeout),
204  m_endPoint (0),
205  m_endPoint6 (0),
206  m_node (sock.m_node),
207  m_tcp (sock.m_tcp),
208  m_rtt (0),
209  m_nextTxSequence (sock.m_nextTxSequence),
210  m_highTxMark (sock.m_highTxMark),
211  m_state (sock.m_state),
212  m_errno (sock.m_errno),
213  m_closeNotified (sock.m_closeNotified),
214  m_closeOnEmpty (sock.m_closeOnEmpty),
215  m_shutdownSend (sock.m_shutdownSend),
216  m_shutdownRecv (sock.m_shutdownRecv),
217  m_connected (sock.m_connected),
218  m_msl (sock.m_msl),
219  m_segmentSize (sock.m_segmentSize),
220  m_maxWinSize (sock.m_maxWinSize),
221  m_rWnd (sock.m_rWnd),
222  m_highRxMark (sock.m_highRxMark),
223  m_highRxAckMark (sock.m_highRxAckMark),
224  m_winScalingEnabled (sock.m_winScalingEnabled),
225  m_sndScaleFactor (sock.m_sndScaleFactor),
226  m_rcvScaleFactor (sock.m_rcvScaleFactor),
227  m_timestampEnabled (sock.m_timestampEnabled),
228  m_timestampToEcho (sock.m_timestampToEcho)
229 
230 {
231  NS_LOG_FUNCTION (this);
232  NS_LOG_LOGIC ("Invoked the copy constructor");
233  // Copy the rtt estimator if it is set
234  if (sock.m_rtt)
235  {
236  m_rtt = sock.m_rtt->Copy ();
237  }
238  // Reset all callbacks to null
239  Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
240  Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
241  Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
242  SetConnectCallback (vPS, vPS);
243  SetDataSentCallback (vPSUI);
244  SetSendCallback (vPSUI);
245  SetRecvCallback (vPS);
248 }
249 
251 {
252  NS_LOG_FUNCTION (this);
253  m_node = 0;
254  if (m_endPoint != 0)
255  {
256  NS_ASSERT (m_tcp != 0);
257  /*
258  * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
259  * DestroyCallback is set to TcpSocketBase::Destroy. If we called
260  * m_tcp->DeAllocate, it wil destroy its Ipv4EndpointDemux::DeAllocate,
261  * which in turn destroys my m_endPoint, and in turn invokes
262  * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
263  */
264  NS_ASSERT (m_endPoint != 0);
265  m_tcp->DeAllocate (m_endPoint);
266  NS_ASSERT (m_endPoint == 0);
267  }
268  if (m_endPoint6 != 0)
269  {
270  NS_ASSERT (m_tcp != 0);
271  NS_ASSERT (m_endPoint6 != 0);
272  m_tcp->DeAllocate (m_endPoint6);
273  NS_ASSERT (m_endPoint6 == 0);
274  }
275  m_tcp = 0;
276  CancelAllTimers ();
277 }
278 
279 /* Associate a node with this TCP socket */
280 void
282 {
283  m_node = node;
284 }
285 
286 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
287 void
289 {
290  m_tcp = tcp;
291 }
292 
293 /* Set an RTT estimator with this socket */
294 void
296 {
297  m_rtt = rtt;
298 }
299 
300 /* Inherit from Socket class: Returns error code */
303 {
304  return m_errno;
305 }
306 
307 /* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
310 {
311  return NS3_SOCK_STREAM;
312 }
313 
314 /* Inherit from Socket class: Returns associated node */
315 Ptr<Node>
317 {
319  return m_node;
320 }
321 
322 /* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
323 int
325 {
326  NS_LOG_FUNCTION (this);
327  m_endPoint = m_tcp->Allocate ();
328  if (0 == m_endPoint)
329  {
331  return -1;
332  }
333 
334  if (std::find(m_tcp->m_sockets.begin(), m_tcp->m_sockets.end(), this) == m_tcp->m_sockets.end())
335  {
336  m_tcp->m_sockets.push_back (this);
337  }
338  return SetupCallback ();
339 }
340 
341 int
343 {
344  NS_LOG_FUNCTION (this);
345  m_endPoint6 = m_tcp->Allocate6 ();
346  if (0 == m_endPoint6)
347  {
349  return -1;
350  }
351 
352  if (std::find(m_tcp->m_sockets.begin(), m_tcp->m_sockets.end(), this) == m_tcp->m_sockets.end())
353  {
354  m_tcp->m_sockets.push_back (this);
355  }
356  return SetupCallback ();
357 }
358 
359 /* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
360 int
362 {
363  NS_LOG_FUNCTION (this << address);
364  if (InetSocketAddress::IsMatchingType (address))
365  {
367  Ipv4Address ipv4 = transport.GetIpv4 ();
368  uint16_t port = transport.GetPort ();
369  if (ipv4 == Ipv4Address::GetAny () && port == 0)
370  {
371  m_endPoint = m_tcp->Allocate ();
372  }
373  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
374  {
375  m_endPoint = m_tcp->Allocate (port);
376  }
377  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
378  {
379  m_endPoint = m_tcp->Allocate (ipv4);
380  }
381  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
382  {
383  m_endPoint = m_tcp->Allocate (ipv4, port);
384  }
385  if (0 == m_endPoint)
386  {
388  return -1;
389  }
390  }
391  else if (Inet6SocketAddress::IsMatchingType (address))
392  {
394  Ipv6Address ipv6 = transport.GetIpv6 ();
395  uint16_t port = transport.GetPort ();
396  if (ipv6 == Ipv6Address::GetAny () && port == 0)
397  {
398  m_endPoint6 = m_tcp->Allocate6 ();
399  }
400  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
401  {
402  m_endPoint6 = m_tcp->Allocate6 (port);
403  }
404  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
405  {
406  m_endPoint6 = m_tcp->Allocate6 (ipv6);
407  }
408  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
409  {
410  m_endPoint6 = m_tcp->Allocate6 (ipv6, port);
411  }
412  if (0 == m_endPoint6)
413  {
415  return -1;
416  }
417  }
418  else
419  {
421  return -1;
422  }
423 
424  if (std::find(m_tcp->m_sockets.begin(), m_tcp->m_sockets.end(), this) == m_tcp->m_sockets.end())
425  {
426  m_tcp->m_sockets.push_back (this);
427  }
428  NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
429 
430  return SetupCallback ();
431 }
432 
433 /* Inherit from Socket class: Initiate connection to a remote address:port */
434 int
436 {
437  NS_LOG_FUNCTION (this << address);
438 
439  // If haven't do so, Bind() this socket first
440  if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0)
441  {
442  if (m_endPoint == 0)
443  {
444  if (Bind () == -1)
445  {
446  NS_ASSERT (m_endPoint == 0);
447  return -1; // Bind() failed
448  }
449  NS_ASSERT (m_endPoint != 0);
450  }
452  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
453  m_endPoint6 = 0;
454 
455  // Get the appropriate local address and port number from the routing protocol and set up endpoint
456  if (SetupEndpoint () != 0)
457  { // Route to destination does not exist
458  return -1;
459  }
460  }
461  else if (Inet6SocketAddress::IsMatchingType (address) && m_endPoint == 0)
462  {
463  // If we are operating on a v4-mapped address, translate the address to
464  // a v4 address and re-call this function
466  Ipv6Address v6Addr = transport.GetIpv6 ();
467  if (v6Addr.IsIpv4MappedAddress () == true)
468  {
469  Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
470  return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
471  }
472 
473  if (m_endPoint6 == 0)
474  {
475  if (Bind6 () == -1)
476  {
477  NS_ASSERT (m_endPoint6 == 0);
478  return -1; // Bind() failed
479  }
480  NS_ASSERT (m_endPoint6 != 0);
481  }
482  m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
483  m_endPoint = 0;
484 
485  // Get the appropriate local address and port number from the routing protocol and set up endpoint
486  if (SetupEndpoint6 () != 0)
487  { // Route to destination does not exist
488  return -1;
489  }
490  }
491  else
492  {
494  return -1;
495  }
496 
497  // Re-initialize parameters in case this socket is being reused after CLOSE
498  m_rtt->Reset ();
500 
501  // DoConnect() will do state-checking and send a SYN packet
502  return DoConnect ();
503 }
504 
505 /* Inherit from Socket class: Listen on the endpoint for an incoming connection */
506 int
508 {
509  NS_LOG_FUNCTION (this);
510  // Linux quits EINVAL if we're not in CLOSED state, so match what they do
511  if (m_state != CLOSED)
512  {
514  return -1;
515  }
516  // In other cases, set the state to LISTEN and done
517  NS_LOG_INFO ("CLOSED -> LISTEN");
518  m_state = LISTEN;
519  return 0;
520 }
521 
522 /* Inherit from Socket class: Kill this socket and signal the peer (if any) */
523 int
525 {
526  NS_LOG_FUNCTION (this);
530  if (m_rxBuffer->Size () != 0)
531  {
532  NS_LOG_INFO ("Socket " << this << " << unread rx data during close. Sending reset");
533  SendRST ();
534  return 0;
535  }
536 
537  if (m_txBuffer->SizeFromSequence (m_nextTxSequence) > 0)
538  { // App close with pending data must wait until all data transmitted
539  if (m_closeOnEmpty == false)
540  {
541  m_closeOnEmpty = true;
542  NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
543  }
544  return 0;
545  }
546  return DoClose ();
547 }
548 
549 /* Inherit from Socket class: Signal a termination of send */
550 int
552 {
553  NS_LOG_FUNCTION (this);
554 
555  //this prevents data from being added to the buffer
556  m_shutdownSend = true;
557  m_closeOnEmpty = true;
558  //if buffer is already empty, send a fin now
559  //otherwise fin will go when buffer empties.
560  if (m_txBuffer->Size () == 0)
561  {
562  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
563  {
564  NS_LOG_INFO("Emtpy tx buffer, send fin");
566 
567  if (m_state == ESTABLISHED)
568  { // On active close: I am the first one to send FIN
569  NS_LOG_INFO ("ESTABLISHED -> FIN_WAIT_1");
571  }
572  else
573  { // On passive close: Peer sent me FIN already
574  NS_LOG_INFO ("CLOSE_WAIT -> LAST_ACK");
575  m_state = LAST_ACK;
576  }
577  }
578  }
579 
580  return 0;
581 }
582 
583 /* Inherit from Socket class: Signal a termination of receive */
584 int
586 {
587  NS_LOG_FUNCTION (this);
588  m_shutdownRecv = true;
589  return 0;
590 }
591 
592 /* Inherit from Socket class: Send a packet. Parameter flags is not used.
593  Packet has no TCP header. Invoked by upper-layer application */
594 int
595 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
596 {
597  NS_LOG_FUNCTION (this << p);
598  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
600  {
601  // Store the packet into Tx buffer
602  if (!m_txBuffer->Add (p))
603  { // TxBuffer overflow, send failed
605  return -1;
606  }
607  if (m_shutdownSend)
608  {
610  return -1;
611  }
612  // Submit the data to lower layers
613  NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]);
614  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
615  { // Try to send the data out
617  {
619  }
620  }
621  return p->GetSize ();
622  }
623  else
624  { // Connection not established yet
626  return -1; // Send failure
627  }
628 }
629 
630 /* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
631 int
633 {
634  return Send (p, flags); // SendTo() and Send() are the same
635 }
636 
637 /* Inherit from Socket class: Return data to upper-layer application. Parameter flags
638  is not used. Data is returned as a packet of size no larger than maxSize */
640 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
641 {
642  NS_LOG_FUNCTION (this);
643  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
644  if (m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT)
645  {
646  return Create<Packet> (); // Send EOF on connection close
647  }
648  Ptr<Packet> outPacket = m_rxBuffer->Extract (maxSize);
649  if (outPacket != 0 && outPacket->GetSize () != 0)
650  {
651  SocketAddressTag tag;
652  if (m_endPoint != 0)
653  {
655  }
656  else if (m_endPoint6 != 0)
657  {
659  }
660  outPacket->AddPacketTag (tag);
661  }
662  return outPacket;
663 }
664 
665 /* Inherit from Socket class: Recv and return the remote's address */
667 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
668 {
669  NS_LOG_FUNCTION (this << maxSize << flags);
670  Ptr<Packet> packet = Recv (maxSize, flags);
671  // Null packet means no data to read, and an empty packet indicates EOF
672  if (packet != 0 && packet->GetSize () != 0)
673  {
674  if (m_endPoint != 0)
675  {
677  }
678  else if (m_endPoint6 != 0)
679  {
681  }
682  else
683  {
684  fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
685  }
686  }
687  return packet;
688 }
689 
690 /* Inherit from Socket class: Get the max number of bytes an app can send */
691 uint32_t
693 {
694  NS_LOG_FUNCTION (this);
695  return m_txBuffer->Available ();
696 }
697 
698 /* Inherit from Socket class: Get the max number of bytes an app can read */
699 uint32_t
701 {
702  NS_LOG_FUNCTION (this);
703  return m_rxBuffer->Available ();
704 }
705 
706 /* Inherit from Socket class: Return local address:port */
707 int
709 {
710  NS_LOG_FUNCTION (this);
711  if (m_endPoint != 0)
712  {
714  }
715  else if (m_endPoint6 != 0)
716  {
718  }
719  else
720  { // It is possible to call this method on a socket without a name
721  // in which case, behavior is unspecified
722  // Should this return an InetSocketAddress or an Inet6SocketAddress?
723  address = InetSocketAddress (Ipv4Address::GetZero (), 0);
724  }
725  return 0;
726 }
727 
728 /* Inherit from Socket class: Bind this socket to the specified NetDevice */
729 void
731 {
732  NS_LOG_FUNCTION (netdevice);
733  Socket::BindToNetDevice (netdevice); // Includes sanity check
734  if (m_endPoint == 0)
735  {
736  if (Bind () == -1)
737  {
738  NS_ASSERT (m_endPoint == 0);
739  return;
740  }
741  NS_ASSERT (m_endPoint != 0);
742  }
743  m_endPoint->BindToNetDevice (netdevice);
744 
745  if (m_endPoint6 == 0)
746  {
747  if (Bind6 () == -1)
748  {
749  NS_ASSERT (m_endPoint6 == 0);
750  return;
751  }
752  NS_ASSERT (m_endPoint6 != 0);
753  }
754  m_endPoint6->BindToNetDevice (netdevice);
755 
756  return;
757 }
758 
759 /* Clean up after Bind. Set up callback functions in the end-point. */
760 int
762 {
763  NS_LOG_FUNCTION (this);
764 
765  if (m_endPoint == 0 && m_endPoint6 == 0)
766  {
767  return -1;
768  }
769  if (m_endPoint != 0)
770  {
774  }
775  if (m_endPoint6 != 0)
776  {
780  }
781 
782  return 0;
783 }
784 
785 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
786 int
788 {
789  NS_LOG_FUNCTION (this);
790 
791  // A new connection is allowed only if this socket does not have a connection
793  { // send a SYN packet and change state into SYN_SENT
795  NS_LOG_INFO (TcpStateName[m_state] << " -> SYN_SENT");
796  m_state = SYN_SENT;
797  }
798  else if (m_state != TIME_WAIT)
799  { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
800  // exists. We send RST, tear down everything, and close this socket.
801  SendRST ();
802  CloseAndNotify ();
803  }
804  return 0;
805 }
806 
807 /* Do the action to close the socket. Usually send a packet with appropriate
808  flags depended on the current m_state. */
809 int
811 {
812  NS_LOG_FUNCTION (this);
813  switch (m_state)
814  {
815  case SYN_RCVD:
816  case ESTABLISHED:
817  // send FIN to close the peer
819  NS_LOG_INFO ("ESTABLISHED -> FIN_WAIT_1");
821  break;
822  case CLOSE_WAIT:
823  // send FIN+ACK to close the peer
825  NS_LOG_INFO ("CLOSE_WAIT -> LAST_ACK");
826  m_state = LAST_ACK;
827  break;
828  case SYN_SENT:
829  case CLOSING:
830  // Send RST if application closes in SYN_SENT and CLOSING
831  SendRST ();
832  CloseAndNotify ();
833  break;
834  case LISTEN:
835  case LAST_ACK:
836  // In these three states, move to CLOSED and tear down the end point
837  CloseAndNotify ();
838  break;
839  case CLOSED:
840  case FIN_WAIT_1:
841  case FIN_WAIT_2:
842  case TIME_WAIT:
843  default: /* mute compiler */
844  // Do nothing in these four states
845  break;
846  }
847  return 0;
848 }
849 
850 /* Peacefully close the socket by notifying the upper layer and deallocate end point */
851 void
853 {
854  NS_LOG_FUNCTION (this);
855 
856  if (!m_closeNotified)
857  {
859  m_closeNotified = true;
860  }
861 
862  NS_LOG_INFO (TcpStateName[m_state] << " -> CLOSED");
863  m_state = CLOSED;
864  DeallocateEndPoint ();
865 }
866 
867 
868 /* Tell if a sequence number range is out side the range that my rx buffer can
869  accpet */
870 bool
872 {
873  if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
874  { // Rx buffer in these states are not initialized.
875  return false;
876  }
877  if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
878  { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
879  // sequence number must equals to m_rxBuffer->NextRxSequence ()
880  return (m_rxBuffer->NextRxSequence () != head);
881  }
882 
883  // In all other cases, check if the sequence number is in range
884  return (tail < m_rxBuffer->NextRxSequence () || m_rxBuffer->MaxRxSequence () <= head);
885 }
886 
887 /* Function called by the L3 protocol when it received a packet to pass on to
888  the TCP. This function is registered as the "RxCallback" function in
889  SetupCallback(), which invoked by Bind(), and CompleteFork() */
890 void
892  Ptr<Ipv4Interface> incomingInterface)
893 {
894  DoForwardUp (packet, header, port, incomingInterface);
895 }
896 
897 void
898 TcpSocketBase::ForwardUp6 (Ptr<Packet> packet, Ipv6Header header, uint16_t port, Ptr<Ipv6Interface> incomingInterface)
899 {
900  DoForwardUp (packet, header, port);
901 }
902 
903 void
904 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
905  uint8_t icmpType, uint8_t icmpCode,
906  uint32_t icmpInfo)
907 {
908  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
909  (uint32_t)icmpCode << icmpInfo);
910  if (!m_icmpCallback.IsNull ())
911  {
912  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
913  }
914 }
915 
916 void
917 TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
918  uint8_t icmpType, uint8_t icmpCode,
919  uint32_t icmpInfo)
920 {
921  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
922  (uint32_t)icmpCode << icmpInfo);
923  if (!m_icmpCallback6.IsNull ())
924  {
925  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
926  }
927 }
928 
929 /* The real function to handle the incoming packet from lower layers. This is
930  wrapped by ForwardUp() so that this function can be overloaded by daughter
931  classes. */
932 void
934  Ptr<Ipv4Interface> incomingInterface)
935 {
936  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
938  ":" << m_endPoint->GetPeerPort () <<
939  " to " << m_endPoint->GetLocalAddress () <<
940  ":" << m_endPoint->GetLocalPort ());
941  Address fromAddress = InetSocketAddress (header.GetSource (), port);
942  Address toAddress = InetSocketAddress (header.GetDestination (), m_endPoint->GetLocalPort ());
943 
944  // Peel off TCP header and do validity checking
945  TcpHeader tcpHeader;
946  uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader);
947  if (bytesRemoved == 0 || bytesRemoved > 60)
948  {
949  NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid");
950  return; // Discard invalid packet
951  }
952 
953  ReadOptions (tcpHeader);
954 
955  if (tcpHeader.GetFlags () & TcpHeader::ACK)
956  {
957  EstimateRtt (tcpHeader);
958  }
959 
960  // Discard fully out of range data packets
961  if (packet->GetSize ()
962  && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
963  {
964  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
965  " received packet of seq [" << tcpHeader.GetSequenceNumber () <<
966  ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
967  ") out of range [" << m_rxBuffer->NextRxSequence () << ":" <<
968  m_rxBuffer->MaxRxSequence () << ")");
969  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
970  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
971  {
973  }
974  return;
975  }
976 
977  // Update Rx window size, i.e. the flow control window
978  if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0 && m_persistEvent.IsRunning ())
979  { // persist probes end
980  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
982  }
983  if (tcpHeader.GetFlags () & TcpHeader::ACK)
984  {
985  UpdateWindowSize (tcpHeader);
986  }
987 
988  // TCP state machine code in different process functions
989  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
990  switch (m_state)
991  {
992  case ESTABLISHED:
993  ProcessEstablished (packet, tcpHeader);
994  break;
995  case LISTEN:
996  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
997  break;
998  case TIME_WAIT:
999  // Do nothing
1000  break;
1001  case CLOSED:
1002  // Send RST if the incoming packet is not a RST
1003  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1004  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1005  TcpHeader h;
1008  h.SetAckNumber (m_rxBuffer->NextRxSequence ());
1009  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1010  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1012  AddOptions (h);
1013  m_tcp->SendPacket (Create<Packet> (), h, header.GetDestination (), header.GetSource (), m_boundnetdevice);
1014  }
1015  break;
1016  case SYN_SENT:
1017  ProcessSynSent (packet, tcpHeader);
1018  break;
1019  case SYN_RCVD:
1020  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1021  break;
1022  case FIN_WAIT_1:
1023  case FIN_WAIT_2:
1024  case CLOSE_WAIT:
1025  ProcessWait (packet, tcpHeader);
1026  break;
1027  case CLOSING:
1028  ProcessClosing (packet, tcpHeader);
1029  break;
1030  case LAST_ACK:
1031  ProcessLastAck (packet, tcpHeader);
1032  break;
1033  default: // mute compiler
1034  break;
1035  }
1036 }
1037 
1038 // XXX this is duplicate code with the other DoForwardUp()
1039 void
1041 {
1042  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1044  ":" << m_endPoint6->GetPeerPort () <<
1045  " to " << m_endPoint6->GetLocalAddress () <<
1046  ":" << m_endPoint6->GetLocalPort ());
1047  Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port);
1049 
1050  // Peel off TCP header and do validity checking
1051  TcpHeader tcpHeader;
1052  uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader);
1053  if (bytesRemoved == 0 || bytesRemoved > 60)
1054  {
1055  NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid");
1056  return; // Discard invalid packet
1057  }
1058 
1059  ReadOptions (tcpHeader);
1060 
1061  if (tcpHeader.GetFlags () & TcpHeader::ACK)
1062  {
1063  EstimateRtt (tcpHeader);
1064  }
1065 
1066  // Discard fully out of range packets
1067  if (packet->GetSize ()
1068  && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
1069  {
1070  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1071  " received packet of seq [" << tcpHeader.GetSequenceNumber () <<
1072  ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
1073  ") out of range [" << m_rxBuffer->NextRxSequence () << ":" <<
1074  m_rxBuffer->MaxRxSequence () << ")");
1075  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1076  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
1077  {
1079  }
1080  return;
1081  }
1082 
1083  // Update Rx window size, i.e. the flow control window
1084  if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0 && m_persistEvent.IsRunning ())
1085  { // persist probes end
1086  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
1088  }
1089 
1090  if (tcpHeader.GetFlags () & TcpHeader::ACK)
1091  {
1092  UpdateWindowSize (tcpHeader);
1093  }
1094 
1095  // TCP state machine code in different process functions
1096  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1097  switch (m_state)
1098  {
1099  case ESTABLISHED:
1100  ProcessEstablished (packet, tcpHeader);
1101  break;
1102  case LISTEN:
1103  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1104  break;
1105  case TIME_WAIT:
1106  // Do nothing
1107  break;
1108  case CLOSED:
1109  // Send RST if the incoming packet is not a RST
1110  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1111  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1112  TcpHeader h;
1115  h.SetAckNumber (m_rxBuffer->NextRxSequence ());
1116  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1117  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1119  AddOptions (h);
1120  m_tcp->SendPacket (Create<Packet> (), h, header.GetDestinationAddress (), header.GetSourceAddress (), m_boundnetdevice);
1121  }
1122  break;
1123  case SYN_SENT:
1124  ProcessSynSent (packet, tcpHeader);
1125  break;
1126  case SYN_RCVD:
1127  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1128  break;
1129  case FIN_WAIT_1:
1130  case FIN_WAIT_2:
1131  case CLOSE_WAIT:
1132  ProcessWait (packet, tcpHeader);
1133  break;
1134  case CLOSING:
1135  ProcessClosing (packet, tcpHeader);
1136  break;
1137  case LAST_ACK:
1138  ProcessLastAck (packet, tcpHeader);
1139  break;
1140  default: // mute compiler
1141  break;
1142  }
1143 }
1144 
1145 /* Received a packet upon ESTABLISHED state. This function is mimicking the
1146  role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1147 void
1149 {
1150  NS_LOG_FUNCTION (this << tcpHeader);
1151 
1152  // Extract the flags. PSH and URG are not honoured.
1153  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1154 
1155  // Different flags are different events
1156  if (tcpflags == TcpHeader::ACK)
1157  {
1158  ReceivedAck (packet, tcpHeader);
1159  }
1160  else if (tcpflags == TcpHeader::SYN)
1161  { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1162  // respond with a SYN+ACK. But it is not a legal state transition as of
1163  // RFC793. Thus this is ignored.
1164  }
1165  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1166  { // No action for received SYN+ACK, it is probably a duplicated packet
1167  }
1168  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1169  { // Received FIN or FIN+ACK, bring down this socket nicely
1170  PeerClose (packet, tcpHeader);
1171  }
1172  else if (tcpflags == 0)
1173  { // No flags means there is only data
1174  ReceivedData (packet, tcpHeader);
1175  if (m_rxBuffer->Finished ())
1176  {
1177  PeerClose (packet, tcpHeader);
1178  }
1179  }
1180  else
1181  { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1182  if (tcpflags != TcpHeader::RST)
1183  { // this must be an invalid flag, send reset
1184  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1185  SendRST ();
1186  }
1187  CloseAndNotify ();
1188  }
1189 }
1190 
1191 /* Process the newly received ACK */
1192 void
1194 {
1195  NS_LOG_FUNCTION (this << tcpHeader);
1196 
1197  // Received ACK. Compare the ACK number against highest unacked seqno
1198  if (0 == (tcpHeader.GetFlags () & TcpHeader::ACK))
1199  { // Ignore if no ACK flag
1200  }
1201  else if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ())
1202  { // Case 1: Old ACK, ignored.
1203  NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber ());
1204  }
1205  else if (tcpHeader.GetAckNumber () == m_txBuffer->HeadSequence ())
1206  { // Case 2: Potentially a duplicated ACK
1207  if (tcpHeader.GetAckNumber () < m_nextTxSequence && packet->GetSize() == 0)
1208  {
1209  NS_LOG_LOGIC ("Dupack of " << tcpHeader.GetAckNumber ());
1210  DupAck (tcpHeader, ++m_dupAckCount);
1211  }
1212  // otherwise, the ACK is precisely equal to the nextTxSequence
1213  NS_ASSERT (tcpHeader.GetAckNumber () <= m_nextTxSequence);
1214  }
1215  else if (tcpHeader.GetAckNumber () > m_txBuffer->HeadSequence ())
1216  { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer
1217  NS_LOG_LOGIC ("New ack of " << tcpHeader.GetAckNumber ());
1218  NewAck (tcpHeader.GetAckNumber ());
1219  m_dupAckCount = 0;
1220  }
1221  // If there is any data piggybacked, store it into m_rxBuffer
1222  if (packet->GetSize () > 0)
1223  {
1224  ReceivedData (packet, tcpHeader);
1225  }
1226 }
1227 
1228 /* Received a packet upon LISTEN state. */
1229 void
1231  const Address& fromAddress, const Address& toAddress)
1232 {
1233  NS_LOG_FUNCTION (this << tcpHeader);
1234 
1235  // Extract the flags. PSH and URG are not honoured.
1236  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1237 
1238  // Fork a socket if received a SYN. Do nothing otherwise.
1239  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
1240  if (tcpflags != TcpHeader::SYN)
1241  {
1242  return;
1243  }
1244 
1245  // Call socket's notify function to let the server app know we got a SYN
1246  // If the server app refuses the connection, do nothing
1247  if (!NotifyConnectionRequest (fromAddress))
1248  {
1249  return;
1250  }
1251  // Clone the socket, simulate fork
1252  Ptr<TcpSocketBase> newSock = Fork ();
1253  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
1255  packet, tcpHeader, fromAddress, toAddress);
1256 }
1257 
1258 /* Received a packet upon SYN_SENT */
1259 void
1261 {
1262  NS_LOG_FUNCTION (this << tcpHeader);
1263 
1264  // Extract the flags. PSH and URG are not honoured.
1265  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1266 
1267  if (tcpflags == 0)
1268  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
1269  NS_LOG_INFO ("SYN_SENT -> ESTABLISHED");
1270  m_state = ESTABLISHED;
1271  m_connected = true;
1272  m_retxEvent.Cancel ();
1274  ReceivedData (packet, tcpHeader);
1276  }
1277  else if (tcpflags == TcpHeader::ACK)
1278  { // Ignore ACK in SYN_SENT
1279  }
1280  else if (tcpflags == TcpHeader::SYN)
1281  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
1282  NS_LOG_INFO ("SYN_SENT -> SYN_RCVD");
1283  m_state = SYN_RCVD;
1285  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1287  }
1288  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK)
1289  && m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
1290  { // Handshake completed
1291  NS_LOG_INFO ("SYN_SENT -> ESTABLISHED");
1292  m_state = ESTABLISHED;
1293  m_connected = true;
1294  m_retxEvent.Cancel ();
1295  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1297  m_txBuffer->SetHeadSequence (m_nextTxSequence);
1301  // Always respond to first data packet to speed up the connection.
1302  // Remove to get the behaviour of old NS-3 code.
1304  }
1305  else
1306  { // Other in-sequence input
1307  if (tcpflags != TcpHeader::RST)
1308  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
1309  NS_LOG_LOGIC ("Illegal flag " << std::hex << static_cast<uint32_t> (tcpflags) << std::dec << " received. Reset packet is sent.");
1310  SendRST ();
1311  }
1312  CloseAndNotify ();
1313  }
1314 }
1315 
1316 /* Received a packet upon SYN_RCVD */
1317 void
1319  const Address& fromAddress, const Address& toAddress)
1320 {
1321  NS_LOG_FUNCTION (this << tcpHeader);
1322 
1323  // Extract the flags. PSH and URG are not honoured.
1324  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1325 
1326  if (tcpflags == 0
1327  || (tcpflags == TcpHeader::ACK
1328  && m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
1329  { // If it is bare data, accept it and move to ESTABLISHED state. This is
1330  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
1331  // handshake is completed nicely.
1332  NS_LOG_INFO ("SYN_RCVD -> ESTABLISHED");
1333  m_state = ESTABLISHED;
1334  m_connected = true;
1335  m_retxEvent.Cancel ();
1337  m_txBuffer->SetHeadSequence (m_nextTxSequence);
1338  if (m_endPoint)
1339  {
1340  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1341  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1342  }
1343  else if (m_endPoint6)
1344  {
1345  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1346  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1347  }
1348  // Always respond to first data packet to speed up the connection.
1349  // Remove to get the behaviour of old NS-3 code.
1351  ReceivedAck (packet, tcpHeader);
1352  NotifyNewConnectionCreated (this, fromAddress);
1353  // As this connection is established, the socket is available to send data now
1354  if (GetTxAvailable () > 0)
1355  {
1357  }
1358  }
1359  else if (tcpflags == TcpHeader::SYN)
1360  { // Probably the peer lost my SYN+ACK
1361  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1363  }
1364  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1365  {
1366  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1367  { // In-sequence FIN before connection complete. Set up connection and close.
1368  m_connected = true;
1369  m_retxEvent.Cancel ();
1371  m_txBuffer->SetHeadSequence (m_nextTxSequence);
1372  if (m_endPoint)
1373  {
1374  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1375  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1376  }
1377  else if (m_endPoint6)
1378  {
1379  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1380  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1381  }
1382  PeerClose (packet, tcpHeader);
1383  }
1384  }
1385  else
1386  { // Other in-sequence input
1387  if (tcpflags != TcpHeader::RST)
1388  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
1389  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1390  if (m_endPoint)
1391  {
1392  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1393  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1394  }
1395  else if (m_endPoint6)
1396  {
1397  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1398  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1399  }
1400  SendRST ();
1401  }
1402  CloseAndNotify ();
1403  }
1404 }
1405 
1406 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
1407 void
1409 {
1410  NS_LOG_FUNCTION (this << tcpHeader);
1411 
1412  // Extract the flags. PSH and URG are not honoured.
1413  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1414 
1415  if (packet->GetSize () > 0 && tcpflags != TcpHeader::ACK)
1416  { // Bare data, accept it
1417  ReceivedData (packet, tcpHeader);
1418  }
1419  else if (tcpflags == TcpHeader::ACK)
1420  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
1421  ReceivedAck (packet, tcpHeader);
1422  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
1423  && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
1424  { // This ACK corresponds to the FIN sent
1425  NS_LOG_INFO ("FIN_WAIT_1 -> FIN_WAIT_2");
1426  m_state = FIN_WAIT_2;
1427  }
1428  }
1429  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1430  { // Got FIN, respond with ACK and move to next state
1431  if (tcpflags & TcpHeader::ACK)
1432  { // Process the ACK first
1433  ReceivedAck (packet, tcpHeader);
1434  }
1435  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
1436  }
1437  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1438  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
1439  return;
1440  }
1441  else
1442  { // This is a RST or bad flags
1443  if (tcpflags != TcpHeader::RST)
1444  {
1445  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1446  SendRST ();
1447  }
1448  CloseAndNotify ();
1449  return;
1450  }
1451 
1452  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
1453  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer->Finished ())
1454  {
1455  if (m_state == FIN_WAIT_1)
1456  {
1457  NS_LOG_INFO ("FIN_WAIT_1 -> CLOSING");
1458  m_state = CLOSING;
1459  if (m_txBuffer->Size () == 0
1460  && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
1461  { // This ACK corresponds to the FIN sent
1462  TimeWait ();
1463  }
1464  }
1465  else if (m_state == FIN_WAIT_2)
1466  {
1467  TimeWait ();
1468  }
1470  if (!m_shutdownRecv)
1471  {
1472  NotifyDataRecv ();
1473  }
1474  }
1475 }
1476 
1477 /* Received a packet upon CLOSING */
1478 void
1480 {
1481  NS_LOG_FUNCTION (this << tcpHeader);
1482 
1483  // Extract the flags. PSH and URG are not honoured.
1484  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1485 
1486  if (tcpflags == TcpHeader::ACK)
1487  {
1488  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1489  { // This ACK corresponds to the FIN sent
1490  TimeWait ();
1491  }
1492  }
1493  else
1494  { // CLOSING state means simultaneous close, i.e. no one is sending data to
1495  // anyone. If anything other than ACK is received, respond with a reset.
1496  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1497  { // FIN from the peer as well. We can close immediately.
1499  }
1500  else if (tcpflags != TcpHeader::RST)
1501  { // Receive of SYN or SYN+ACK or bad flags or pure data
1502  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1503  SendRST ();
1504  }
1505  CloseAndNotify ();
1506  }
1507 }
1508 
1509 /* Received a packet upon LAST_ACK */
1510 void
1512 {
1513  NS_LOG_FUNCTION (this << tcpHeader);
1514 
1515  // Extract the flags. PSH and URG are not honoured.
1516  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1517 
1518  if (tcpflags == 0)
1519  {
1520  ReceivedData (packet, tcpHeader);
1521  }
1522  else if (tcpflags == TcpHeader::ACK)
1523  {
1524  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1525  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
1526  CloseAndNotify ();
1527  }
1528  }
1529  else if (tcpflags == TcpHeader::FIN)
1530  { // Received FIN again, the peer probably lost the FIN+ACK
1532  }
1533  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
1534  {
1535  CloseAndNotify ();
1536  }
1537  else
1538  { // Received a SYN or SYN+ACK or bad flags
1539  NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
1540  SendRST ();
1541  CloseAndNotify ();
1542  }
1543 }
1544 
1545 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
1546 void
1548 {
1549  NS_LOG_FUNCTION (this << tcpHeader);
1550 
1551  // Ignore all out of range packets
1552  if (tcpHeader.GetSequenceNumber () < m_rxBuffer->NextRxSequence ()
1553  || tcpHeader.GetSequenceNumber () > m_rxBuffer->MaxRxSequence ())
1554  {
1555  return;
1556  }
1557  // For any case, remember the FIN position in rx buffer first
1558  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
1559  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
1560  // If there is any piggybacked data, process it
1561  if (p->GetSize ())
1562  {
1563  ReceivedData (p, tcpHeader);
1564  }
1565  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
1566  if (!m_rxBuffer->Finished ())
1567  {
1568  return;
1569  }
1570 
1571  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
1572  if (m_state == FIN_WAIT_1)
1573  {
1574  NS_LOG_INFO ("FIN_WAIT_1 -> CLOSING");
1575  m_state = CLOSING;
1576  return;
1577  }
1578 
1579  DoPeerClose (); // Change state, respond with ACK
1580 }
1581 
1582 /* Received a in-sequence FIN. Close down this socket. */
1583 void
1585 {
1587 
1588  // Move the state to CLOSE_WAIT
1589  NS_LOG_INFO (TcpStateName[m_state] << " -> CLOSE_WAIT");
1590  m_state = CLOSE_WAIT;
1591 
1592  if (!m_closeNotified)
1593  {
1594  // The normal behaviour for an application is that, when the peer sent a in-sequence
1595  // FIN, the app should prepare to close. The app has two choices at this point: either
1596  // respond with ShutdownSend() call to declare that it has nothing more to send and
1597  // the socket can be closed immediately; or remember the peer's close request, wait
1598  // until all its existing data are pushed into the TCP socket, then call Close()
1599  // explicitly.
1600  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
1601  NotifyNormalClose ();
1602  m_closeNotified = true;
1603  }
1604  if (m_shutdownSend)
1605  { // The application declares that it would not sent any more, close this socket
1606  Close ();
1607  }
1608  else
1609  { // Need to ack, the application will close later
1611  }
1612  if (m_state == LAST_ACK)
1613  {
1614  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
1615  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4);
1617  }
1618 }
1619 
1620 /* Kill this socket. This is a callback function configured to m_endpoint in
1621  SetupCallback(), invoked when the endpoint is destroyed. */
1622 void
1624 {
1625  NS_LOG_FUNCTION (this);
1626  m_endPoint = 0;
1627  if (m_tcp != 0)
1628  {
1629  std::vector<Ptr<TcpSocketBase> >::iterator it
1630  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1631  if (it != m_tcp->m_sockets.end ())
1632  {
1633  m_tcp->m_sockets.erase (it);
1634  }
1635  }
1636  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1637  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1638  CancelAllTimers ();
1639 }
1640 
1641 /* Kill this socket. This is a callback function configured to m_endpoint in
1642  SetupCallback(), invoked when the endpoint is destroyed. */
1643 void
1645 {
1646  NS_LOG_FUNCTION (this);
1647  m_endPoint6 = 0;
1648  if (m_tcp != 0)
1649  {
1650  std::vector<Ptr<TcpSocketBase> >::iterator it
1651  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1652  if (it != m_tcp->m_sockets.end ())
1653  {
1654  m_tcp->m_sockets.erase (it);
1655  }
1656  }
1657  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1658  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1659  CancelAllTimers ();
1660 }
1661 
1662 /* Send an empty packet with specified TCP flags */
1663 void
1665 {
1666  NS_LOG_FUNCTION (this << (uint32_t)flags);
1667  Ptr<Packet> p = Create<Packet> ();
1668  TcpHeader header;
1670 
1671  /*
1672  * Add tags for each socket option.
1673  * Note that currently the socket adds both IPv4 tag and IPv6 tag
1674  * if both options are set. Once the packet got to layer three, only
1675  * the corresponding tags will be read.
1676  */
1677  if (IsManualIpTos ())
1678  {
1679  SocketIpTosTag ipTosTag;
1680  ipTosTag.SetTos (GetIpTos ());
1681  p->AddPacketTag (ipTosTag);
1682  }
1683 
1684  if (IsManualIpv6Tclass ())
1685  {
1686  SocketIpv6TclassTag ipTclassTag;
1687  ipTclassTag.SetTclass (GetIpv6Tclass ());
1688  p->AddPacketTag (ipTclassTag);
1689  }
1690 
1691  if (IsManualIpTtl ())
1692  {
1693  SocketIpTtlTag ipTtlTag;
1694  ipTtlTag.SetTtl (GetIpTtl ());
1695  p->AddPacketTag (ipTtlTag);
1696  }
1697 
1698  if (IsManualIpv6HopLimit ())
1699  {
1700  SocketIpv6HopLimitTag ipHopLimitTag;
1701  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
1702  p->AddPacketTag (ipHopLimitTag);
1703  }
1704 
1705  if (m_endPoint == 0 && m_endPoint6 == 0)
1706  {
1707  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
1708  return;
1709  }
1710  if (flags & TcpHeader::FIN)
1711  {
1712  flags |= TcpHeader::ACK;
1713  }
1714  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
1715  {
1716  ++s;
1717  }
1718 
1719  header.SetFlags (flags);
1720  header.SetSequenceNumber (s);
1721  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
1722  if (m_endPoint != 0)
1723  {
1724  header.SetSourcePort (m_endPoint->GetLocalPort ());
1725  header.SetDestinationPort (m_endPoint->GetPeerPort ());
1726  }
1727  else
1728  {
1729  header.SetSourcePort (m_endPoint6->GetLocalPort ());
1730  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
1731  }
1732  AddOptions (header);
1733  header.SetWindowSize (AdvertisedWindowSize ());
1734 
1735  // RFC 6298, clause 2.4
1736  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4), m_minRto);
1737 
1738  bool hasSyn = flags & TcpHeader::SYN;
1739  bool hasFin = flags & TcpHeader::FIN;
1740  bool isAck = flags == TcpHeader::ACK;
1741  if (hasSyn)
1742  {
1743  if (m_cnCount == 0)
1744  { // No more connection retries, give up
1745  NS_LOG_LOGIC ("Connection failed.");
1746  m_rtt->Reset (); //According to recommendation -> RFC 6298
1747  CloseAndNotify ();
1748  return;
1749  }
1750  else
1751  { // Exponential backoff of connection time out
1752  int backoffCount = 0x1 << (m_cnRetries - m_cnCount);
1753  m_rto = m_cnTimeout * backoffCount;
1754  m_cnCount--;
1755  }
1756  }
1757  if (m_endPoint != 0)
1758  {
1759  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
1761  }
1762  else
1763  {
1764  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
1766  }
1767  if (flags & TcpHeader::ACK)
1768  { // If sending an ACK, cancel the delay ACK as well
1769  m_delAckEvent.Cancel ();
1770  m_delAckCount = 0;
1771  }
1772  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
1773  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
1774  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
1775  << Simulator::Now ().GetSeconds () << " to expire at time "
1776  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
1778  }
1779 }
1780 
1781 /* This function closes the endpoint completely. Called upon RST_TX action. */
1782 void
1784 {
1785  NS_LOG_FUNCTION (this);
1787  NotifyErrorClose ();
1788  DeallocateEndPoint ();
1789 }
1790 
1791 /* Deallocate the end point and cancel all the timers */
1792 void
1794 {
1795  if (m_endPoint != 0)
1796  {
1797  CancelAllTimers ();
1798  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
1799  m_tcp->DeAllocate (m_endPoint);
1800  m_endPoint = 0;
1801  std::vector<Ptr<TcpSocketBase> >::iterator it
1802  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1803  if (it != m_tcp->m_sockets.end ())
1804  {
1805  m_tcp->m_sockets.erase (it);
1806  }
1807  }
1808  else if (m_endPoint6 != 0)
1809  {
1810  CancelAllTimers ();
1811  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
1812  m_tcp->DeAllocate (m_endPoint6);
1813  m_endPoint6 = 0;
1814  std::vector<Ptr<TcpSocketBase> >::iterator it
1815  = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
1816  if (it != m_tcp->m_sockets.end ())
1817  {
1818  m_tcp->m_sockets.erase (it);
1819  }
1820  }
1821 }
1822 
1823 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
1824 int
1826 {
1827  NS_LOG_FUNCTION (this);
1828  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
1829  NS_ASSERT (ipv4 != 0);
1830  if (ipv4->GetRoutingProtocol () == 0)
1831  {
1832  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
1833  }
1834  // Create a dummy packet, then ask the routing function for the best output
1835  // interface's address
1836  Ipv4Header header;
1838  Socket::SocketErrno errno_;
1839  Ptr<Ipv4Route> route;
1841  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
1842  if (route == 0)
1843  {
1844  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
1845  NS_LOG_ERROR (errno_);
1846  m_errno = errno_;
1847  return -1;
1848  }
1849  NS_LOG_LOGIC ("Route exists");
1850  m_endPoint->SetLocalAddress (route->GetSource ());
1851  return 0;
1852 }
1853 
1854 int
1856 {
1857  NS_LOG_FUNCTION (this);
1859  NS_ASSERT (ipv6 != 0);
1860  if (ipv6->GetRoutingProtocol () == 0)
1861  {
1862  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
1863  }
1864  // Create a dummy packet, then ask the routing function for the best output
1865  // interface's address
1866  Ipv6Header header;
1868  Socket::SocketErrno errno_;
1869  Ptr<Ipv6Route> route;
1871  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
1872  if (route == 0)
1873  {
1874  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
1875  NS_LOG_ERROR (errno_);
1876  m_errno = errno_;
1877  return -1;
1878  }
1879  NS_LOG_LOGIC ("Route exists");
1880  m_endPoint6->SetLocalAddress (route->GetSource ());
1881  return 0;
1882 }
1883 
1884 /* This function is called only if a SYN received in LISTEN state. After
1885  TcpSocketBase cloned, allocate a new end point to handle the incoming
1886  connection and send a SYN+ACK to complete the handshake. */
1887 void
1889  const Address& fromAddress, const Address& toAddress)
1890 {
1891  // Get port and address from peer (connecting host)
1892  if (InetSocketAddress::IsMatchingType (toAddress))
1893  {
1894  m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
1895  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
1896  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1897  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1898  m_endPoint6 = 0;
1899  }
1900  else if (Inet6SocketAddress::IsMatchingType (toAddress))
1901  {
1902  m_endPoint6 = m_tcp->Allocate6 (Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
1903  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
1904  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1905  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1906  m_endPoint = 0;
1907  }
1908  m_tcp->m_sockets.push_back (this);
1909 
1910  // Change the cloned socket from LISTEN state to SYN_RCVD
1911  NS_LOG_INFO ("LISTEN -> SYN_RCVD");
1912  m_state = SYN_RCVD;
1914  SetupCallback ();
1915  // Set the sequence number and send SYN+ACK
1916  m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
1917 
1919 }
1920 
1921 void
1923 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
1924  // be called as a scheduled event
1926  // The if-block below was moved from ProcessSynSent() to here because we need
1927  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
1928  // reflect the behaviour in the real world.
1929  if (GetTxAvailable () > 0)
1930  {
1932  }
1933 }
1934 
1935 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
1936  TCP header, and send to TcpL4Protocol */
1937 uint32_t
1938 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
1939 {
1940  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
1941 
1942  bool isRetransmission = false;
1943  if ( seq == m_txBuffer->HeadSequence () )
1944  {
1945  isRetransmission = true;
1946  }
1947 
1948  Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq);
1949  uint32_t sz = p->GetSize (); // Size of packet
1950  uint8_t flags = withAck ? TcpHeader::ACK : 0;
1951  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
1952 
1953  if (withAck)
1954  {
1955  m_delAckEvent.Cancel ();
1956  m_delAckCount = 0;
1957  }
1958 
1959  /*
1960  * Add tags for each socket option.
1961  * Note that currently the socket adds both IPv4 tag and IPv6 tag
1962  * if both options are set. Once the packet got to layer three, only
1963  * the corresponding tags will be read.
1964  */
1965  if (IsManualIpTos ())
1966  {
1967  SocketIpTosTag ipTosTag;
1968  ipTosTag.SetTos (GetIpTos ());
1969  p->AddPacketTag (ipTosTag);
1970  }
1971 
1972  if (IsManualIpv6Tclass ())
1973  {
1974  SocketIpv6TclassTag ipTclassTag;
1975  ipTclassTag.SetTclass (GetIpv6Tclass ());
1976  p->AddPacketTag (ipTclassTag);
1977  }
1978 
1979  if (IsManualIpTtl ())
1980  {
1981  SocketIpTtlTag ipTtlTag;
1982  ipTtlTag.SetTtl (GetIpTtl ());
1983  p->AddPacketTag (ipTtlTag);
1984  }
1985 
1986  if (IsManualIpv6HopLimit ())
1987  {
1988  SocketIpv6HopLimitTag ipHopLimitTag;
1989  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
1990  p->AddPacketTag (ipHopLimitTag);
1991  }
1992 
1993  if (m_closeOnEmpty && (remainingData == 0))
1994  {
1995  flags |= TcpHeader::FIN;
1996  if (m_state == ESTABLISHED)
1997  { // On active close: I am the first one to send FIN
1998  NS_LOG_INFO ("ESTABLISHED -> FIN_WAIT_1");
1999  m_state = FIN_WAIT_1;
2000  }
2001  else if (m_state == CLOSE_WAIT)
2002  { // On passive close: Peer sent me FIN already
2003  NS_LOG_INFO ("CLOSE_WAIT -> LAST_ACK");
2004  m_state = LAST_ACK;
2005  }
2006  }
2007  TcpHeader header;
2008  header.SetFlags (flags);
2009  header.SetSequenceNumber (seq);
2010  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2011  if (m_endPoint)
2012  {
2013  header.SetSourcePort (m_endPoint->GetLocalPort ());
2015  }
2016  else
2017  {
2018  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2020  }
2021  header.SetWindowSize (AdvertisedWindowSize ());
2022  AddOptions (header);
2023 
2024  if (m_retxEvent.IsExpired () )
2025  {
2026  // RFC 6298, clause 2.5
2027  Time doubledRto = m_rto + m_rto;
2028  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
2029 
2030  // Schedules retransmit
2031 
2032  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
2033  Simulator::Now ().GetSeconds () << " to expire at time " <<
2034  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
2036  }
2037  NS_LOG_LOGIC ("Send packet via TcpL4Protocol with flags 0x" << std::hex << static_cast<uint32_t> (flags) << std::dec);
2038  if (m_endPoint)
2039  {
2040  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2042  }
2043  else
2044  {
2045  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2047  }
2048 
2049  // update the history of sequence numbers used to calculate the RTT
2050  if (isRetransmission == false)
2051  { // This is the next expected one, just log at end
2052  m_history.push_back (RttHistory (seq, sz, Simulator::Now () ));
2053  }
2054  else
2055  { // This is a retransmit, find in list and mark as re-tx
2056  for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
2057  {
2058  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
2059  { // Found it
2060  i->retx = true;
2061  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
2062  break;
2063  }
2064  }
2065  }
2066 
2067  // Notify the application of the data being sent unless this is a retransmit
2068  if (seq == m_highTxMark)
2069  {
2071  }
2072  // Update highTxMark
2073  m_highTxMark = std::max (seq + sz, m_highTxMark.Get ());
2074  return sz;
2075 }
2076 
2077 /* Send as much pending data as possible according to the Tx window. Note that
2078  * this function did not implement the PSH flag
2079  */
2080 bool
2082 {
2083  NS_LOG_FUNCTION (this << withAck);
2084  if (m_txBuffer->Size () == 0)
2085  {
2086  return false; // Nothing to send
2087  }
2088  if (m_endPoint == 0 && m_endPoint6 == 0)
2089  {
2090  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
2091  return false; // Is this the right way to handle this condition?
2092  }
2093  uint32_t nPacketsSent = 0;
2094  while (m_txBuffer->SizeFromSequence (m_nextTxSequence))
2095  {
2096  uint32_t w = AvailableWindow (); // Get available window size
2097  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
2098  if (w < m_segmentSize && m_txBuffer->SizeFromSequence (m_nextTxSequence) > w)
2099  {
2100  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
2101  break; // No more
2102  }
2103  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
2104  // in the buffer and the amount of data to send is less than one segment
2105  if (!m_noDelay && UnAckDataCount () > 0
2106  && m_txBuffer->SizeFromSequence (m_nextTxSequence) < m_segmentSize)
2107  {
2108  NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send.");
2109  break;
2110  }
2111  NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" <<
2112  " w " << w <<
2113  " rxwin " << m_rWnd <<
2114  " segsize " << m_segmentSize <<
2115  " nextTxSeq " << m_nextTxSequence <<
2116  " highestRxAck " << m_txBuffer->HeadSequence () <<
2117  " pd->Size " << m_txBuffer->Size () <<
2118  " pd->SFS " << m_txBuffer->SizeFromSequence (m_nextTxSequence));
2119  uint32_t s = std::min (w, m_segmentSize); // Send no more than window
2120  uint32_t sz = SendDataPacket (m_nextTxSequence, s, withAck);
2121  nPacketsSent++; // Count sent this loop
2122  m_nextTxSequence += sz; // Advance next tx sequence
2123  }
2124  NS_LOG_LOGIC ("SendPendingData sent " << nPacketsSent << " packets");
2125  return (nPacketsSent > 0);
2126 }
2127 
2128 uint32_t
2130 {
2131  NS_LOG_FUNCTION (this);
2132  return m_nextTxSequence.Get () - m_txBuffer->HeadSequence ();
2133 }
2134 
2135 uint32_t
2137 {
2138  NS_LOG_FUNCTION (this);
2139  return m_highTxMark.Get () - m_txBuffer->HeadSequence ();
2140 }
2141 
2142 uint32_t
2144 {
2146  uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
2147  uint32_t win = Window (); // Number of bytes allowed to be outstanding
2148  NS_LOG_LOGIC ("UnAckCount=" << unack << ", Win=" << win);
2149  return (win < unack) ? 0 : (win - unack);
2150 }
2151 
2152 uint16_t
2154 {
2155  uint32_t w = m_rxBuffer->MaxBufferSize () - m_rxBuffer->Size ();
2156 
2157  w >>= m_sndScaleFactor;
2158 
2159  if (w > m_maxWinSize)
2160  {
2161  NS_LOG_WARN ("There is a loss in the adv win size, wrt buffer size");
2162  w = m_maxWinSize;
2163  }
2164 
2165  return (uint16_t) w;
2166 }
2167 
2168 // Receipt of new packet, put into Rx buffer
2169 void
2171 {
2172  NS_LOG_FUNCTION (this << tcpHeader);
2173  NS_LOG_LOGIC ("seq " << tcpHeader.GetSequenceNumber () <<
2174  " ack " << tcpHeader.GetAckNumber () <<
2175  " pkt size " << p->GetSize () );
2176 
2177  // Put into Rx buffer
2178  SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence ();
2179  if (!m_rxBuffer->Add (p, tcpHeader))
2180  { // Insert failed: No data or RX buffer full
2182  return;
2183  }
2184  // Now send a new ACK packet acknowledging all received and delivered data
2185  if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
2186  { // A gap exists in the buffer, or we filled a gap: Always ACK
2188  }
2189  else
2190  { // In-sequence packet: ACK if delayed ack count allows
2192  {
2193  m_delAckEvent.Cancel ();
2194  m_delAckCount = 0;
2196  }
2197  else if (m_delAckEvent.IsExpired ())
2198  {
2201  NS_LOG_LOGIC (this << " scheduled delayed ACK at " << (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
2202  }
2203  }
2204  // Notify app to receive if necessary
2205  if (expectedSeq < m_rxBuffer->NextRxSequence ())
2206  { // NextRxSeq advanced, we have something to send to the app
2207  if (!m_shutdownRecv)
2208  {
2209  NotifyDataRecv ();
2210  }
2211  // Handle exceptions
2212  if (m_closeNotified)
2213  {
2214  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
2215  }
2216  // If we received FIN before and now completed all "holes" in rx buffer,
2217  // invoke peer close procedure
2218  if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
2219  {
2220  DoPeerClose ();
2221  }
2222  }
2223 }
2224 
2232 void
2234 {
2235  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber();
2236  Time m = Time (0.0);
2237 
2238  // An ack has been received, calculate rtt and log this measurement
2239  // Note we use a linear search (O(n)) for this since for the common
2240  // case the ack'ed packet will be at the head of the list
2241  if (!m_history.empty ())
2242  {
2243  RttHistory& h = m_history.front ();
2244  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
2245  { // Ok to use this sample
2246  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
2247  {
2248  Ptr<TcpOptionTS> ts;
2249  ts = DynamicCast<TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
2250  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
2251  }
2252  else
2253  {
2254  m = Simulator::Now () - h.time; // Elapsed time
2255  }
2256  }
2257  }
2258 
2259  // Now delete all ack history with seq <= ack
2260  while(!m_history.empty ())
2261  {
2262  RttHistory& h = m_history.front ();
2263  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq) break; // Done removing
2264  m_history.pop_front (); // Remove
2265  }
2266 
2267  if (!m.IsZero ())
2268  {
2269  m_rtt->Measurement (m); // Log the measurement
2270  // RFC 6298, clause 2.4
2271  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4), m_minRto);
2272  m_lastRtt = m_rtt->GetEstimate ();
2273  NS_LOG_FUNCTION(this << m_lastRtt);
2274  }
2275 }
2276 
2277 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
2278 // when the three-way handshake completed. This cancels retransmission timer
2279 // and advances Tx window
2280 void
2282 {
2283  NS_LOG_FUNCTION (this << ack);
2284 
2285  if (m_state != SYN_RCVD)
2286  { // Set RTO unless the ACK is received in SYN_RCVD state
2287  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2288  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2289  m_retxEvent.Cancel ();
2290  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
2291  // RFC 6298, clause 2.4
2292  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4), m_minRto);
2293 
2294  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
2295  Simulator::Now ().GetSeconds () << " to expire at time " <<
2296  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2298  }
2299  if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
2300  { // Zero window: Enter persist state to send 1 byte to probe
2301  NS_LOG_LOGIC (this << "Enter zerowindow persist state");
2302  NS_LOG_LOGIC (this << "Cancelled ReTxTimeout event which was set to expire at " <<
2303  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2304  m_retxEvent.Cancel ();
2305  NS_LOG_LOGIC ("Schedule persist timeout at time " <<
2306  Simulator::Now ().GetSeconds () << " to expire at time " <<
2307  (Simulator::Now () + m_persistTimeout).GetSeconds ());
2310  }
2311  // Note the highest ACK and tell app to send more
2312  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
2313  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
2314  m_txBuffer->DiscardUpTo (ack);
2315  if (GetTxAvailable () > 0)
2316  {
2318  }
2319  if (ack > m_nextTxSequence)
2320  {
2321  m_nextTxSequence = ack; // If advanced
2322  }
2323  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
2324  { // No retransmit timer if no data to retransmit
2325  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2326  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2327  m_retxEvent.Cancel ();
2328  }
2329  // Try to send more data
2331  {
2333  }
2334 }
2335 
2336 // Retransmit timeout
2337 void
2339 {
2340  NS_LOG_FUNCTION (this);
2341  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
2342  // If erroneous timeout in closed/timed-wait state, just return
2343  if (m_state == CLOSED || m_state == TIME_WAIT)
2344  {
2345  return;
2346  }
2347  // If all data are received (non-closing socket and nothing to send), just return
2348  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark)
2349  {
2350  return;
2351  }
2352 
2353  Retransmit ();
2354 }
2355 
2356 void
2358 {
2359  m_delAckCount = 0;
2361 }
2362 
2363 void
2365 {
2366  NS_LOG_FUNCTION (this);
2367 
2369  if (m_state == LAST_ACK)
2370  {
2371  CloseAndNotify ();
2372  }
2373  if (!m_closeNotified)
2374  {
2375  m_closeNotified = true;
2376  }
2377 }
2378 
2379 // Send 1-byte data to probe for the window size at the receiver when
2380 // the local knowledge tells that the receiver has zero window size
2381 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
2382 void
2384 {
2385  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
2386  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
2387  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_nextTxSequence);
2388  TcpHeader tcpHeader;
2389  tcpHeader.SetSequenceNumber (m_nextTxSequence);
2390  tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ());
2391  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
2392  if (m_endPoint != 0)
2393  {
2394  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
2395  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
2396  }
2397  else
2398  {
2399  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
2400  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
2401  }
2402  AddOptions (tcpHeader);
2403 
2404  if (m_endPoint != 0)
2405  {
2406  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
2408  }
2409  else
2410  {
2411  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
2413  }
2414  NS_LOG_LOGIC ("Schedule persist timeout at time "
2415  << Simulator::Now ().GetSeconds () << " to expire at time "
2416  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
2418 }
2419 
2420 void
2422 {
2423  m_nextTxSequence = m_txBuffer->HeadSequence (); // Start from highest Ack
2424  m_dupAckCount = 0;
2425  DoRetransmit (); // Retransmit the packet
2426 }
2427 
2428 void
2430 {
2431  NS_LOG_FUNCTION (this);
2432  // Retransmit SYN packet
2433  if (m_state == SYN_SENT)
2434  {
2435  if (m_cnCount > 0)
2436  {
2438  }
2439  else
2440  {
2442  }
2443  return;
2444  }
2445  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
2446  if (m_txBuffer->Size () == 0)
2447  {
2448  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
2449  { // Must have lost FIN, re-send
2451  }
2452  return;
2453  }
2454  // Retransmit a data packet: Call SendDataPacket
2455  NS_LOG_LOGIC ("TcpSocketBase " << this << " retxing seq " << m_txBuffer->HeadSequence ());
2456  uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_segmentSize, true);
2457  // In case of RTO, advance m_nextTxSequence
2458  m_nextTxSequence = std::max (m_nextTxSequence.Get (), m_txBuffer->HeadSequence () + sz);
2459 
2460 }
2461 
2462 void
2464 {
2465  m_retxEvent.Cancel ();
2467  m_delAckEvent.Cancel ();
2471 }
2472 
2473 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
2474 void
2476 {
2477  NS_LOG_INFO (TcpStateName[m_state] << " -> TIME_WAIT");
2478  m_state = TIME_WAIT;
2479  CancelAllTimers ();
2480  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
2481  // according to RFC793, p.28
2484 }
2485 
2486 /* Below are the attribute get/set functions */
2487 
2488 void
2490 {
2491  m_txBuffer->SetMaxBufferSize (size);
2492 }
2493 
2494 uint32_t
2496 {
2497  return m_txBuffer->MaxBufferSize ();
2498 }
2499 
2500 void
2502 {
2503  m_rxBuffer->SetMaxBufferSize (size);
2504 }
2505 
2506 uint32_t
2508 {
2509  return m_rxBuffer->MaxBufferSize ();
2510 }
2511 
2512 void
2514 {
2515  m_segmentSize = size;
2516  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
2517 }
2518 
2519 uint32_t
2521 {
2522  return m_segmentSize;
2523 }
2524 
2525 void
2527 {
2528  m_cnTimeout = timeout;
2529 }
2530 
2531 Time
2533 {
2534  return m_cnTimeout;
2535 }
2536 
2537 void
2539 {
2540  m_cnRetries = count;
2541 }
2542 
2543 uint32_t
2545 {
2546  return m_cnRetries;
2547 }
2548 
2549 void
2551 {
2553 }
2554 
2555 Time
2557 {
2558  return m_delAckTimeout;
2559 }
2560 
2561 void
2563 {
2564  m_delAckMaxCount = count;
2565 }
2566 
2567 uint32_t
2569 {
2570  return m_delAckMaxCount;
2571 }
2572 
2573 void
2575 {
2576  m_noDelay = noDelay;
2577 }
2578 
2579 bool
2581 {
2582  return m_noDelay;
2583 }
2584 
2585 void
2587 {
2589 }
2590 
2591 Time
2593 {
2594  return m_persistTimeout;
2595 }
2596 
2597 bool
2599 {
2600  // Broadcast is not implemented. Return true only if allowBroadcast==false
2601  return (!allowBroadcast);
2602 }
2603 
2604 bool
2606 {
2607  return false;
2608 }
2609 
2610 void
2612 {
2613  NS_LOG_FUNCTION (this << header);
2614 
2615  if ((header.GetFlags () & TcpHeader::SYN))
2616  {
2617  if (m_winScalingEnabled)
2618  {
2619  m_winScalingEnabled = false;
2620 
2621  if (header.HasOption (TcpOption::WINSCALE))
2622  {
2623  m_winScalingEnabled = true;
2626  }
2627  }
2628  }
2629 
2630  m_timestampEnabled = false;
2631 
2632  if (header.HasOption (TcpOption::TS))
2633  {
2634  m_timestampEnabled = true;
2636  }
2637 }
2638 
2639 void
2641 {
2642  NS_LOG_FUNCTION (this << header);
2643 
2644  // The window scaling option is set only on SYN packets
2645  if (m_winScalingEnabled && (header.GetFlags () & TcpHeader::SYN))
2646  {
2647  AddOptionWScale (header);
2648  }
2649 
2650  if (m_timestampEnabled)
2651  {
2652  AddOptionTimestamp (header);
2653  }
2654 }
2655 
2656 void
2658 {
2659  NS_LOG_FUNCTION (this << option);
2660 
2661  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
2662 
2663  // In naming, we do the contrary of RFC 1323. The received scaling factor
2664  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
2665  m_rcvScaleFactor = ws->GetScale ();
2666 
2667  if (m_rcvScaleFactor > 14)
2668  {
2669  NS_LOG_WARN ("Possible error; m_rcvScaleFactor exceeds 14: " << m_rcvScaleFactor);
2670  m_rcvScaleFactor = 14;
2671  }
2672 
2673  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
2674  static_cast<int> (m_rcvScaleFactor));
2675 }
2676 
2677 uint8_t
2679 {
2680  NS_LOG_FUNCTION (this);
2681  uint32_t maxSpace = m_rxBuffer->MaxBufferSize ();
2682  uint8_t scale = 0;
2683 
2684  while (maxSpace > m_maxWinSize)
2685  {
2686  maxSpace = maxSpace >> 1;
2687  ++scale;
2688  }
2689 
2690  if (scale > 14)
2691  {
2692  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
2693  scale = 14;
2694  }
2695 
2696  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
2697  static_cast<int> (scale) << " for buffer size " << m_rxBuffer->MaxBufferSize ());
2698  return scale;
2699 }
2700 
2701 void
2703 {
2704  NS_LOG_FUNCTION (this << header);
2705  NS_ASSERT(header.GetFlags () & TcpHeader::SYN);
2706 
2707  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
2708 
2709  // In naming, we do the contrary of RFC 1323. The sended scaling factor
2710  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
2711 
2713  option->SetScale (m_sndScaleFactor);
2714 
2715  header.AppendOption (option);
2716 
2717  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
2718  static_cast<int> (m_sndScaleFactor));
2719 }
2720 
2721 void
2723 {
2724  NS_LOG_FUNCTION (this << option);
2725 
2726  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
2727  m_timestampToEcho = ts->GetTimestamp ();
2728 
2729  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
2730  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
2731 }
2732 
2733 void
2735 {
2736  NS_LOG_FUNCTION (this << header);
2737 
2738  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
2739 
2740  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
2741  option->SetEcho (m_timestampToEcho);
2742 
2743  header.AppendOption (option);
2744  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
2745  option->GetTimestamp () << " echo=" << m_timestampToEcho);
2746 }
2747 
2749 {
2750  NS_LOG_FUNCTION (this << header);
2751  // If the connection is not established, the window size is always
2752  // updated
2753  uint32_t receivedWindow = header.GetWindowSize ();
2754  receivedWindow <<= m_rcvScaleFactor;
2755  NS_LOG_DEBUG ("Received (scaled) window is " << receivedWindow << " bytes");
2756  if (m_state < ESTABLISHED)
2757  {
2758  m_rWnd = receivedWindow;
2759  NS_LOG_DEBUG ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
2760  return;
2761  }
2762 
2763  // Test for conditions that allow updating of the window
2764  // 1) segment contains new data (advancing the right edge of the receive
2765  // buffer),
2766  // 2) segment does not contain new data but the segment acks new data
2767  // (highest sequence number acked advances), or
2768  // 3) the advertised window is larger than the current send window
2769  bool update = false;
2770  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
2771  {
2772  // right edge of the send window is increased (window update)
2773  update = true;
2774  }
2775  if (header.GetAckNumber () > m_highRxAckMark)
2776  {
2777  m_highRxAckMark = header.GetAckNumber ();
2778  update = true;
2779  }
2780  if (header.GetSequenceNumber () > m_highRxMark)
2781  {
2782  m_highRxMark = header.GetSequenceNumber ();
2783  update = true;
2784  }
2785  if (update == true)
2786  {
2787  m_rWnd = receivedWindow;
2788  NS_LOG_DEBUG ("updating rWnd to " << m_rWnd);
2789  }
2790 }
2791 
2792 void
2794 {
2795  NS_LOG_FUNCTION (this << minRto);
2796  m_minRto = minRto;
2797 }
2798 
2799 Time
2801 {
2802  return m_minRto;
2803 }
2804 
2805 void
2807 {
2808  NS_LOG_FUNCTION (this << clockGranularity);
2809  m_clockGranularity = clockGranularity;
2810 }
2811 
2812 Time
2814 {
2815  return m_clockGranularity;
2816 }
2817 
2820 {
2821  return m_txBuffer;
2822 }
2823 
2826 {
2827  return m_rxBuffer;
2828 }
2829 
2830 
2831 //RttHistory methods
2833  : seq (s), count (c), time (t), retx (false)
2834 {
2835 }
2836 
2838  : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
2839 {
2840 }
2841 
2842 } // namespace ns3
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:232
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
Custom version of log2() to deal with Bug 1467.
void SetTclass(uint8_t tclass)
Set the tag's Tclass.
Definition: socket.cc:822
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:102
bool IsManualIpTtl(void) const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:383
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)
#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.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
AttributeValue implementation for Boolean.
Definition: boolean.h:34
virtual uint8_t GetIpTtl(void) const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:471
virtual uint16_t AdvertisedWindowSize(void)
The amount of Rx window announced to the peer.
Callback template class.
Definition: callback.h:984
bool m_noDelay
Set to true to disable Nagle's algorithm.
virtual uint32_t GetSegSize(void) const
Get the segment size.
Time GetClockGranularity(void) const
Get the Clock Granularity (used in RTO calcs).
uint8_t GetIpTos(void) const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:404
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:1047
(abstract) base class of all TcpSockets
Definition: tcp-socket.h:77
Ipv4EndPoint * m_endPoint
the IPv4 endpoint
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
static Time ElapsedTimeFromTsValue(uint32_t echoTime)
Estimate the Time elapsed from a TS echo value.
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:161
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:305
TracedValue< SequenceNumber32 > m_highRxAckMark
Highest ack received.
virtual int ShutdownRecv(void)
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv4Header, uint16_t, Ptr< Ipv4Interface > > callback)
Set the reception callback.
TcpSocketBase(void)
Create an unbound TCP socket.
void SetClockGranularity(Time clockGranularity)
Sets the Clock Granularity (used in RTO calcs).
EventId m_retxEvent
Retransmission event.
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:175
IPv6 layer implementation.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:81
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
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.
bool IsZero(void) const
Definition: nstime.h:276
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:836
void SetAddress(Address addr)
Set the tag's address.
Definition: socket.cc:523
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:227
static TypeId GetTypeId(void)
Get the type ID.
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
void SendRST(void)
Send reset and tear down this socket.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:874
bool m_winScalingEnabled
Window Scale option enabled.
bool m_timestampEnabled
Timestamp option enabled.
uint16_t m_maxWinSize
Maximum window size to advertise.
virtual void ScaleSsThresh(uint8_t scaleFactor)=0
Scale the initial SsThresh value to the correct one.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:766
second
Definition: nstime.h:114
bool retx
True if this has been retransmitted.
bool IsManualIpTos(void) const
Checks if the socket has a specific IPv4 ToS set.
Definition: socket.cc:371
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.
uint32_t count
Number of bytes sent.
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:244
#define NS_FATAL_ERROR(msg)
Fatal error handling.
Definition: fatal-error.h:100
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:496
Time m_cnTimeout
Timeout for connection retry.
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
uint32_t m_segmentSize
Segment size.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
EventId m_lastAckEvent
Last ACK timeout event.
void ConnectionSucceeded(void)
Schedule-friendly wrapper for Socket::NotifyConnectionSucceeded()
void SetTos(uint8_t tos)
Set the tag's TOS.
Definition: socket.cc:765
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:819
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
Get the underlying value.
Definition: traced-value.h:186
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:999
virtual Time GetPersistTimeout(void) const
Get the timout for persistent connection.
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:257
virtual void PersistTimeout(void)
Send 1 byte probe to get an updated window size.
Ptr< TcpTxBuffer > GetTxBuffer(void) const
Get a pointer to the Tx buffer.
TracedValue< TcpStates_t > m_state
TCP state.
uint32_t m_delAckMaxCount
Number of packet to fire an ACK before delay timeout.
uint8_t CalculateWScale() const
Calculate window scale value based on receive buffer space.
uint16_t port
Definition: dsdv-manet.cc:44
a polymophic address class
Definition: address.h:90
void SetMinRto(Time minRto)
Sets the Minimum RTO.
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
uint16_t GetPeerPort()
Get the peer port.
AttributeValue implementation for Callback.
Definition: callback.h:1687
uint32_t m_cnRetries
Number of connection retries before giving up.
virtual uint32_t GetRcvBufSize(void) const
Get the receive buffer size.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
uint32_t m_delAckCount
Delayed ACK counter.
virtual bool GetTcpNoDelay(void) const
Check if Nagle's algorithm is enabled or not.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
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.
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.
bool AppendOption(Ptr< TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:448
virtual void ReadOptions(const TcpHeader &tcpHeader)
Read TCP options from incoming packets.
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:197
void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
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.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: pointer.h:210
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
Time time
Time this one was sent.
virtual uint32_t UnAckDataCount(void)
Return count of number of unacked bytes.
Ptr< TcpTxBuffer > m_txBuffer
Tx buffer.
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:93
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:584
AttributeValue implementation for Time.
Definition: nstime.h:928
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:167
virtual uint32_t GetSndBufSize(void) const
Get the send buffer size.
virtual enum SocketType GetSocketType(void) const
uint16_t GetLocalPort()
Get the local port.
void UpdateWindowSize(const TcpHeader &header)
Update the receiver window (RWND) based on the value of the window field in the header.
void AddOptionTimestamp(TcpHeader &header)
Add the timestamp option to the header.
Hold an unsigned integer type.
Definition: uinteger.h:44
Ipv6EndPoint * m_endPoint6
the IPv6 endpoint
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
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.
Ptr< const AttributeAccessor > MakeCallbackAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: callback.h:1729
Ipv4Address GetLocalAddress(void)
Get the local address.
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:209
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:951
RttHistory(SequenceNumber32 s, uint32_t c, Time t)
Constructor - builds an RttHistory with the given parameters.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1296
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:377
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:285
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:128
enum SocketErrno m_errno
Socket error code.
Ipv4Address GetSource(void) const
Definition: ipv4-route.cc:56
friend Ptr< T > CopyObject(Ptr< T > object)
Copy an Object.
Definition: object.h:490
A base class for implementation of a stream socket using TCP.
uint8_t m_sndScaleFactor
Sent Window Scale (i.e., the one of the node)
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.
Ptr< TcpRxBuffer > m_rxBuffer
Rx buffer (reordering buffer)
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:252
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:645
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)
Set the destination port.
Definition: tcp-header.cc:95
void NotifyConnectionSucceeded(void)
Notify through the callback (if set) that the connection has been established.
Definition: socket.cc:217
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:389
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:237
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 options to TcpHeader.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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
Hold objects of type Ptr.
Definition: pointer.h:36
virtual uint32_t Window(void)=0
Return the max possible number of unacked bytes.
Generic "sequence number" class.
void NotifyNewConnectionCreated(Ptr< Socket > socket, const Address &from)
Notify through the callback (if set) that a new connection has been created.
Definition: socket.cc:275
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
void TimeWait(void)
Move from CLOSING or FIN_WAIT_2 to TIME_WAIT state.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
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)
Set the source port.
Definition: tcp-header.cc:89
virtual uint32_t BytesInFlight(void)
Return total bytes in flight.
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1192
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:446
void Destroy(void)
Kill this socket by zeroing its attributes (IPv4)
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
Time TimeStep(uint64_t ts)
Definition: nstime.h:923
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Schedule an event to expire Now.
Definition: simulator.h:980
virtual int Close(void)
Close a socket.
static Ipv4Address GetZero(void)
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: nstime.h:929
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer informations (address and port).
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
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:121
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.
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:75
TracedValue< SequenceNumber32 > m_highTxMark
Highest seqno ever sent, regardless of ReTx.
static uint32_t NowToTsValue()
Return an uint32_t value which represent "now".
Time m_minRto
minimum value of the Retransmit timeout
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:330
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:114
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
void SetLocalAddress(Ipv4Address address)
Set the local address.
virtual void SetSndBufSize(uint32_t size)
Set the send buffer size.
Ptr< TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:474
static Time FromDouble(double value, enum Unit unit)
Create a Time equal to value in unit unit.
Definition: nstime.h:424
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.
Ptr< TcpRxBuffer > GetRxBuffer(void) const
Get a pointer to the Rx buffer.
Describes an IPv6 address.
Definition: ipv6-address.h:47
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
Time GetMinRto(void) const
Get the Minimum RTO.
void ProcessEstablished(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon ESTABLISHED state.
void ProcessOptionWScale(const Ptr< const TcpOption > option)
Read and parse the Window scale option.
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:914
bool m_connected
Connection established.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint32_t GetId(void) const
Definition: node.cc:107
TracedValue< Time > m_rto
Retransmit timeout.
Helper class to store RTT measurements.
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:228
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
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.
SequenceNumber32 seq
First sequence number in packet sent.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
RttHistory_t m_history
List of sent packet.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:866
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
Ipv4Address GetPeerAddress(void)
Get the peer address.
uint32_t m_timestampToEcho
Timestamp to echo.
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.
TracedValue< SequenceNumber32 > m_highRxMark
Highest seqno received.
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:53
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:220
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:84
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.
uint8_t m_rcvScaleFactor
Received Window Scale (i.e., the one of the peer)
bool m_shutdownRecv
Receive no longer allowed.
virtual Time GetDelAckTimeout(void) const
Get the time to delay an ACK.
EventId m_sendPendingDataEvent
micro-delay event to send pending data
virtual void DelAckTimeout(void)
Action upon delay ACK timeout, i.e.
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:490
virtual void LastAckTimeout(void)
Timeout at LAST_ACK, close the connection.
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
This class can be used to hold variables of floating point type such as 'double' or 'float'...
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:1145
void ProcessOptionTimestamp(const Ptr< const TcpOption > option)
Process the timestamp option from other side.
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:455
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
void SetIcmpCallback(Callback< void, Ipv4Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
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:57
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:295
TypeId SetParent(TypeId tid)
Definition: type-id.cc:638
Time m_clockGranularity
Clock Granularity used in RTO calcs.
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
Receiver window (RCV.WND in RFC793)
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:247
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
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
void AddOptionWScale(TcpHeader &header)
Add the window scale option to the header.
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.
void Destroy6(void)
Kill this socket by zeroing its attributes (IPv6)
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.