--- 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<NetDevice> device)
+{
+ if (device == 0)
+ {
+ m_device = 0;
+ }
+ else
+ {
+ m_device = device->GetIfIndex ();
+ }
+}
+void
PacketSocketAddress::SetPhysicalAddress (const Address address)
{
m_address = address;
--- 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<NetDevice> device);
void SetPhysicalAddress (const Address address);
uint16_t GetProtocol (void) const;
--- /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 <emmanuelle.laprise@bluekazoo.ca>
+ */
+#include "packet-socket-factory.h"
+#include "node.h"
+
+namespace ns3 {
+
+const InterfaceId PacketSocketFactory::iid = MakeInterfaceId ("Packet",
+ SocketFactory::iid);
+
+PacketSocketFactory::PacketSocketFactory ()
+{
+ SetInterfaceId (PacketSocketFactory::iid);
+}
+
+Ptr<Socket> PacketSocketFactory::CreateSocket (void)
+{
+ Ptr<Node> node = QueryInterface<Node> (Node::iid);
+ Ptr<PacketSocket> socket = Create<PacketSocket> (node);
+ return socket;
+}
+} // namespace ns3
--- /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 <emmanuelle.laprise@bluekazoo.ca>
+ */
+#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<Socket> CreateSocket (void);
+};
+
+} // namespace ns3
+
+#endif /* PACKET_SOCKET_FACTORY_H */
--- /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 <emmanuelle.laprise@bluekazoo.ca>
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#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> 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<Node>
+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<NetDevice> 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<void, Ptr<Socket> > 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<void, Ptr<Socket> > connectionSucceeded,
+ ns3::Callback<void, Ptr<Socket> > connectionFailed,
+ ns3::Callback<void, Ptr<Socket> > 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<bool, Ptr<Socket>, const Address &> connectionRequest,
+ ns3::Callback<void, Ptr<Socket>, const Address &> newConnectionCreated,
+ ns3::Callback<void, Ptr<Socket> > 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<void, Ptr<Socket>, 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<void, Ptr<Socket>, 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<NetDevice> device = m_node->GetDevice (i);
+ if (!device->Send (p, dest, ad.GetProtocol ()))
+ {
+ error = true;
+ }
+ }
+ }
+ else
+ {
+ Ptr<NetDevice> 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<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address &> callback)
+{
+ m_rxCallback = callback;
+}
+
+void
+PacketSocket::DoRecvDummy(ns3::Callback<void, Ptr<Socket>, uint32_t, const Address &> callback)
+{
+ m_dummyRxCallback = callback;
+}
+
+void
+PacketSocket::ForwardUp (Ptr<NetDevice> 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
--- /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 <emmanuelle.laprise@bluekazoo.ca>,
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef PACKET_SOCKET_H
+#define PACKET_SOCKET_H
+
+#include <stdint.h>
+#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> node);
+ virtual ~PacketSocket ();
+
+ virtual enum SocketErrno GetErrno (void) const;
+ virtual Ptr<Node> 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<void, Ptr<Socket> > closeCompleted);
+ virtual int DoConnect(const Address & address,
+ Callback<void, Ptr<Socket> > connectionSucceeded,
+ Callback<void, Ptr<Socket> > connectionFailed,
+ Callback<void, Ptr<Socket> > halfClose);
+ virtual int DoAccept(Callback<bool, Ptr<Socket>, const Address&> connectionRequest,
+ Callback<void, Ptr<Socket>, const Address&> newConnectionCreated,
+ Callback<void, Ptr<Socket> > closeRequested);
+ virtual int DoSend (const uint8_t* buffer,
+ uint32_t size,
+ Callback<void, Ptr<Socket>, uint32_t> dataSent);
+ virtual int DoSendTo(const Address &address,
+ const uint8_t *buffer,
+ uint32_t size,
+ Callback<void, Ptr<Socket>, uint32_t> dataSent);
+ virtual void DoRecv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address&> receive);
+ virtual void DoRecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Address&>);
+
+private:
+ void Init (void);
+ void ForwardUp (Ptr<NetDevice> 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<Node> m_node;
+ Callback<void,Ptr<Socket>,uint32_t,const Address &> m_dummyRxCallback;
+ Callback<void,Ptr<Socket>,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 */
+
+
--- 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',