1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2007 Emmanuelle Laprise, INRIA
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Authors: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
19 * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
22 #include "packet-socket.h"
23 #include "packet-socket-address.h"
26 #include "ns3/packet.h"
27 #include "ns3/uinteger.h"
28 #include "ns3/trace-source-accessor.h"
32 NS_LOG_COMPONENT_DEFINE ("PacketSocket");
37 PacketSocket::GetTypeId (void)
39 static TypeId tid = TypeId ("ns3::PacketSocket")
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> ())
53 PacketSocket::PacketSocket () : m_rxAvailable (0)
55 NS_LOG_FUNCTION (this);
57 m_shutdownSend = false;
58 m_shutdownRecv = false;
59 m_errno = ERROR_NOTERROR;
60 m_isSingleDevice = false;
65 PacketSocket::SetNode (Ptr<Node> node)
67 NS_LOG_FUNCTION (this << node);
71 PacketSocket::~PacketSocket ()
73 NS_LOG_FUNCTION (this);
77 PacketSocket::DoDispose (void)
79 NS_LOG_FUNCTION (this);
83 enum Socket::SocketErrno
84 PacketSocket::GetErrno (void) const
86 NS_LOG_FUNCTION (this);
91 PacketSocket::GetNode (void) const
93 NS_LOG_FUNCTION (this);
98 PacketSocket::Bind (void)
100 NS_LOG_FUNCTION (this);
101 PacketSocketAddress address;
102 address.SetProtocol (0);
103 address.SetAllDevices ();
104 return DoBind (address);
108 PacketSocket::Bind (const Address &address)
110 NS_LOG_FUNCTION (this << address);
111 if (!PacketSocketAddress::IsMatchingType (address))
113 m_errno = ERROR_INVAL;
116 PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (address);
121 PacketSocket::DoBind (const PacketSocketAddress &address)
123 NS_LOG_FUNCTION (this << address);
124 if (m_state == STATE_BOUND ||
125 m_state == STATE_CONNECTED)
127 m_errno = ERROR_INVAL;
130 if (m_state == STATE_CLOSED)
132 m_errno = ERROR_BADF;
136 if (address.IsSingleDevice ())
138 dev = m_node->GetDevice (address.GetSingleDevice ());
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 ();
154 PacketSocket::ShutdownSend (void)
156 NS_LOG_FUNCTION (this);
157 if (m_state == STATE_CLOSED)
159 m_errno = ERROR_BADF;
162 m_shutdownSend = true;
167 PacketSocket::ShutdownRecv (void)
169 NS_LOG_FUNCTION (this);
170 if (m_state == STATE_CLOSED)
172 m_errno = ERROR_BADF;
175 m_shutdownRecv = true;
180 PacketSocket::Close(void)
182 NS_LOG_FUNCTION (this);
183 if (m_state == STATE_CLOSED)
185 m_errno = ERROR_BADF;
188 m_state = STATE_CLOSED;
189 m_shutdownSend = true;
190 m_shutdownRecv = true;
195 PacketSocket::Connect(const Address &ad)
197 NS_LOG_FUNCTION (this << ad);
198 PacketSocketAddress address;
199 if (m_state == STATE_CLOSED)
201 m_errno = ERROR_BADF;
204 if (m_state == STATE_OPEN)
206 // connect should happen _after_ bind.
207 m_errno = ERROR_INVAL; // generic error condition.
210 if (m_state == STATE_CONNECTED)
212 m_errno = ERROR_ISCONN;
215 if (!PacketSocketAddress::IsMatchingType (ad))
217 m_errno = ERROR_AFNOSUPPORT;
221 m_state = STATE_CONNECTED;
222 NotifyConnectionSucceeded ();
225 NotifyConnectionFailed ();
229 PacketSocket::Listen(void)
231 m_errno = Socket::ERROR_OPNOTSUPP;
236 PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
238 NS_LOG_FUNCTION (this << p << flags);
239 if (m_state == STATE_OPEN ||
240 m_state == STATE_BOUND)
242 m_errno = ERROR_NOTCONN;
245 return SendTo (p, flags, m_destAddr);
249 PacketSocket::GetMinMtu (PacketSocketAddress ad) const
251 if (ad.IsSingleDevice ())
253 Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
254 return device->GetMtu ();
258 uint32_t minMtu = 0xffff;
259 for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
261 Ptr<NetDevice> device = m_node->GetDevice (i);
262 minMtu = std::min (minMtu, (uint32_t)device->GetMtu ());
269 PacketSocket::GetTxAvailable (void) const
271 if (m_state == STATE_CONNECTED)
273 PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (m_destAddr);
274 return GetMinMtu (ad);
276 // If we are not connected, we return a 'safe' value by default.
281 PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
283 NS_LOG_FUNCTION (this << p << flags << address);
284 PacketSocketAddress ad;
285 if (m_state == STATE_CLOSED)
287 NS_LOG_LOGIC ("ERROR_BADF");
288 m_errno = ERROR_BADF;
293 NS_LOG_LOGIC ("ERROR_SHUTDOWN");
294 m_errno = ERROR_SHUTDOWN;
297 if (!PacketSocketAddress::IsMatchingType (address))
299 NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
300 m_errno = ERROR_AFNOSUPPORT;
303 ad = PacketSocketAddress::ConvertFrom (address);
304 if (p->GetSize () > GetMinMtu (ad))
306 m_errno = ERROR_MSGSIZE;
311 Address dest = ad.GetPhysicalAddress ();
312 if (ad.IsSingleDevice ())
314 Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
315 if (!device->Send (p, dest, ad.GetProtocol ()))
317 NS_LOG_LOGIC ("error: NetDevice::Send error");
323 for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
325 Ptr<NetDevice> device = m_node->GetDevice (i);
326 if (!device->Send (p, dest, ad.GetProtocol ()))
328 NS_LOG_LOGIC ("error: NetDevice::Send error");
335 NotifyDataSent (p->GetSize ());
336 NotifySend (GetTxAvailable ());
341 NS_LOG_LOGIC ("ERROR_INVAL 2");
342 m_errno = ERROR_INVAL;
352 PacketSocket::ForwardUp (Ptr<NetDevice> device, Ptr<const Packet> packet,
353 uint16_t protocol, const Address &from,
354 const Address &to, NetDevice::PacketType packetType)
356 NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
363 PacketSocketAddress address;
364 address.SetPhysicalAddress (from);
365 address.SetSingleDevice (device->GetIfIndex ());
366 address.SetProtocol (protocol);
368 if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
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);
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
385 // drop and trace packet
386 NS_LOG_WARN ("No receive buffer space available. Drop.");
387 m_dropTrace (packet);
392 PacketSocket::GetRxAvailable (void) const
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;
401 PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
403 NS_LOG_FUNCTION (this << maxSize << flags);
404 if (m_deliveryQueue.empty() )
408 Ptr<Packet> p = m_deliveryQueue.front ();
409 if (p->GetSize () <= maxSize)
411 m_deliveryQueue.pop ();
412 m_rxAvailable -= p->GetSize ();
422 PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
424 NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
425 Ptr<Packet> packet = Recv (maxSize, flags);
428 SocketAddressTag tag;
430 found = packet->PeekPacketTag (tag);
432 fromAddress = tag.GetAddress ();
438 PacketSocket::GetSockName (Address &address) const
440 NS_LOG_FUNCTION (this << address);
441 PacketSocketAddress ad = PacketSocketAddress::ConvertFrom(address);
443 ad.SetProtocol (m_protocol);
444 if (m_isSingleDevice)
446 Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
447 ad.SetPhysicalAddress(device->GetAddress());
448 ad.SetSingleDevice (m_device);
452 ad.SetPhysicalAddress(Address());