a packet socket

This commit is contained in:
Mathieu Lacage
2007-08-01 09:02:03 +02:00
parent 2687579986
commit b835a6b564
7 changed files with 584 additions and 0 deletions

View File

@@ -35,6 +35,18 @@ PacketSocketAddress::SetDevice (uint32_t index)
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;

View File

@@ -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 @@ class PacketSocketAddress
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;

View File

@@ -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

View File

@@ -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 */

332
src/node/packet-socket.cc Normal file
View File

@@ -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

132
src/node/packet-socket.h Normal file
View File

@@ -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 */

View File

@@ -8,7 +8,9 @@ def build(bld):
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 @@ def build(bld):
'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 @@ def build(bld):
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 @@ def build(bld):
'node-list.h',
'socket.h',
'socket-factory.h',
'packet-socket-factory.h',
'udp.h',
'ipv4.h',
'application.h',