rework the socket/udp layer to remove the Ipv4EndPointDemux template

This commit is contained in:
Mathieu Lacage
2007-05-02 19:14:34 +02:00
parent 2d41f0a3c1
commit 3dbf9f25e1
11 changed files with 300 additions and 339 deletions

View File

@@ -199,7 +199,6 @@ node.add_sources ([
'ipv4-interface.cc',
'ipv4.cc',
'ipv4-end-point.cc',
'udp-end-point.cc',
'udp.cc',
'capability.cc',
'arp-header.cc',
@@ -220,6 +219,7 @@ node.add_sources ([
'socket.cc',
'udp-socket.cc',
'pcap-trace.cc',
'ipv4-end-point-demux.cc',
])
node.add_headers ([
'ipv4-header.h',
@@ -266,7 +266,6 @@ node.add_inst_headers ([
'udp.h',
'ipv4-l4-protocol.h',
'ipv4-l4-demux.h',
'udp-end-point.h',
'ipv4-end-point-demux.h',
'ipv4-end-point.h',
'pcap-trace.h',

View File

@@ -0,0 +1,204 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ipv4-end-point-demux.h"
#include "ipv4-end-point.h"
namespace ns3{
Ipv4EndPointDemux::Ipv4EndPointDemux ()
: m_ephemeral (1025)
{}
Ipv4EndPointDemux::~Ipv4EndPointDemux ()
{
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
Ipv4EndPoint *endPoint = *i;
delete endPoint;
}
m_endPoints.clear ();
}
bool
Ipv4EndPointDemux::LookupPortLocal (uint16_t port)
{
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == port)
{
return true;
}
}
return false;
}
bool
Ipv4EndPointDemux::LookupLocal (Ipv4Address addr, uint16_t port)
{
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == port &&
(*i)->GetLocalAddress () == addr)
{
return true;
}
}
return false;
}
Ipv4EndPoint *
Ipv4EndPointDemux::Allocate (void)
{
uint16_t port = AllocateEphemeralPort ();
if (port == 0)
{
return 0;
}
Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port);
m_endPoints.push_back (endPoint);
return endPoint;
}
Ipv4EndPoint *
Ipv4EndPointDemux::Allocate (Ipv4Address address)
{
uint16_t port = AllocateEphemeralPort ();
if (port == 0)
{
return 0;
}
Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
m_endPoints.push_back (endPoint);
return endPoint;
}
Ipv4EndPoint *
Ipv4EndPointDemux::Allocate (uint16_t port)
{
return Allocate (Ipv4Address::GetAny (), port);
}
Ipv4EndPoint *
Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port)
{
if (LookupLocal (address, port))
{
return 0;
}
Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
m_endPoints.push_back (endPoint);
return endPoint;
}
Ipv4EndPoint *
Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4Address peerAddress, uint16_t peerPort)
{
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == localPort &&
(*i)->GetLocalAddress () == localAddress &&
(*i)->GetPeerPort () == peerPort &&
(*i)->GetPeerAddress () == peerAddress)
{
/* no way we can allocate this end-point. */
return 0;
}
}
Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
endPoint->SetPeer (peerAddress, peerPort);
m_endPoints.push_back (endPoint);
return endPoint;
}
/*
* If we have an exact match, we return it.
* Otherwise, if we find a generic match, we return it.
* Otherwise, we return 0.
*/
Ipv4EndPoint *
Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport,
Ipv4Address saddr, uint16_t sport)
{
uint32_t genericity = 3;
Ipv4EndPoint *generic = 0;
//TRACE ("lookup " << daddr << ":" << dport << " " << saddr << ":" << sport);
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
#if 0
TRACE ("against " <<
(*i)->GetLocalAddress ()
<< ":" <<
(*i)->GetLocalPort ()
<< " " <<
(*i)->GetPeerAddress ()
<< ":"
<< (*i)->GetPeerPort ());
#endif
if ((*i)->GetLocalPort () != dport)
{
continue;
}
if ((*i)->GetLocalAddress () == daddr &&
(*i)->GetPeerPort () == sport &&
(*i)->GetPeerAddress () == saddr)
{
/* this is an exact match. */
return *i;
}
uint32_t tmp = 0;
if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ())
{
tmp ++;
}
if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ())
{
tmp ++;
}
if (tmp < genericity)
{
generic = (*i);
genericity = tmp;
}
}
return generic;
}
uint16_t
Ipv4EndPointDemux::AllocateEphemeralPort (void)
{
uint16_t port = m_ephemeral;
do
{
port++;
if (port > 5000)
{
port = 1024;
}
if (!LookupPortLocal (port))
{
return port;
}
} while (port != m_ephemeral);
return 0;
}
} //namespace ns3

