A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
nsc-tcp-socket-impl.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  * based on tcp-socket-impl.cc, Author: Raj Bhattacharjea <raj.b@gatech.edu>
17  * Author: Florian Westphal <fw@strlen.de>
18  */
19 
20 #define NS_LOG_APPEND_CONTEXT \
21  if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
22 
23 #include "ns3/node.h"
24 #include "ns3/inet-socket-address.h"
25 #include "ns3/log.h"
26 #include "ns3/ipv4.h"
27 #include "ipv4-end-point.h"
28 #include "nsc-tcp-l4-protocol.h"
29 #include "nsc-tcp-socket-impl.h"
30 #include "ns3/simulation-singleton.h"
31 #include "ns3/simulator.h"
32 #include "ns3/packet.h"
33 #include "ns3/uinteger.h"
34 #include "ns3/trace-source-accessor.h"
35 
36 #include <algorithm>
37 
38 // for ntohs().
39 #include <arpa/inet.h>
40 #include <netinet/in.h>
41 #include "sim_interface.h"
42 
43 #include "sim_errno.h"
44 
45 NS_LOG_COMPONENT_DEFINE ("NscTcpSocketImpl");
46 
47 using namespace std;
48 
49 namespace ns3 {
50 
51 NS_OBJECT_ENSURE_REGISTERED (NscTcpSocketImpl);
52 
53 TypeId
54 NscTcpSocketImpl::GetTypeId ()
55 {
56  static TypeId tid = TypeId ("ns3::NscTcpSocketImpl")
57  .SetParent<TcpSocket> ()
58  .AddTraceSource ("CongestionWindow",
59  "The TCP connection's congestion window",
60  MakeTraceSourceAccessor (&NscTcpSocketImpl::m_cWnd))
61  ;
62  return tid;
63 }
64 
65 NscTcpSocketImpl::NscTcpSocketImpl ()
66  : m_endPoint (0),
67  m_node (0),
68  m_tcp (0),
69  m_localAddress (Ipv4Address::GetZero ()),
70  m_localPort (0),
71  m_peerAddress ("0.0.0.0", 0),
72  m_errno (ERROR_NOTERROR),
73  m_shutdownSend (false),
74  m_shutdownRecv (false),
75  m_connected (false),
76  m_state (CLOSED),
77  m_closeOnEmpty (false),
78  m_txBufferSize (0),
79  m_lastMeasuredRtt (Seconds (0.0))
80 {
81  NS_LOG_FUNCTION (this);
82 }
83 
85  : TcpSocket (sock), //copy the base class callbacks
86  m_delAckMaxCount (sock.m_delAckMaxCount),
87  m_delAckTimeout (sock.m_delAckTimeout),
88  m_noDelay (sock.m_noDelay),
89  m_endPoint (0),
90  m_node (sock.m_node),
91  m_tcp (sock.m_tcp),
92  m_remoteAddress (sock.m_remoteAddress),
93  m_remotePort (sock.m_remotePort),
94  m_localAddress (sock.m_localAddress),
95  m_localPort (sock.m_localPort),
96  m_peerAddress (sock.m_peerAddress),
97  m_errno (sock.m_errno),
98  m_shutdownSend (sock.m_shutdownSend),
99  m_shutdownRecv (sock.m_shutdownRecv),
100  m_connected (sock.m_connected),
101  m_state (sock.m_state),
102  m_closeOnEmpty (sock.m_closeOnEmpty),
103  m_txBufferSize (sock.m_txBufferSize),
104  m_segmentSize (sock.m_segmentSize),
105  m_rxWindowSize (sock.m_rxWindowSize),
106  m_advertisedWindowSize (sock.m_advertisedWindowSize),
107  m_cWnd (sock.m_cWnd),
108  m_ssThresh (sock.m_ssThresh),
109  m_initialCWnd (sock.m_initialCWnd),
110  m_lastMeasuredRtt (Seconds (0.0)),
111  m_cnTimeout (sock.m_cnTimeout),
112  m_cnCount (sock.m_cnCount),
113  m_rxAvailable (0),
114  m_nscTcpSocket (0),
115  m_sndBufSize (sock.m_sndBufSize)
116 {
118  NS_LOG_LOGIC ("Invoked the copy constructor");
119  //copy the pending data if necessary
120  if(!sock.m_txBuffer.empty () )
121  {
122  m_txBuffer = sock.m_txBuffer;
123  }
124  //can't "copy" the endpoint just yes, must do this when we know the peer info
125  //too; this is in SYN_ACK_TX
126 }
127 
129 {
130  NS_LOG_FUNCTION (this);
131  m_node = 0;
132  if (m_endPoint != 0)
133  {
134  NS_ASSERT (m_tcp != 0);
143  NS_ASSERT (m_endPoint != 0);
145  NS_ASSERT (m_endPoint == 0);
146  }
147  m_tcp = 0;
148 }
149 
150 void
152 {
153  m_node = node;
154  // Initialize some variables
157 }
158 
159 void
161 {
163  m_tcp = tcp;
164 }
165 
166 
169 {
171  return m_errno;
172 }
173 
176 {
177  return NS3_SOCK_STREAM;
178 }
179 
180 Ptr<Node>
182 {
184  return m_node;
185 }
186 
187 void
189 {
191  m_node = 0;
192  m_endPoint = 0;
193  m_tcp = 0;
194 }
195 int
197 {
199  if (m_endPoint == 0)
200  {
201  return -1;
202  }
207  return 0;
208 }
209 
210 int
212 {
214  m_endPoint = m_tcp->Allocate ();
215  return FinishBind ();
216 }
217 int
219 {
220  NS_LOG_LOGIC ("NscTcpSocketImpl: ERROR_AFNOSUPPORT - Bind6 not supported");
222  return (-1);
223 }
224 int
226 {
227  NS_LOG_FUNCTION (this<<address);
228  if (!InetSocketAddress::IsMatchingType (address))
229  {
230  return ERROR_INVAL;
231  }
233  Ipv4Address ipv4 = transport.GetIpv4 ();
234  uint16_t port = transport.GetPort ();
235  if (ipv4 == Ipv4Address::GetAny () && port == 0)
236  {
237  m_endPoint = m_tcp->Allocate ();
238  NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
239  }
240  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
241  {
242  m_endPoint = m_tcp->Allocate (port);
243  NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
244  }
245  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
246  {
247  m_endPoint = m_tcp->Allocate (ipv4);
248  NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
249  }
250  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
251  {
252  m_endPoint = m_tcp->Allocate (ipv4, port);
253  NS_LOG_LOGIC ("NscTcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
254  }
255 
256  m_localPort = port;
257  return FinishBind ();
258 }
259 
260 int
262 {
264  m_shutdownSend = true;
265  return 0;
266 }
267 int
269 {
271  m_shutdownRecv = true;
272  return 0;
273 }
274 
275 int
277 {
278  NS_LOG_FUNCTION (this << m_state);
279 
280  if (m_state == CLOSED)
281  {
282  return -1;
283  }
284  if (!m_txBuffer.empty ())
285  { // App close with pending data must wait until all data transmitted
286  m_closeOnEmpty = true;
287  NS_LOG_LOGIC ("Socket " << this <<
288  " deferring close, state " << m_state);
289  return 0;
290  }
291 
292  NS_LOG_LOGIC ("NscTcp socket " << this << " calling disconnect(); moving to CLOSED");
294  m_state = CLOSED;
295  ShutdownSend ();
296  return 0;
297 }
298 
299 int
301 {
302  NS_LOG_FUNCTION (this << address);
303  if (m_endPoint == 0)
304  {
305  if (Bind () == -1)
306  {
307  NS_ASSERT (m_endPoint == 0);
308  return -1;
309  }
310  NS_ASSERT (m_endPoint != 0);
311  }
313  m_remoteAddress = transport.GetIpv4 ();
314  m_remotePort = transport.GetPort ();
315 
316  std::ostringstream ss;
317  m_remoteAddress.Print (ss);
318  std::string ipstring = ss.str ();
319 
320  m_nscTcpSocket->connect (ipstring.c_str (), m_remotePort);
321  m_state = SYN_SENT;
322  return 0;
323 }
324 
325 int
326 NscTcpSocketImpl::Send (const Ptr<Packet> p, uint32_t flags)
327 {
328  NS_LOG_FUNCTION (this << p);
329 
330  NS_ASSERT (p->GetSize () > 0);
332  {
333  if (p->GetSize () > GetTxAvailable ())
334  {
336  return -1;
337  }
338 
339  uint32_t sent = p->GetSize ();
340  if (m_state == ESTABLISHED)
341  {
342  m_txBuffer.push (p);
343  m_txBufferSize += sent;
344  SendPendingData ();
345  }
346  else
347  { // SYN_SET -- Queue Data
348  m_txBuffer.push (p);
349  m_txBufferSize += sent;
350  }
351  return sent;
352  }
353  else
354  {
356  return -1;
357  }
358 }
359 
360 int
361 NscTcpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
362 {
363  NS_LOG_FUNCTION (this << address << p);
364  if (!m_connected)
365  {
367  return -1;
368  }
369  else
370  {
371  return Send (p, flags); //drop the address according to BSD manpages
372  }
373 }
374 
375 uint32_t
377 {
379  if (m_txBufferSize != 0)
380  {
382  return m_sndBufSize - m_txBufferSize;
383  }
384  else
385  {
386  return m_sndBufSize;
387  }
388 }
389 
390 int
392 {
393  NS_LOG_FUNCTION (this);
395  m_state = LISTEN;
396  return 0;
397 }
398 
399 
400 void
402 {
403  switch (m_state) {
404  case SYN_SENT:
405  if (!m_nscTcpSocket->is_connected ())
406  break;
409  // fall through to schedule read/write events
410  case ESTABLISHED:
411  if (!m_txBuffer.empty ())
414  break;
415  case LISTEN:
417  break;
418  case CLOSED: break;
419  default:
420  NS_LOG_DEBUG (this << " invalid state: " << m_state);
421  }
422 }
423 
425 NscTcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
426 {
428  if (m_deliveryQueue.empty () )
429  {
431  return 0;
432  }
433  Ptr<Packet> p = m_deliveryQueue.front ();
434  if (p->GetSize () <= maxSize)
435  {
436  m_deliveryQueue.pop ();
437  m_rxAvailable -= p->GetSize ();
438  }
439  else
440  {
442  p = 0;
443  }
444  return p;
445 }
446 
448 NscTcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
449  Address &fromAddress)
450 {
451  NS_LOG_FUNCTION (this << maxSize << flags);
452  Ptr<Packet> packet = Recv (maxSize, flags);
453  if (packet != 0)
454  {
455  SocketAddressTag tag;
456  bool found;
457  found = packet->PeekPacketTag (tag);
458  NS_ASSERT (found);
459  fromAddress = tag.GetAddress ();
460  }
461  return packet;
462 }
463 
464 int
466 {
469  return 0;
470 }
471 
472 uint32_t
474 {
476  // We separately maintain this state to avoid walking the queue
477  // every time this might be called
478  return m_rxAvailable;
479 }
480 
481 void
483  Ptr<Ipv4Interface> incomingInterface)
484 {
485  NSCWakeup ();
486 }
487 
489 {
490  // The address pairs (m_localAddress, m_localPort, m_remoteAddress, m_remotePort)
491  // are bogus, but this isn't important at the moment, because
492  // address <-> Socket handling is done by NSC internally.
493  // We only need to add the new ns-3 socket to the list of sockets, so
494  // we use plain Allocate() instead of Allocate(m_localAddress, ... )
495  struct sockaddr_in sin;
496  size_t sin_len = sizeof(sin);
497 
498  if (0 == m_nscTcpSocket->getpeername ((struct sockaddr*) &sin, &sin_len)) {
499  m_remotePort = ntohs (sin.sin_port);
500  m_remoteAddress = Ipv4Address::Deserialize ((const uint8_t*) &sin.sin_addr);
502  }
503 
504  m_endPoint = m_tcp->Allocate ();
505 
506  //the cloned socket with be in listen state, so manually change state
507  NS_ASSERT (m_state == LISTEN);
509 
510  sin_len = sizeof(sin);
511 
512  if (0 == m_nscTcpSocket->getsockname ((struct sockaddr *) &sin, &sin_len))
513  m_localAddress = Ipv4Address::Deserialize ((const uint8_t*) &sin.sin_addr);
514 
515  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " accepted connection from "
516  << m_remoteAddress << ":" << m_remotePort
517  << " to " << m_localAddress << ":" << m_localPort);
518  //equivalent to FinishBind
521 
523 }
524 
526 { // We would preferred to have scheduled an event directly to
527  // NotifyConnectionSucceeded, but (sigh) these are protected
528  // and we can get the address of it :(
529  struct sockaddr_in sin;
530  size_t sin_len = sizeof(sin);
531  if (0 == m_nscTcpSocket->getsockname ((struct sockaddr *) &sin, &sin_len)) {
532  m_localAddress = Ipv4Address::Deserialize ((const uint8_t*)&sin.sin_addr);
533  m_localPort = ntohs (sin.sin_port);
534  }
535 
536  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " connected to "
537  << m_remoteAddress << ":" << m_remotePort
538  << " from " << m_localAddress << ":" << m_localPort);
540 }
541 
542 
544 {
545  if (m_state == CLOSED)
546  { // Happens if application closes listening socket after Accept() was scheduled.
547  return false;
548  }
549  NS_ASSERT (m_state == LISTEN);
550 
551  if (!m_nscTcpSocket->is_listening ())
552  {
553  return false;
554  }
555  INetStreamSocket *newsock;
556  int res = m_nscTcpSocket->accept (&newsock);
557  if (res != 0)
558  {
559  return false;
560  }
561 // We could obtain a fromAddress using getpeername, but we've already
562 // finished the tcp handshake here, i.e. this is a new connection
563 // and not a connection request.
564 // if (!NotifyConnectionRequest(fromAddress))
565 // return true;
566 
567  // Clone the socket
568  Ptr<NscTcpSocketImpl> newSock = Copy ();
569  newSock->m_nscTcpSocket = newsock;
570  NS_LOG_LOGIC ("Cloned a NscTcpSocketImpl " << newSock);
571 
573  return true;
574 }
575 
577 {
578  if (m_state != ESTABLISHED)
579  {
580  return false;
581  }
582  int len, err;
583  uint8_t buffer[8192];
584  len = sizeof(buffer);
586  err = m_nscTcpSocket->read_data (buffer, &len);
587  if (err == 0 && len == 0)
588  {
589  NS_LOG_LOGIC ("ReadPendingData got EOF from socket");
591  return false;
592  }
593  m_errno = GetNativeNs3Errno (err);
594  switch (m_errno)
595  {
596  case ERROR_NOTERROR: break; // some data was sent
597  case ERROR_AGAIN: return false;
598  default:
599  NS_LOG_WARN ("Error (" << err << ") " <<
600  "during read_data, ns-3 errno set to" << m_errno);
601  m_state = CLOSED;
602  return false;
603  }
604 
605  Ptr<Packet> p = Create<Packet> (buffer, len);
606 
607  SocketAddressTag tag;
608 
610  p->AddPacketTag (tag);
611  m_deliveryQueue.push (p);
612  m_rxAvailable += p->GetSize ();
613 
614  NotifyDataRecv ();
615  return true;
616 }
617 
619 {
620  NS_LOG_FUNCTION (this);
621  NS_LOG_LOGIC ("ENTERING SendPendingData");
622 
623  if (m_txBuffer.empty ())
624  {
625  return false;
626  }
627 
628  int ret;
629  size_t size, written = 0;
630 
631  do {
632  NS_ASSERT (!m_txBuffer.empty ());
633  Ptr<Packet> &p = m_txBuffer.front ();
634  size = p->GetSize ();
635  NS_ASSERT (size > 0);
636 
638 
639  uint8_t *buf = new uint8_t[size];
640  p->CopyData (buf, size);
641  ret = m_nscTcpSocket->send_data ((const char *)buf, size);
642  delete[] buf;
643 
644  if (ret <= 0)
645  {
646  break;
647  }
648  written += ret;
649 
650  NS_ASSERT (m_txBufferSize >= (size_t)ret);
651  m_txBufferSize -= ret;
652 
653  if ((size_t)ret < size)
654  {
655  p->RemoveAtStart (ret);
656  break;
657  }
658 
659  m_txBuffer.pop ();
660 
661  if (m_txBuffer.empty ())
662  {
663  if (m_closeOnEmpty)
664  {
666  m_state = CLOSED;
667  }
668  break;
669  }
670  } while ((size_t) ret == size);
671 
672  if (written > 0)
673  {
675  return true;
676  }
677  return false;
678 }
679 
681 {
682  return CopyObject<NscTcpSocketImpl> (this);
683 }
684 
685 void
687 {
688  m_sndBufSize = size;
689 }
690 
691 uint32_t
693 {
694  return m_sndBufSize;
695 }
696 
697 void
699 {
700  m_rcvBufSize = size;
701 }
702 
703 uint32_t
705 {
706  return m_rcvBufSize;
707 }
708 
709 void
711 {
712  m_segmentSize = size;
713 }
714 
715 uint32_t
717 {
718  return m_segmentSize;
719 }
720 
721 void
723 {
724  m_advertisedWindowSize = window;
725 }
726 
727 uint32_t
729 {
730  return m_advertisedWindowSize;
731 }
732 
733 void
734 NscTcpSocketImpl::SetSSThresh (uint32_t threshold)
735 {
736  m_ssThresh = threshold;
737 }
738 
739 uint32_t
741 {
742  return m_ssThresh;
743 }
744 
745 void
747 {
748  m_initialCWnd = cwnd;
749 }
750 
751 uint32_t
753 {
754  return m_initialCWnd;
755 }
756 
757 void
759 {
761 }
762 
763 Time
765 {
766  return m_cnTimeout;
767 }
768 
769 void
771 {
772  m_cnCount = count;
773 }
774 
775 uint32_t
777 {
778  return m_cnCount;
779 }
780 
781 void
783 {
785 }
786 
787 Time
789 {
790  return m_delAckTimeout;
791 }
792 
793 void
795 {
796  m_delAckMaxCount = count;
797 }
798 
799 uint32_t
801 {
802  return m_delAckMaxCount;
803 }
804 
805 void
807 {
808  m_noDelay = noDelay;
809 }
810 
811 bool
813 {
814  return m_noDelay;
815 }
816 
817 void
819 {
821 }
822 
823 Time
825 {
826  return m_persistTimeout;
827 }
828 
831 {
832  enum nsc_errno err;
833 
834  if (error >= 0)
835  {
836  return ERROR_NOTERROR;
837  }
838  err = (enum nsc_errno) error;
839  switch (err)
840  {
841  case NSC_EADDRINUSE: // fallthrough
843  case NSC_EINPROGRESS: // Altough nsc sockets are nonblocking, we pretend they're not.
844  case NSC_EAGAIN: return ERROR_AGAIN;
845  case NSC_EISCONN: // fallthrough
846  case NSC_EALREADY: return ERROR_ISCONN;
847  case NSC_ECONNREFUSED: return ERROR_NOROUTETOHOST; // XXX, better mapping?
848  case NSC_ECONNRESET: // for no, all of these fall through
849  case NSC_EHOSTDOWN:
850  case NSC_ENETUNREACH:
852  case NSC_EMSGSIZE: return ERROR_MSGSIZE;
853  case NSC_ENOTCONN: return ERROR_NOTCONN;
854  case NSC_ESHUTDOWN: return ERROR_SHUTDOWN;
855  case NSC_ETIMEDOUT: return ERROR_NOTCONN; // XXX - this mapping isn't correct
856  case NSC_ENOTDIR: // used by eg. sysctl(2). Shouldn't happen normally,
857  // but is triggered by e.g. show_config().
858  case NSC_EUNKNOWN: return ERROR_INVAL; // Catches stacks that 'return -1' without real mapping
859  }
860  NS_ASSERT_MSG (0, "Unknown NSC error");
861  return ERROR_INVAL;
862 }
863 
864 bool
866 {
867  if (allowBroadcast)
868  {
869  return false;
870  }
871  return true;
872 }
873 
874 bool
876 {
877  return false;
878 }
879 
880 } // namespace ns3