src/node/packet-socket.cc
author Duy Nguyen <dnlove@gmail.com>
Thu Aug 06 21:58:04 2009 -0700 (2009-08-06)
changeset 4698 60cd412fa3dd
parent 4502 07d34c0d8d18
child 6197 ebe303de4725
permissions -rw-r--r--
fix for bug 650 (PacketSocket Close()
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2007 Emmanuelle Laprise, INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Authors: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
    19  *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    20  */
    21 
    22 #include "packet-socket.h"
    23 #include "packet-socket-address.h"
    24 #include "ns3/log.h"
    25 #include "ns3/node.h"
    26 #include "ns3/packet.h"
    27 #include "ns3/uinteger.h"
    28 #include "ns3/trace-source-accessor.h"
    29 
    30 #include <algorithm>
    31 
    32 NS_LOG_COMPONENT_DEFINE ("PacketSocket");
    33 
    34 namespace ns3 {
    35 
    36 TypeId
    37 PacketSocket::GetTypeId (void)
    38 {
    39   static TypeId tid = TypeId ("ns3::PacketSocket")
    40     .SetParent<Socket> ()
    41     .AddConstructor<PacketSocket> ()
    42     .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
    43                      MakeTraceSourceAccessor (&PacketSocket::m_dropTrace))
    44     .AddAttribute ("RcvBufSize",
    45                    "PacketSocket maximum receive buffer size (bytes)",
    46                    UintegerValue (0xffffffffl),
    47                    MakeUintegerAccessor (&PacketSocket::m_rcvBufSize),
    48                    MakeUintegerChecker<uint32_t> ())
    49     ;
    50   return tid;
    51 }
    52 
    53 PacketSocket::PacketSocket () : m_rxAvailable (0)
    54 {
    55   NS_LOG_FUNCTION (this);
    56   m_state = STATE_OPEN;
    57   m_shutdownSend = false;
    58   m_shutdownRecv = false;
    59   m_errno = ERROR_NOTERROR;
    60   m_isSingleDevice = false;
    61   m_device = 0;
    62 }
    63 
    64 void 
    65 PacketSocket::SetNode (Ptr<Node> node)
    66 {
    67   NS_LOG_FUNCTION (this << node);
    68   m_node = node;
    69 }
    70 
    71 PacketSocket::~PacketSocket ()
    72 {
    73   NS_LOG_FUNCTION (this);
    74 }
    75 
    76 void 
    77 PacketSocket::DoDispose (void)
    78 {
    79   NS_LOG_FUNCTION (this);
    80   m_device = 0;
    81 }
    82 
    83 enum Socket::SocketErrno
    84 PacketSocket::GetErrno (void) const
    85 {
    86   NS_LOG_FUNCTION (this);
    87   return m_errno;
    88 }
    89 
    90 Ptr<Node>
    91 PacketSocket::GetNode (void) const
    92 {
    93   NS_LOG_FUNCTION (this);
    94   return m_node;
    95 }
    96 
    97 int
    98 PacketSocket::Bind (void)
    99 {
   100   NS_LOG_FUNCTION (this);
   101   PacketSocketAddress address;
   102   address.SetProtocol (0);
   103   address.SetAllDevices ();
   104   return DoBind (address);
   105 }
   106 
   107 int
   108 PacketSocket::Bind (const Address &address)
   109 { 
   110   NS_LOG_FUNCTION (this << address);
   111   if (!PacketSocketAddress::IsMatchingType (address))
   112     {
   113       m_errno = ERROR_INVAL;
   114       return -1;
   115     }
   116   PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (address);
   117   return DoBind (ad);
   118 }
   119 
   120 int
   121 PacketSocket::DoBind (const PacketSocketAddress &address)
   122 {
   123   NS_LOG_FUNCTION (this << address);
   124   if (m_state == STATE_BOUND ||
   125       m_state == STATE_CONNECTED)
   126     {
   127       m_errno = ERROR_INVAL;
   128       return -1;
   129     }
   130   if (m_state == STATE_CLOSED)
   131     {
   132       m_errno = ERROR_BADF;
   133       return -1;
   134     }
   135   Ptr<NetDevice> dev ;
   136   if (address.IsSingleDevice ())
   137     {
   138       dev = m_node->GetDevice (address.GetSingleDevice ());
   139     }
   140   else
   141     {
   142       dev = 0;
   143     }
   144   m_node->RegisterProtocolHandler (MakeCallback (&PacketSocket::ForwardUp, this),
   145                                    address.GetProtocol (), dev);
   146   m_state = STATE_BOUND;
   147   m_protocol = address.GetProtocol ();
   148   m_isSingleDevice = address.IsSingleDevice ();
   149   m_device = address.GetSingleDevice ();
   150   return 0;
   151 }
   152 
   153 int
   154 PacketSocket::ShutdownSend (void)
   155 {
   156   NS_LOG_FUNCTION (this);
   157   if (m_state == STATE_CLOSED)
   158     {
   159       m_errno = ERROR_BADF;
   160       return -1;
   161     }
   162   m_shutdownSend = true;
   163   return 0;
   164 }
   165 
   166 int
   167 PacketSocket::ShutdownRecv (void)
   168 {
   169   NS_LOG_FUNCTION (this);
   170   if (m_state == STATE_CLOSED)
   171     {
   172       m_errno = ERROR_BADF;
   173       return -1;
   174     }
   175   m_shutdownRecv = true;
   176   return 0;
   177 }
   178 
   179 int
   180 PacketSocket::Close(void)
   181 {
   182   NS_LOG_FUNCTION (this);
   183   if (m_state == STATE_CLOSED)
   184     {
   185       m_errno = ERROR_BADF;
   186       return -1;
   187     }
   188   m_state = STATE_CLOSED;
   189   m_shutdownSend = true;
   190   m_shutdownRecv = true;
   191   return 0;
   192 }
   193 
   194 int
   195 PacketSocket::Connect(const Address &ad)
   196 {
   197   NS_LOG_FUNCTION (this << ad);
   198   PacketSocketAddress address;
   199   if (m_state == STATE_CLOSED)
   200     {
   201       m_errno = ERROR_BADF;
   202       goto error;
   203     }
   204   if (m_state == STATE_OPEN)
   205     {
   206       // connect should happen _after_ bind.
   207       m_errno = ERROR_INVAL; // generic error condition.
   208       goto error;
   209     }
   210   if (m_state == STATE_CONNECTED)
   211     {
   212       m_errno = ERROR_ISCONN;
   213       goto error;
   214     }
   215   if (!PacketSocketAddress::IsMatchingType (ad))
   216     {
   217       m_errno = ERROR_AFNOSUPPORT;
   218       goto error;
   219     }
   220   m_destAddr = ad;
   221   m_state = STATE_CONNECTED;
   222   NotifyConnectionSucceeded ();
   223   return 0;
   224  error:
   225   NotifyConnectionFailed ();
   226   return -1;
   227 }
   228 int 
   229 PacketSocket::Listen(void)
   230 {
   231   m_errno = Socket::ERROR_OPNOTSUPP;
   232   return -1;
   233 }
   234 
   235 int
   236 PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
   237 {
   238   NS_LOG_FUNCTION (this << p << flags);
   239   if (m_state == STATE_OPEN ||
   240       m_state == STATE_BOUND)
   241     {
   242       m_errno = ERROR_NOTCONN;
   243       return -1;
   244     }
   245   return SendTo (p, flags, m_destAddr);
   246 }
   247 
   248 uint32_t
   249 PacketSocket::GetMinMtu (PacketSocketAddress ad) const
   250 {
   251   if (ad.IsSingleDevice ())
   252     {
   253       Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
   254       return device->GetMtu ();
   255     }
   256   else
   257     {
   258       uint32_t minMtu = 0xffff;
   259       for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
   260         {
   261           Ptr<NetDevice> device = m_node->GetDevice (i);
   262           minMtu = std::min (minMtu, (uint32_t)device->GetMtu ());
   263         }
   264       return minMtu;
   265     }
   266 }
   267 
   268 uint32_t 
   269 PacketSocket::GetTxAvailable (void) const
   270 {
   271   if (m_state == STATE_CONNECTED)
   272     {
   273       PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (m_destAddr);      
   274       return GetMinMtu (ad);
   275     }
   276   // If we are not connected, we return a 'safe' value by default.
   277   return 0xffff;
   278 }
   279 
   280 int
   281 PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
   282 {
   283   NS_LOG_FUNCTION (this << p << flags << address);
   284   PacketSocketAddress ad;
   285   if (m_state == STATE_CLOSED)
   286     {
   287       NS_LOG_LOGIC ("ERROR_BADF");
   288       m_errno = ERROR_BADF;
   289       return -1;
   290     }
   291   if (m_shutdownSend)
   292     {
   293       NS_LOG_LOGIC ("ERROR_SHUTDOWN");
   294       m_errno = ERROR_SHUTDOWN;
   295       return -1;
   296     }
   297   if (!PacketSocketAddress::IsMatchingType (address))
   298     {
   299       NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
   300       m_errno = ERROR_AFNOSUPPORT;
   301       return -1;
   302     }
   303   ad = PacketSocketAddress::ConvertFrom (address);
   304   if (p->GetSize () > GetMinMtu (ad))
   305     {
   306       m_errno = ERROR_MSGSIZE;
   307       return -1;
   308     }
   309   
   310   bool error = false;
   311   Address dest = ad.GetPhysicalAddress ();
   312   if (ad.IsSingleDevice ())
   313     {
   314       Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
   315       if (!device->Send (p, dest, ad.GetProtocol ()))
   316         {
   317           NS_LOG_LOGIC ("error: NetDevice::Send error");
   318           error = true;
   319         }
   320     }
   321   else
   322     {
   323       for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
   324         {
   325           Ptr<NetDevice> device = m_node->GetDevice (i);
   326           if (!device->Send (p, dest, ad.GetProtocol ()))
   327             {
   328               NS_LOG_LOGIC ("error: NetDevice::Send error");
   329               error = true;
   330             }
   331         }
   332     }
   333   if (!error)
   334     {
   335       NotifyDataSent (p->GetSize ());
   336       NotifySend (GetTxAvailable ());
   337     }
   338 
   339   if (error)
   340     {
   341       NS_LOG_LOGIC ("ERROR_INVAL 2");
   342       m_errno = ERROR_INVAL;
   343       return -1;
   344     }
   345   else
   346     {
   347       return 0;
   348     }
   349 }
   350 
   351 void 
   352 PacketSocket::ForwardUp (Ptr<NetDevice> device, Ptr<const Packet> packet, 
   353                          uint16_t protocol, const Address &from,
   354                          const Address &to, NetDevice::PacketType packetType)
   355 {
   356   NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
   357   if (m_shutdownRecv)
   358     {
   359       return;
   360     }
   361 
   362 
   363   PacketSocketAddress address;
   364   address.SetPhysicalAddress (from);
   365   address.SetSingleDevice (device->GetIfIndex ());
   366   address.SetProtocol (protocol);
   367 
   368   if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
   369     {
   370       Ptr<Packet> copy = packet->Copy ();
   371       SocketAddressTag tag;
   372       tag.SetAddress (address);
   373       copy->AddPacketTag (tag);
   374       m_deliveryQueue.push (copy);
   375       m_rxAvailable += packet->GetSize ();
   376       NS_LOG_LOGIC ("UID is " << packet->GetUid() << " PacketSocket " << this);
   377       NotifyDataRecv ();
   378     }
   379   else
   380     {
   381       // In general, this case should not occur unless the
   382       // receiving application reads data from this socket slowly
   383       // in comparison to the arrival rate
   384       //
   385       // drop and trace packet
   386       NS_LOG_WARN ("No receive buffer space available.  Drop.");
   387       m_dropTrace (packet);
   388     }
   389 }
   390 
   391 uint32_t
   392 PacketSocket::GetRxAvailable (void) const
   393 {
   394   NS_LOG_FUNCTION (this);
   395   // We separately maintain this state to avoid walking the queue 
   396   // every time this might be called
   397   return m_rxAvailable;
   398 }
   399 
   400 Ptr<Packet> 
   401 PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
   402 {
   403   NS_LOG_FUNCTION (this << maxSize << flags);
   404   if (m_deliveryQueue.empty() )
   405     {
   406       return 0;
   407     }
   408   Ptr<Packet> p = m_deliveryQueue.front ();
   409   if (p->GetSize () <= maxSize)
   410     {
   411       m_deliveryQueue.pop ();
   412       m_rxAvailable -= p->GetSize ();
   413     }
   414   else
   415     {
   416       p = 0;
   417     }
   418   return p;
   419 }
   420 
   421 Ptr<Packet>
   422 PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
   423 {
   424   NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
   425   Ptr<Packet> packet = Recv (maxSize, flags);
   426   if (packet != 0)
   427     {
   428       SocketAddressTag tag;
   429       bool found;
   430       found = packet->PeekPacketTag (tag);
   431       NS_ASSERT (found);
   432       fromAddress = tag.GetAddress ();
   433     }
   434   return packet;
   435 }
   436 
   437 int
   438 PacketSocket::GetSockName (Address &address) const
   439 {
   440   NS_LOG_FUNCTION (this << address);
   441   PacketSocketAddress ad = PacketSocketAddress::ConvertFrom(address);
   442   
   443   ad.SetProtocol (m_protocol);
   444   if (m_isSingleDevice)
   445     {
   446       Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
   447       ad.SetPhysicalAddress(device->GetAddress());      
   448       ad.SetSingleDevice (m_device);
   449     }
   450   else
   451     {
   452       ad.SetPhysicalAddress(Address());   
   453       ad.SetAllDevices ();
   454     }  
   455   address = ad;
   456   
   457   return 0;
   458 }
   459 
   460 }//namespace ns3