View File

@@ -30,7 +30,6 @@ namespace ns3 {
class Ipv4EndPoint;
template <typename T>
class Ipv4EndPointDemux {
public:
Ipv4EndPointDemux ();
@@ -38,216 +37,29 @@ public:
bool LookupPortLocal (uint16_t port);
bool LookupLocal (Ipv4Address addr, uint16_t port);
T *Lookup (Ipv4Address daddr,
uint16_t dport,
Ipv4Address saddr,
uint16_t sport);
Ipv4EndPoint *Lookup (Ipv4Address daddr,
uint16_t dport,
Ipv4Address saddr,
uint16_t sport);
T *Allocate (void);
T *Allocate (Ipv4Address address);
T *Allocate (uint16_t port);
T *Allocate (Ipv4Address address, uint16_t port);
T *Allocate (Ipv4Address localAddress,
uint16_t localPort,
Ipv4Address peerAddress,
uint16_t peerPort);
Ipv4EndPoint *Allocate (void);
Ipv4EndPoint *Allocate (Ipv4Address address);
Ipv4EndPoint *Allocate (uint16_t port);
Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
Ipv4EndPoint *Allocate (Ipv4Address localAddress,
uint16_t localPort,
Ipv4Address peerAddress,
uint16_t peerPort);
private:
uint16_t AllocateEphemeralPort (void);
typedef std::list<T *> EndPoints;
typedef typename std::list<T *>::iterator EndPointsI;
typedef std::list<Ipv4EndPoint *> EndPoints;
typedef std::list<Ipv4EndPoint *>::iterator EndPointsI;
uint16_t m_ephemeral;
EndPoints m_endPoints;
};
}; // namespace ns3
namespace ns3{
template <typename T>
Ipv4EndPointDemux<T>::Ipv4EndPointDemux ()
: m_ephemeral (1025)
{}
template <typename T>
Ipv4EndPointDemux<T>::~Ipv4EndPointDemux ()
{}
template <typename T>
bool
Ipv4EndPointDemux<T>::LookupPortLocal (uint16_t port)
{
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == port)
{
return true;
}
}
return false;
}
template <typename T>
bool
Ipv4EndPointDemux<T>::LookupLocal (Ipv4Address addr, uint16_t port)
{
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == port &&
(*i)->GetLocalAddress () == addr)
{
return true;
}
}
return false;
}
template <typename T>
T *
Ipv4EndPointDemux<T>::Allocate (void)
{
uint16_t port = AllocateEphemeralPort ();
if (port == 0)
{
return 0;
}
T *endPoint = new T (Ipv4Address::GetAny (), port);
m_endPoints.push_back (endPoint);
return endPoint;
}
template <typename T>
T *
Ipv4EndPointDemux<T>::Allocate (Ipv4Address address)
{
uint16_t port = AllocateEphemeralPort ();
if (port == 0)
{
return 0;
}
T *endPoint = new T (address, port);
m_endPoints.push_back (endPoint);
return endPoint;
}
template <typename T>
T *
Ipv4EndPointDemux<T>::Allocate (uint16_t port)
{
return Allocate (Ipv4Address::GetAny (), port);
}
template <typename T>
T *
Ipv4EndPointDemux<T>::Allocate (Ipv4Address address, uint16_t port)
{
if (LookupLocal (address, port))
{
return 0;
}
T *endPoint = new T (address, port);
m_endPoints.push_back (endPoint);
return endPoint;
}
template <typename T>
T *
Ipv4EndPointDemux<T>::Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4Address peerAddress, uint16_t peerPort)
{
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == localPort &&
(*i)->GetLocalAddress () == localAddress &&
(*i)->GetPeerPort () == peerPort &&
(*i)->GetPeerAddress () == peerAddress)
{
/* no way we can allocate this end-point. */
return 0;
}
}
T *endPoint = new T (localAddress, localPort);
endPoint->SetPeer (peerAddress, peerPort);
m_endPoints.push_back (endPoint);
return endPoint;
}
/*
* If we have an exact match, we return it.
* Otherwise, if we find a generic match, we return it.
* Otherwise, we return 0.
*/
template <typename T>
T *
Ipv4EndPointDemux<T>::Lookup (Ipv4Address daddr, uint16_t dport,
Ipv4Address saddr, uint16_t sport)
{
uint32_t genericity = 3;
T *generic = 0;
//TRACE ("lookup " << daddr << ":" << dport << " " << saddr << ":" << sport);
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
#if 0
TRACE ("against " <<
(*i)->GetLocalAddress ()
<< ":" <<
(*i)->GetLocalPort ()
<< " " <<
(*i)->GetPeerAddress ()
<< ":"
<< (*i)->GetPeerPort ());
#endif
if ((*i)->GetLocalPort () != dport)
{
continue;
}
if ((*i)->GetLocalAddress () == daddr &&
(*i)->GetPeerPort () == sport &&
(*i)->GetPeerAddress () == saddr)
{
/* this is an exact match. */
return *i;
}
uint32_t tmp = 0;
if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ())
{
tmp ++;
}
if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ())
{
tmp ++;
}
if (tmp < genericity)
{
generic = (*i);
genericity = tmp;
}
}
return generic;
}
template <typename T>
uint16_t
Ipv4EndPointDemux<T>::AllocateEphemeralPort (void)
{
uint16_t port = m_ephemeral;
do
{
port++;
if (port > 5000)
{
port = 1024;
}
if (!LookupPortLocal (port))
{
return port;
}
} while (port != m_ephemeral);
return 0;
}
}//namespace ns3
} // namespace ns3
#endif /* IPV4_END_POINTS_H */

