# HG changeset patch # User Mathieu Lacage # Date 1185951723 -7200 # Node ID 34386185bc1f993277c82f4d08ad45c1cf749be9 # Parent 8ea0f4d4fd343f70c86ed59545b4aae56297cdc3 a packet socket diff -r 8ea0f4d4fd34 -r 34386185bc1f src/node/packet-socket-address.cc --- a/src/node/packet-socket-address.cc Wed Aug 01 09:01:54 2007 +0200 +++ b/src/node/packet-socket-address.cc Wed Aug 01 09:02:03 2007 +0200 @@ -35,6 +35,18 @@ m_device = index; } void +PacketSocketAddress::SetDevice (Ptr device) +{ + if (device == 0) + { + m_device = 0; + } + else + { + m_device = device->GetIfIndex (); + } +} +void PacketSocketAddress::SetPhysicalAddress (const Address address) { m_address = address; diff -r 8ea0f4d4fd34 -r 34386185bc1f src/node/packet-socket-address.h --- a/src/node/packet-socket-address.h Wed Aug 01 09:01:54 2007 +0200 +++ b/src/node/packet-socket-address.h Wed Aug 01 09:02:03 2007 +0200 @@ -20,9 +20,11 @@ #ifndef PACKET_SOCKET_ADDRESS_H #define PACKET_SOCKET_ADDRESS_H +#include "ns3/ptr.h" #include "address.h" #include "eui48-address.h" #include "eui64-address.h" +#include "net-device.h" namespace ns3 { @@ -33,7 +35,14 @@ public: PacketSocketAddress (); void SetProtocol (uint16_t protocol); + /** + * \param index of NetDevice. + * + * index zero is reserved to identify _all_ + * Netdevices. + */ void SetDevice (uint32_t index); + void SetDevice (Ptr device); void SetPhysicalAddress (const Address address); uint16_t GetProtocol (void) const; diff -r 8ea0f4d4fd34 -r 34386185bc1f src/node/packet-socket-factory.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/node/packet-socket-factory.cc Wed Aug 01 09:02:03 2007 +0200 @@ -0,0 +1,40 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ +#include "packet-socket-factory.h" +#include "node.h" + +namespace ns3 { + +const InterfaceId PacketSocketFactory::iid = MakeInterfaceId ("Packet", + SocketFactory::iid); + +PacketSocketFactory::PacketSocketFactory () +{ + SetInterfaceId (PacketSocketFactory::iid); +} + +Ptr PacketSocketFactory::CreateSocket (void) +{ + Ptr node = QueryInterface (Node::iid); + Ptr socket = Create (node); + return socket; +} +} // namespace ns3 diff -r 8ea0f4d4fd34 -r 34386185bc1f src/node/packet-socket-factory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/node/packet-socket-factory.h Wed Aug 01 09:02:03 2007 +0200 @@ -0,0 +1,52 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ +#ifndef PACKET_SOCKET_FACTORY_H +#define PACKET_SOCKET_FACTORY_H + +#include "socket-factory.h" +#include "packet-socket.h" + +namespace ns3 { + +class Socket; + +/** + * This can be used as an interface in a node in order for the node to + * generate PacketSockets that can connect to net devices. + */ +class PacketSocketFactory : public SocketFactory +{ +public: + static const InterfaceId iid; /// Interface identifier + + PacketSocketFactory (); + + /** + * Creates a PacketSocket and returns a pointer to it. + * + * \return a pointer to the created socket + */ + virtual Ptr CreateSocket (void); +}; + +} // namespace ns3 + +#endif /* PACKET_SOCKET_FACTORY_H */ diff -r 8ea0f4d4fd34 -r 34386185bc1f src/node/packet-socket.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/node/packet-socket.cc Wed Aug 01 09:02:03 2007 +0200 @@ -0,0 +1,332 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise, INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Emmanuelle Laprise + * Mathieu Lacage + */ + +#include "packet-socket.h" +#include "packet-socket-address.h" +#include "ns3/debug.h" +#include "ns3/node.h" + +NS_DEBUG_COMPONENT_DEFINE ("PacketSocket"); + +namespace ns3 { + +PacketSocket::PacketSocket (Ptr node) + : m_node (node) +{ + Init(); +} + +void +PacketSocket::Init() +{ + m_state = STATE_OPEN; + m_shutdownSend = false; + m_shutdownRecv = false; + m_errno = ERROR_NOTERROR; +} + +PacketSocket::~PacketSocket () +{} + +void +PacketSocket::DoDispose (void) +{ + m_device = 0; +} + +Ptr +PacketSocket::GetNode (void) const +{ + return m_node; +} + + +int +PacketSocket::Bind (void) +{ + PacketSocketAddress address; + address.SetProtocol (0); + address.SetDevice (0); + return DoBind (address); +} +int +PacketSocket::Bind (const Address &address) +{ + if (!PacketSocketAddress::IsMatchingType (address)) + { + m_errno = ERROR_INVAL; + return -1; + } + PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (address); + return DoBind (ad); +} + +int +PacketSocket::DoBind (const PacketSocketAddress &address) +{ + if (m_state == STATE_BOUND || + m_state == STATE_CONNECTED) + { + m_errno = ERROR_INVAL; + return -1; + } + if (m_state == STATE_CLOSED) + { + m_errno = ERROR_BADF; + return -1; + } + Ptr dev = m_node->GetDevice (address.GetDevice ()); + m_node->RegisterProtocolHandler (MakeCallback (&PacketSocket::ForwardUp, this), + address.GetProtocol (), dev); + m_state = STATE_BOUND; + m_protocol = address.GetProtocol (); + m_device = address.GetDevice (); + return 0; +} + +enum Socket::SocketErrno +PacketSocket::GetErrno (void) const +{ + return m_errno; +} +int +PacketSocket::ShutdownSend (void) +{ + if (m_state == STATE_CLOSED) + { + m_errno = ERROR_BADF; + return -1; + } + m_shutdownSend = true; + return 0; +} +int +PacketSocket::ShutdownRecv (void) +{ + if (m_state == STATE_CLOSED) + { + m_errno = ERROR_BADF; + return -1; + } + m_shutdownRecv = false; + return 0; +} +int +PacketSocket::DoClose(ns3::Callback > closeCompleted) +{ + if (m_state == STATE_CLOSED) + { + m_errno = ERROR_BADF; + return -1; + } + if (!closeCompleted.IsNull ()) + { + closeCompleted (this); + } + m_state = STATE_CLOSED; + return 0; +} + +int +PacketSocket::DoConnect(const Address &ad, + ns3::Callback > connectionSucceeded, + ns3::Callback > connectionFailed, + ns3::Callback > halfClose) +{ + PacketSocketAddress address; + if (m_state == STATE_CLOSED) + { + m_errno = ERROR_BADF; + goto error; + } + if (m_state == STATE_OPEN) + { + // connect should happen _after_ bind. + m_errno = ERROR_INVAL; // generic error condition. + goto error; + } + if (m_state == STATE_CONNECTED) + { + m_errno = ERROR_ISCONN; + goto error; + } + if (!PacketSocketAddress::IsMatchingType (ad)) + { + m_errno = ERROR_AFNOSUPPORT; + goto error; + } + m_destAddr = ad; + m_state = STATE_CONNECTED; + if (!connectionSucceeded.IsNull ()) + { + connectionSucceeded (this); + } + return 0; + error: + if (!connectionFailed.IsNull ()) + { + connectionFailed (this); + } + return -1; +} + +int +PacketSocket::DoAccept(ns3::Callback, const Address &> connectionRequest, + ns3::Callback, const Address &> newConnectionCreated, + ns3::Callback > closeRequested) +{ + // calling accept on a packet socket is a programming error. + m_errno = ERROR_OPNOTSUPP; + return -1; +} + +int +PacketSocket::DoSend (const uint8_t* buffer, + uint32_t size, + ns3::Callback, uint32_t> dataSent) +{ + if (m_state == STATE_OPEN || + m_state == STATE_BOUND) + { + m_errno = ERROR_NOTCONN; + return -1; + } + return DoSendTo (m_destAddr, buffer, size, dataSent); +} + +int +PacketSocket::DoSendTo(const Address &address, + const uint8_t *buffer, + uint32_t size, + Callback, uint32_t> dataSent) +{ + PacketSocketAddress ad; + if (m_state == STATE_CLOSED) + { + m_errno = ERROR_BADF; + return -1; + } + if (m_state == STATE_OPEN) + { + // XXX should return another error here. + m_errno = ERROR_INVAL; + return -1; + } + if (m_shutdownSend) + { + m_errno = ERROR_SHUTDOWN; + return -1; + } + if (!PacketSocketAddress::IsMatchingType (address)) + { + m_errno = ERROR_AFNOSUPPORT; + return -1; + } + ad = PacketSocketAddress::ConvertFrom (address); + + Packet p; + if (buffer == 0) + { + p = Packet (size); + } + else + { + p = Packet (buffer, size); + } + + bool error = false; + Address dest = ad.GetPhysicalAddress (); + if (ad.GetDevice () == 0) + { + for (uint32_t i = 1; i <= m_node->GetNDevices (); i++) + { + Ptr device = m_node->GetDevice (i); + if (!device->Send (p, dest, ad.GetProtocol ())) + { + error = true; + } + } + } + else + { + Ptr device = m_node->GetDevice (ad.GetDevice ()); + if (!device->Send (p, dest, ad.GetProtocol ())) + { + error = true; + } + } + if (!error && !dataSent.IsNull ()) + { + dataSent (this, p.GetSize ()); + } + + if (error) + { + m_errno = ERROR_INVAL; + return -1; + } + else + { + return 0; + } +} + +void +PacketSocket::DoRecv(ns3::Callback, const uint8_t*, uint32_t,const Address &> callback) +{ + m_rxCallback = callback; +} + +void +PacketSocket::DoRecvDummy(ns3::Callback, uint32_t, const Address &> callback) +{ + m_dummyRxCallback = callback; +} + +void +PacketSocket::ForwardUp (Ptr device, const Packet &packet, + uint16_t protocol, const Address &from) +{ + if (m_shutdownRecv) + { + return; + } + + Packet p = packet; + + PacketSocketAddress address; + address.SetPhysicalAddress (from); + address.SetDevice (device->GetIfIndex ()); + address.SetProtocol (protocol); + + NS_DEBUG ("PacketSocket::ForwardUp: UID is " << packet.GetUid() + << " PacketSocket " << this); + if (!m_dummyRxCallback.IsNull ()) + { + m_dummyRxCallback (this, p.GetSize (), address.ConvertTo ()); + } + if (!m_rxCallback.IsNull ()) + { + m_rxCallback (this, p.PeekData (), p.GetSize (), address.ConvertTo ()); + } +} + +}//namespace ns3 diff -r 8ea0f4d4fd34 -r 34386185bc1f src/node/packet-socket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/node/packet-socket.h Wed Aug 01 09:02:03 2007 +0200 @@ -0,0 +1,132 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise, INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Emmanuelle Laprise , + * Mathieu Lacage + */ +#ifndef PACKET_SOCKET_H +#define PACKET_SOCKET_H + +#include +#include "ns3/callback.h" +#include "ns3/ptr.h" +#include "ns3/socket.h" + +namespace ns3 { + +class Node; +class Packet; +class NetDevice; +class PacketSocketAddress; + +/** + * \brief A PacketSocket is a link between an application and a net device. + * + * A PacketSocket can be used to connect an application to a net + * device. The application provides the buffers of data, the socket + * conserts them to a raw packet and the net device then adds the + * protocol specific headers and trailers. This socket type + * is very similar to the linux and BSD "packet" sockets. + * + * Here is a summary of the semantics of this class: + * - Bind: Bind uses only the protocol and device fields of the + * PacketSocketAddress. If none are provided, Bind uses + * zero for both, which means that the socket is bound + * to all protocols on all devices on the node. + * + * - Connect: uses only the protocol, device and "physical address" + * field of the PacketSocketAddress. It is used to set the default + * destination address for outgoing packets. + * + * - Send: send the input packet to the underlying NetDevices + * with the default destination address. The socket must + * be bound and connected. + * + * - SendTo: uses the protocol, device, and "physical address" + * fields of the PacketSocketAddress. The device value is + * used to specialize the packet transmission to a single + * device, the protocol value specifies the protocol of this + * packet only and the "physical address" field is used to override the + * default destination address. The socket must be bound. + * + * - Recv: The address represents the address of the packer originator. + * The fields "physical address", device, and protocol are filled. + * + * - Accept: not allowed + */ +class PacketSocket : public Socket +{ +public: + PacketSocket (Ptr node); + virtual ~PacketSocket (); + + virtual enum SocketErrno GetErrno (void) const; + virtual Ptr GetNode (void) const; + virtual int Bind (void); + virtual int Bind (const Address & address); + virtual int ShutdownSend (void); + virtual int ShutdownRecv (void); + +private: + virtual int DoClose(Callback > closeCompleted); + virtual int DoConnect(const Address & address, + Callback > connectionSucceeded, + Callback > connectionFailed, + Callback > halfClose); + virtual int DoAccept(Callback, const Address&> connectionRequest, + Callback, const Address&> newConnectionCreated, + Callback > closeRequested); + virtual int DoSend (const uint8_t* buffer, + uint32_t size, + Callback, uint32_t> dataSent); + virtual int DoSendTo(const Address &address, + const uint8_t *buffer, + uint32_t size, + Callback, uint32_t> dataSent); + virtual void DoRecv(Callback, const uint8_t*, uint32_t,const Address&> receive); + virtual void DoRecvDummy(Callback, uint32_t,const Address&>); + +private: + void Init (void); + void ForwardUp (Ptr device, const Packet &packet, + uint16_t protocol, const Address &from); + int DoBind (const PacketSocketAddress &address); + virtual void DoDispose (void); + + enum State { + STATE_OPEN, + STATE_BOUND, // open and bound + STATE_CONNECTED, // open, bound and connected + STATE_CLOSED + }; + Ptr m_node; + Callback,uint32_t,const Address &> m_dummyRxCallback; + Callback,uint8_t const*,uint32_t, const Address &> m_rxCallback; + enum SocketErrno m_errno; + bool m_shutdownSend; + bool m_shutdownRecv; + enum State m_state; + uint16_t m_protocol; + uint32_t m_device; + Address m_destAddr; /// Default destination address +}; + +}//namespace ns3 + +#endif /* PACKET_SOCKET_H */ + + diff -r 8ea0f4d4fd34 -r 34386185bc1f src/node/wscript --- a/src/node/wscript Wed Aug 01 09:01:54 2007 +0200 +++ b/src/node/wscript Wed Aug 01 09:02:03 2007 +0200 @@ -8,7 +8,9 @@ node.source = [ 'address.cc', 'eui48-address.cc', + 'eui64-address.cc', 'inet-socket-address.cc', + 'packet-socket-address.cc', 'node.cc', 'ipv4-address.cc', 'net-device.cc', @@ -23,6 +25,8 @@ 'node-list.cc', 'socket.cc', 'socket-factory.cc', + 'packet-socket-factory.cc', + 'packet-socket.cc', 'udp.cc', 'ipv4.cc', 'application.cc', @@ -32,7 +36,9 @@ headers.source = [ 'address.h', 'eui48-address.h', + 'eui64-address.h', 'inet-socket-address.h', + 'packet-socket-address.h', 'node.h', 'ipv4-address.h', 'net-device.h', @@ -47,6 +53,7 @@ 'node-list.h', 'socket.h', 'socket-factory.h', + 'packet-socket-factory.h', 'udp.h', 'ipv4.h', 'application.h',