View File

@@ -30,7 +30,12 @@ Ipv4EndPoint::Ipv4EndPoint (Ipv4Address address, uint16_t port)
m_peerPort (0)
{}
Ipv4EndPoint::~Ipv4EndPoint ()
{}
{
if (!m_destroyCallback.IsNull ())
{
m_destroyCallback ();
}
}
Ipv4Address
Ipv4EndPoint::GetLocalAddress (void)
@@ -59,5 +64,27 @@ Ipv4EndPoint::SetPeer (Ipv4Address address, uint16_t port)
m_peerPort = port;
}
void
Ipv4EndPoint::SetRxCallback (Callback<void,const Packet &, Ipv4Address, uint16_t> callback)
{
m_rxCallback = callback;
}
void
Ipv4EndPoint::SetDestroyCallback (Callback<void> callback)
{
m_destroyCallback = callback;
}
void
Ipv4EndPoint::ForwardUp (const Packet &p, Ipv4Address saddr, uint16_t sport)
{
if (!m_rxCallback.IsNull ())
{
m_rxCallback (p, saddr, sport);
}
}
}; // namespace ns3

View File

@@ -24,10 +24,12 @@
#include <stdint.h>
#include "ipv4-address.h"
#include "ns3/callback.h"
namespace ns3 {
class Header;
class Packet;
class Ipv4EndPoint {
public:
@@ -41,11 +43,18 @@ public:
void SetPeer (Ipv4Address address, uint16_t port);
void SetRxCallback (Callback<void,const Packet &, Ipv4Address, uint16_t> callback);
void SetDestroyCallback (Callback<void> callback);
void ForwardUp (const Packet &p, Ipv4Address saddr, uint16_t sport);
private:
Ipv4Address m_localAddr;
uint16_t m_localPort;
Ipv4Address m_peerAddr;
uint16_t m_peerPort;
Callback<void,const Packet &, Ipv4Address, uint16_t> m_rxCallback;
Callback<void> m_destroyCallback;
};
}; // namespace ns3

View File

@@ -1,41 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "udp-end-point.h"
namespace ns3 {
UdpEndPoint::UdpEndPoint (Ipv4Address address, uint16_t port)
: Ipv4EndPoint (address, port),
m_socket (0)
{}
void
UdpEndPoint::SetSocket (UdpSocket *socket)
{
m_socket = socket;
}
UdpSocket *
UdpEndPoint::GetSocket (void) const
{
return m_socket;
}
}//namespace ns3

View File

@@ -1,45 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005 INRIA
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef UDP_END_POINT_H
#define UDP_END_POINT_H
#include <stdint.h>
#include "ipv4-end-point.h"
#include "ipv4-address.h"
namespace ns3 {
class UdpSocket;
class UdpEndPoint : public Ipv4EndPoint
{
public:
UdpEndPoint (Ipv4Address address, uint16_t port);
void SetSocket (UdpSocket *socket);
UdpSocket *GetSocket (void) const;
private:
UdpSocket *m_socket;
};
}//namespace ns3
#endif /* UDP_END_POINT_H */

View File

@@ -20,7 +20,7 @@
*/
#include "udp-socket.h"
#include "udp.h"
#include "udp-end-point.h"
#include "ipv4-end-point.h"
#include "node.h"
#include "ipv4-l4-demux.h"
@@ -39,7 +39,6 @@ UdpSocket::UdpSocket (Node *node)
}
UdpSocket::~UdpSocket ()
{
delete m_endPoint;
m_node->Unref ();
m_node = 0;
}
@@ -50,49 +49,46 @@ UdpSocket::PeekNode (void) const
return m_node;
}
int
UdpSocket::Bind (void)
void
UdpSocket::DestroyEndPoint (void)
{
m_endPoint = GetUdp ()->Allocate ();
m_endPoint = 0;
}
int
UdpSocket::FinishBind (void)
{
m_endPoint->SetRxCallback (MakeCallback (&UdpSocket::ForwardUp, this));
m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocket::DestroyEndPoint, this));
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
int
UdpSocket::Bind (void)
{
m_endPoint = GetUdp ()->Allocate ();
return FinishBind ();
}
int
UdpSocket::Bind (Ipv4Address address)
{
m_endPoint = GetUdp ()->Allocate (address);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
return FinishBind ();
}
int
UdpSocket::Bind (uint16_t port)
{
m_endPoint = GetUdp ()->Allocate (port);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
return FinishBind ();
}
int
UdpSocket::Bind (Ipv4Address address, uint16_t port)
{
m_endPoint = GetUdp ()->Allocate (address, port);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
return FinishBind ();
}
enum Socket::SocketErrno
@@ -228,12 +224,13 @@ UdpSocket::DoRecvDummy(ns3::Callback<void, Socket*, uint32_t,const Ipv4Address&,
}
void
UdpSocket::ForwardUp (Packet &p, Ipv4Address saddr, uint16_t sport)
UdpSocket::ForwardUp (const Packet &packet, Ipv4Address saddr, uint16_t sport)
{
if (m_shutdownRecv)
{
return;
}
Packet p = packet;
if (!m_dummyRxCallback.IsNull ())
{
m_dummyRxCallback (this, p.GetSize (), saddr, sport);

View File

@@ -27,7 +27,7 @@
namespace ns3 {
class UdpEndPoint;
class Ipv4EndPoint;
class Node;
class Packet;
class Udp;
@@ -74,12 +74,14 @@ private:
private:
friend class Udp;
// invoked by Udp class
void ForwardUp (Packet &p, Ipv4Address saddr, uint16_t sport);
int FinishBind (void);
void ForwardUp (const Packet &p, Ipv4Address saddr, uint16_t sport);
void DestroyEndPoint (void);
Udp *GetUdp (void) const;
int DoSendPacketTo (const Packet &p, Ipv4Address daddr, uint16_t dport,
ns3::Callback<void, Socket*, uint32_t> dataSent);
UdpEndPoint *m_endPoint;
Ipv4EndPoint *m_endPoint;
Node *m_node;
Ipv4Address m_defaultAddress;
uint16_t m_defaultPort;

View File

@@ -26,7 +26,7 @@
#include "udp.h"
#include "udp-header.h"
#include "ipv4-end-point-demux.h"
#include "udp-end-point.h"
#include "ipv4-end-point.h"
#include "node.h"
#include "ipv4.h"
#include "l3-demux.h"
@@ -40,7 +40,7 @@ const uint8_t Udp::PROT_NUMBER = 17;
Udp::Udp (Node *node)
: Ipv4L4Protocol (PROT_NUMBER, 2),
m_node (node),
m_endPoints (new Ipv4EndPointDemux<UdpEndPoint> ())
m_endPoints (new Ipv4EndPointDemux ())
{
m_node->Ref ();
}
@@ -64,27 +64,27 @@ Udp::CreateSocket (void)
return new UdpSocket (m_node);
}
UdpEndPoint *
Ipv4EndPoint *
Udp::Allocate (void)
{
return m_endPoints->Allocate ();
}
UdpEndPoint *
Ipv4EndPoint *
Udp::Allocate (Ipv4Address address)
{
return m_endPoints->Allocate (address);
}
UdpEndPoint *
Ipv4EndPoint *
Udp::Allocate (uint16_t port)
{
return m_endPoints->Allocate (port);
}
UdpEndPoint *
Ipv4EndPoint *
Udp::Allocate (Ipv4Address address, uint16_t port)
{
return m_endPoints->Allocate (address, port);
}
UdpEndPoint *
Ipv4EndPoint *
Udp::Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4Address peerAddress, uint16_t peerPort)
{
@@ -105,15 +105,13 @@ Udp::Receive(Packet& packet,
{
UdpHeader udpHeader;
packet.RemoveHeader (udpHeader);
UdpEndPoint *endPoint = m_endPoints->Lookup (destination, udpHeader.GetDestination (),
source, udpHeader.GetSource ());
Ipv4EndPoint *endPoint = m_endPoints->Lookup (destination, udpHeader.GetDestination (),
source, udpHeader.GetSource ());
if (endPoint == 0)
{
return;
}
UdpSocket *socket = endPoint->GetSocket ();
socket->ForwardUp (packet, source, udpHeader.GetSource ());
NS_ASSERT (socket != 0);
endPoint->ForwardUp (packet, source, udpHeader.GetSource ());
}
void

View File

@@ -27,7 +27,6 @@
#include "ns3/packet.h"
#include "ipv4-address.h"
#include "ipv4-end-point-demux.h"
#include "udp-end-point.h"
#include "ipv4-l4-protocol.h"
namespace ns3 {
@@ -48,11 +47,11 @@ public:
Socket *CreateSocket (void);
UdpEndPoint *Allocate (void);
UdpEndPoint *Allocate (Ipv4Address address);
UdpEndPoint *Allocate (uint16_t port);
UdpEndPoint *Allocate (Ipv4Address address, uint16_t port);
UdpEndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4EndPoint *Allocate (void);
Ipv4EndPoint *Allocate (Ipv4Address address);
Ipv4EndPoint *Allocate (uint16_t port);
Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4Address peerAddress, uint16_t peerPort);
// called by UdpSocket.
@@ -66,7 +65,7 @@ public:
Ipv4Address const &destination);
private:
Node *m_node;
Ipv4EndPointDemux<UdpEndPoint> *m_endPoints;
Ipv4EndPointDemux *m_endPoints;
};
}; // namespace ns3