remove DatagramSocket, use Socket base class for UdpSocket subclass.

This commit is contained in:
Mathieu Lacage
2007-04-30 16:23:10 +02:00
parent f3febd91ac
commit 399ba068e1
16 changed files with 709 additions and 548 deletions

View File

@@ -200,7 +200,6 @@ node.add_sources ([
'ipv4.cc',
'ipv4-end-point.cc',
'udp-end-point.cc',
'datagram-socket.cc',
'udp.cc',
'capability.cc',
'arp-header.cc',
@@ -218,13 +217,13 @@ node.add_sources ([
'channel.cc',
'node-list.cc',
'ascii-trace.cc',
'socket.cc',
'udp-socket.cc',
])
node.add_headers ([
'ipv4-header.h',
'udp-header.h',
'ipv4-checksum.h',
'udp.h',
'ipv4-l4-protocol.h',
'application.h',
'application-list.h',
'onoff-application.h',
@@ -233,16 +232,15 @@ node.add_headers ([
'arp.h',
'ipv4-loopback-interface.h',
'l3-demux.h',
'ipv4-l4-demux.h',
'header-utils.h',
'protocol.h',
'queue.h',
'arp-ipv4-interface.h',
'udp-socket.h',
])
node.add_inst_headers ([
'node.h',
'internet-node.h',
'datagram-socket.h',
'ipv4-address.h',
'net-device.h',
'ipv4-interface.h',
@@ -263,6 +261,13 @@ node.add_inst_headers ([
'application-list.h',
'onoff-application.h',
'ascii-trace.h',
'socket.h',
'udp.h',
'ipv4-l4-protocol.h',
'ipv4-l4-demux.h',
'udp-end-point.h',
'ipv4-end-point-demux.h',
'ipv4-end-point.h',
])
p2p = build.Ns3Module ('p2p', 'src/devices/p2p')

View File

@@ -55,7 +55,8 @@
#include "ns3/mac-address.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv4.h"
#include "ns3/datagram-socket.h"
#include "ns3/udp.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/drop-tail.h"
#include "ns3/node-list.h"

View File

@@ -27,8 +27,9 @@
#include "ns3/p2p-net-device.h"
#include "ns3/drop-tail.h"
#include "ns3/ipv4.h"
#include "ns3/udp.h"
#include "ns3/trace-context.h"
#include "ns3/datagram-socket.h"
#include "ns3/socket.h"
#include "ns3/simulator.h"
#include "ns3/node-list.h"
#include "ns3/trace-root.h"
@@ -77,12 +78,12 @@ protected:
};
static void
GenerateTraffic (DatagramSocket *socket, uint32_t size)
GenerateTraffic (Socket *socket, uint32_t size)
{
std::cout << "Node: " << socket->GetNode()->GetId ()
<< " at=" << Simulator::Now ().GetSeconds () << "s,"
<< " tx bytes=" << size << std::endl;
socket->SendDummy (size);
socket->Send (0, size);
if (size > 50)
{
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
@@ -90,7 +91,7 @@ GenerateTraffic (DatagramSocket *socket, uint32_t size)
}
static void
DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
SocketPrinter (Socket *socket, uint32_t size, const Ipv4Address &from, uint16_t fromPort)
{
std::cout << "Node: " << socket->GetNode()->GetId ()
<< " at=" << Simulator::Now ().GetSeconds () << "s,"
@@ -98,9 +99,9 @@ DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from,
}
static void
PrintTraffic (DatagramSocket *socket)
PrintTraffic (Socket *socket)
{
socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
socket->RecvDummy (MakeCallback (&SocketPrinter));
}
@@ -200,10 +201,10 @@ int main (int argc, char *argv[])
ipb->SetDefaultRoute (Ipv4Address ("10.1.1.1"), 1);
DatagramSocket *source = new DatagramSocket (&a);
DatagramSocket *sink = new DatagramSocket(&b);
Socket *source = a.GetUdp ()->CreateSocket ();
Socket *sink = b.GetUdp ()->CreateSocket ();
sink->Bind (80);
source->SetDefaultDestination (Ipv4Address ("10.1.1.2"), 80);
source->Connect (Ipv4Address ("10.1.1.2"), 80);
Logger logger("p2p-net-test.log");

View File

@@ -2,7 +2,8 @@
#include "ns3/internet-node.h"
#include "ns3/simulator.h"
#include "ns3/datagram-socket.h"
#include "ns3/udp.h"
#include "ns3/socket.h"
#include "ns3/nstime.h"
using namespace ns3;
@@ -31,10 +32,10 @@ SmallTests (void)
}
static void
GenerateTraffic (DatagramSocket *socket, uint32_t size)
GenerateTraffic (Socket *socket, uint32_t size)
{
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, tx bytes=" << size << std::endl;
socket->SendDummy (size);
socket->Send (0, size);
if (size > 0)
{
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
@@ -42,15 +43,15 @@ GenerateTraffic (DatagramSocket *socket, uint32_t size)
}
static void
DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
SocketPrinter (Socket *socket, uint32_t size, const Ipv4Address &from, uint16_t fromPort)
{
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << size << std::endl;
}
static void
PrintTraffic (DatagramSocket *socket)
PrintTraffic (Socket *socket)
{
socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
socket->RecvDummy (MakeCallback (&SocketPrinter));
}
int main (int argc, char *argv[])
@@ -58,12 +59,12 @@ int main (int argc, char *argv[])
SmallTests ();
InternetNode *a = new InternetNode ();
DatagramSocket *sink = new DatagramSocket (a);
Socket *sink = a->GetUdp ()->CreateSocket ();
sink->Bind (80);
DatagramSocket *source = new DatagramSocket (a);
source->SetDefaultDestination (Ipv4Address::GetLoopback (), 80);
Socket *source = a->GetUdp ()->CreateSocket ();
source->Connect (Ipv4Address::GetLoopback (), 80);
GenerateTraffic (source, 500);
PrintTraffic (sink);

View File

@@ -1,173 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 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 "datagram-socket.h"
#include "udp.h"
#include "udp-end-point.h"
#include "node.h"
#include "ipv4-l4-demux.h"
namespace ns3 {
DatagramSocket::DatagramSocket (Node *node)
: m_endPoint (0),
m_node (node)
{
NS_ASSERT (GetUdp () != 0);
}
DatagramSocket::~DatagramSocket ()
{
delete m_endPoint;
}
int
DatagramSocket::Bind (void)
{
m_endPoint = GetUdp ()->Allocate ();
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
int
DatagramSocket::Bind (Ipv4Address address)
{
m_endPoint = GetUdp ()->Allocate (address);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
int
DatagramSocket::Bind (uint16_t port)
{
m_endPoint = GetUdp ()->Allocate (port);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
int
DatagramSocket::Bind (Ipv4Address address, uint16_t port)
{
m_endPoint = GetUdp ()->Allocate (address, port);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
void
DatagramSocket::SetDefaultDestination (Ipv4Address daddr, uint16_t dport)
{
m_defaultAddress = daddr;
m_defaultPort = dport;
}
void
DatagramSocket::SendDummy (uint32_t size)
{
SendDummyTo (size, m_defaultAddress, m_defaultPort);
}
void
DatagramSocket::SendDummyTo (uint32_t size, Ipv4Address daddr, uint16_t dport)
{
if (m_endPoint == 0)
{
Bind ();
if (m_endPoint == 0)
{
return;
}
}
Packet p = Packet (size);
GetUdp ()->Send (p, m_endPoint->GetLocalAddress (), daddr,
m_endPoint->GetLocalPort (), dport);
}
void
DatagramSocket::Send (uint8_t const*buffer, uint32_t size)
{
SendTo (buffer, size, m_defaultAddress, m_defaultPort);
}
void
DatagramSocket::SendTo (uint8_t const*buffer, uint32_t size,
Ipv4Address daddr, uint16_t dport)
{
if (m_endPoint == 0)
{
Bind ();
if (m_endPoint == 0)
{
return;
}
}
Packet p = Packet (buffer, size);
GetUdp ()->Send (p, m_endPoint->GetLocalAddress (), daddr,
m_endPoint->GetLocalPort (), dport);
}
void
DatagramSocket::SetDummyRxCallback (Callback<void,DatagramSocket*,
uint32_t,
Ipv4Address,uint16_t> cb)
{
m_dummyRxCallback = cb;
}
void
DatagramSocket::SetRxCallback (Callback<void,DatagramSocket*,
uint8_t const*,uint32_t,
Ipv4Address,uint16_t> cb)
{
m_rxCallback = cb;
}
void
DatagramSocket::ForwardUp (Packet &p, Ipv4Address saddr, uint16_t sport)
{
if (!m_dummyRxCallback.IsNull ())
{
m_dummyRxCallback (this, p.GetSize (), saddr, sport);
}
if (!m_rxCallback.IsNull ())
{
m_rxCallback (this, p.PeekData (), p.GetSize (), saddr, sport);
}
}
Udp *
DatagramSocket::GetUdp (void) const
{
return m_node->GetUdp ();
}
Node *
DatagramSocket::GetNode (void) const
{
return m_node;
}
}//namespace ns3

View File

@@ -1,169 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 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_SOCKET_H
#define UDP_SOCKET_H
#include <stdint.h>
#include "ns3/callback.h"
#include "ipv4-address.h"
namespace ns3 {
class UdpEndPoint;
class Node;
class Packet;
class Udp;
/**
* Before any data is sent, the socket must be bound with
* one of the Bind methods.
* If none of these Bind methods are called prior to
* one of the ::Send methods, the socket is implicitely
* bound to a random port and to all interfaces.
*/
class DatagramSocket
{
public:
/**
* Create an unbound udp socket.
*/
DatagramSocket (Node *node);
~DatagramSocket ();
/**
* Allocate a free port number and
* bind this socket to this port number on all
* interfaces of this system.
*
* \returns 0 on success, -1 on failure.
*/
int Bind (void);
/**
* Allocate a free port number and
* bind this socket to this port number on the
* specified interface.
*
* \param address address of interface to bind to.
* \returns 0 on success, -1 on failure.
*/
int Bind (Ipv4Address address);
/**
* Bind this socket to this port number
* on all interfaces of this system.
*
* \param port port to bind to on all interfaces
* \returns 0 on success, -1 on failure.
*/
int Bind (uint16_t port);
/**
* Bind this socket to this port number
* on the interface specified by address.
*
* \param address address of interface to bind to.
* \param port port to bind to on specified interface
* \returns 0 on success, -1 on failure.
*/
int Bind (Ipv4Address address, uint16_t port);
/**
* \param daddr destination address
* \param dport destination port
*
* Set the default destination address and port
* number for all packets outgoing from this socket.
*/
void SetDefaultDestination (Ipv4Address daddr, uint16_t dport);
/**
* \param size size of dummy data to send.
*
* Send dummy data to default destination
*/
void SendDummy (uint32_t size);
/**
* \param size size of dummy data to send
* \param daddr destination address of dummy data
* \param dport destination port of dummy data
*
* Send dummy data to specified destination, ignore any default
* destination specified with DatagramSocket::SetDefaultDestination
*/
void SendDummyTo (uint32_t size, Ipv4Address daddr, uint16_t dport);
/**
* \param buffer data buffer to send
* \param size size of data buffer to send
*/
void Send (uint8_t const*buffer, uint32_t size);
/**
* \param buffer data buffer to send
* \param size size of data buffer to send
* \param daddr destination address
* \param dport destination port
*
* Send data to specified destination, ignore any default
* destination specified with DatagramSocket::SetDefaultDestination
*/
void SendTo (uint8_t const*buffer, uint32_t size,
Ipv4Address daddr, uint16_t dport);
/**
* \param cb callback to invoke
*
* When a packet is received by this socket, it invokes the "dummy callback" which
* forwards to the application the number of bytes received and from who they
* were received.
*/
void SetDummyRxCallback (Callback<void,DatagramSocket*,uint32_t,Ipv4Address,uint16_t> cb);
/**
* \param cb callback to invoke
*
* When a packet is received by this socket, it invokes the "normal callback" which
* forwards to the application the buffer of bytes received and from who they
* were received. The application is responsible for copying that buffer if it wants
* to keep track of it.
*/
void SetRxCallback (Callback<void,DatagramSocket*,uint8_t const*,uint32_t,Ipv4Address,uint16_t> cb);
/**
* \returns pointer to node
*/
Node* GetNode(void) const;
private:
friend class Udp;
// invoked by Udp class
void ForwardUp (Packet &p, Ipv4Address saddr, uint16_t sport);
Udp *GetUdp (void) const;
UdpEndPoint *m_endPoint;
Node *m_node;
Ipv4Address m_defaultAddress;
uint16_t m_defaultPort;
Callback<void,DatagramSocket*,uint32_t,Ipv4Address,uint16_t> m_dummyRxCallback;
Callback<void,DatagramSocket*,uint8_t const*,uint32_t,Ipv4Address,uint16_t> m_rxCallback;
};
}//namespace ns3
#endif /* UDP_SOCKET_H */

View File

@@ -29,8 +29,9 @@
#include "ns3/data-rate.h"
#include "onoff-application.h"
#include "ns3/random-variable.h"
#include "datagram-socket.h"
#include "socket.h"
#include "ns3/simulator.h"
#include "udp.h"
using namespace std;
@@ -157,8 +158,8 @@ void OnOffApplication::StartApplication() // Called at time specified by Star
MakeCallback(&OnOffApplication::ConnectionFailed,
this));
#endif
m_socket = new DatagramSocket (GetNode());
m_socket->SetDefaultDestination(m_peerIP, m_peerPort);
m_socket = GetNode ()->GetUdp ()->CreateSocket ();
m_socket->Connect (m_peerIP, m_peerPort);
}
StopApplication(); // Insure no pending event
// If we are not yet connected, there is nothing to do here
@@ -238,7 +239,7 @@ void OnOffApplication::ScheduleStopEvent()
void OnOffApplication::SendPacket()
{
m_sendScheduled = false;
m_socket->SendDummy(m_pktSize);
m_socket->Send(0, m_pktSize);
#ifdef NOTYET
m_socket->Send(0, m_pktSize); // Send the packet
#endif
@@ -248,13 +249,13 @@ void OnOffApplication::SendPacket()
ScheduleNextTx();
}
void OnOffApplication::ConnectionSucceeded(DatagramSocket*)
void OnOffApplication::ConnectionSucceeded(Socket*)
{
m_connected = true;
ScheduleStartEvent();
}
void OnOffApplication::ConnectionFailed(DatagramSocket*)
void OnOffApplication::ConnectionFailed(Socket*)
{
cout << "OnOffApplication, Connection Failed" << endl;
}

View File

@@ -36,7 +36,7 @@ namespace ns3 {
class Ipv4Address;
class RandomVariable;
class DatagramSocket;
class Socket;
class DataRate;
class OnOffApplication : public Application {
@@ -69,7 +69,7 @@ public: // Static methods
static void DefaultSize(uint32_t s) { g_defaultSize = s;}
public:
DatagramSocket* m_socket; // Associated socket
Socket * m_socket; // Associated socket
Ipv4Address m_peerIP; // Peer IP address
uint16_t m_peerPort; // Peer port
bool m_connected; // True if connected
@@ -95,9 +95,9 @@ private:
void ScheduleNextTx();
void ScheduleStartEvent();
void ScheduleStopEvent();
void ConnectionSucceeded(DatagramSocket*);
void ConnectionFailed(DatagramSocket*);
void Ignore(DatagramSocket*);
void ConnectionSucceeded(Socket*);
void ConnectionFailed(Socket*);
void Ignore(Socket*);
protected:
};

81
src/node/socket.cc Normal file
View File

@@ -0,0 +1,81 @@
#include "socket.h"
namespace ns3 {
Socket::~Socket ()
{}
void
Socket::Close(Callback<void, Socket*> closeCompleted)
{
DoClose (closeCompleted);
}
void
Socket::Connect(const Ipv4Address & address,
uint16_t portNumber,
Callback<void, Socket*> connectionSucceeded,
Callback<void, Socket*> connectionFailed,
Callback<void, Socket*> halfClose)
{
DoConnect (address, portNumber, connectionSucceeded, connectionFailed, halfClose);
}
int
Socket::Accept(Callback<bool, Socket*, const Ipv4Address&, uint16_t> connectionRequest,
Callback<void, Socket*, const Ipv4Address&, uint16_t> newConnectionCreated,
Callback<void, Socket*> closeRequested)
{
return DoAccept (connectionRequest, newConnectionCreated, closeRequested);
}
int
Socket::Send (const uint8_t* buffer,
uint32_t size,
Callback<void, Socket*, uint32_t> dataSent)
{
return DoSend (buffer, size, dataSent);
}
int
Socket::SendTo(const Ipv4Address &address,
uint16_t port,
const uint8_t *buffer,
uint32_t size,
Callback<void, Socket*, uint32_t> dataSent)
{
return DoSendTo (address, port, buffer, size, dataSent);
}
void
Socket::Recv(Callback<void, Socket*, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> callback)
{
DoRecv (callback);
}
void
Socket::RecvDummy(Callback<void, Socket*, uint32_t,const Ipv4Address&, uint16_t> callback)
{
DoRecvDummy (callback);
}
bool
Socket::RefuseAllConnections (Socket* socket, const Ipv4Address& address, uint16_t port)
{
return false;
}
void
Socket::DummyCallbackVoidSocket (Socket *socket)
{}
void
Socket::DummyCallbackVoidSocketUi32 (Socket *socket, uint32_t)
{}
void
Socket::DummyCallbackVoidSocketUi32Ipv4AddressUi16 (Socket *socket, uint32_t, const Ipv4Address &, uint16_t)
{}
void
Socket::DummyCallbackVoidSocketBufferUi32Ipv4AddressUi16 (Socket *socket, const uint8_t *, uint32_t,
const Ipv4Address &, uint16_t)
{}
void
Socket::DummyCallbackVoidSocketIpv4AddressUi16 (Socket *socket, const Ipv4Address &, uint16_t)
{}
}//namespace ns3

View File

@@ -18,187 +18,244 @@
// Author: George F. Riley<riley@ece.gatech.edu>
//
// Define the Sockets API for ns3.
// George F. Riley, Georgia Tech, Fall 2006
// The Socket class defines an API based on the well-known
// BSD sockets. However, in a simulation environment, it is difficult
// to implement the semantics "blocking" calls, such as recv.
// The ns3 API will always return immediately from the blocking calls,
// with an upcall at a later time when the call would unblock.
// All blocking calls have a parameters with callbacks
// to the desired upcall. However, the design supports the upcall
// even if the owner of the socket has not posted the corresponding
// blocking call, which eases implementation slightly.
//
// The ns3 class "Process"is anticipated to be a common way to create
// and manipulate sockets, so a set of member functions are provided
// in class Process to give a syntactically easy way to access the
// sockets with default upcall virtual functions for each of the
// defined blocking calls. See the definition and implementation
// Process in process.h for details.
//
// As designed, the Socket class is a virtual base class, which defines
// the services that each layer 4 protocol must provide.
#ifndef __SOCKET_H__
#define __SOCKET_H__
#include "ns3/callback.h"
#include "protocol.h"
#include "ipv4-address.h"
#include <stdint.h>
namespace ns3{
namespace ns3 {
class IPAddr;
class L4Protocol;
class Process;
class Node;
// \brief Define the BSD Sockets API
/**
* \brief Define a Socket API based on the BSD Socket API.
*
* Contrary to the original BSD socket API, this API is asynchronous:
* it does not contain blocking calls. This API also does not use
* the dreaded BSD sockaddr_t type. Other than that, it tries to stick
* to the BSD API to make it easier those who know the BSD API to use
* this API.
*/
class Socket {
public:
Socket(); // Constructor
virtual ~Socket() {}
private:
// These static methods are default, do-nothing callbacks. They are
// provided as default arguments to the various socket calls, so callers who
// are not interested in a particular callback can ignore the
// parameters. Since these are used as formal parameters to MakeCallbac,
// each must have a unique name (they can't be disambiguated by argument
// list). The naming convention is a single letter indicating the
// return type (V = void for example) and a single letter for each
// argument type (S = Socket for exampls).
static void CBIgnoreVS(Socket*) {}
static void CBIgnoreVSIP(Socket*, const IPAddr&, PortId_t) {}
static void CBIgnoreVSU(Socket*, uint32_t) {}
static void CBIgnoreVSCU(Socket*, char*, uint32_t) {}
static bool CBIgnoreBSIP(Socket*, const IPAddr&, PortId_t){ return true;}
static void CBIgnoreVSCUIP(Socket*, char*, uint32_t, const IPAddr&, PortId_t);
virtual ~Socket();
enum SocketErrno {
ENOTERROR,
EISCONN,
ENOTCONN,
EMSGSIZE,
EAGAIN,
ESHUTDOWN,
EOPNOTSUPP,
SOCKET_ERRNO_LAST
};
/**
* \return the errno associated to the last call which failed in this
* socket. Each socket's errno is initialized to zero
* when the socket is created.
*/
virtual enum Socket::SocketErrno GetErrno (void) const = 0;
/**
* \returns the node this socket is associated with.
*/
virtual Node *GetNode (void) const = 0;
/**
* Allocate a free port number and
* bind this socket to this port number on all
* interfaces of this system.
*
* \returns 0 on success, -1 on failure.
*/
virtual int Bind (void) = 0;
/**
* Allocate a free port number and
* bind this socket to this port number on the
* specified interface.
*
* \param address address of interface to bind to.
* \returns 0 on success, -1 on failure.
*/
virtual int Bind (Ipv4Address address) = 0;
/**
* Bind this socket to this port number
* on all interfaces of this system.
*
* \param port port to bind to on all interfaces
* \returns 0 on success, -1 on failure.
*/
virtual int Bind (uint16_t port) = 0;
/**
* Bind this socket to this port number
* on the interface specified by address.
*
* \param address address of interface to bind to.
* \param port port to bind to on specified interface
* \returns 0 on success, -1 on failure.
*/
virtual int Bind (Ipv4Address address, uint16_t port) = 0;
/**
* \brief Close a socket.
* \param closeCompleted Callback invoked when the close operation is
* completed.
*
* After the Close call, the socket is no longer valid, and cannot
* safely be used for subsequent operations.
*/
void Close(Callback<void, Socket*> closeCompleted = MakeCallback (&Socket::DummyCallbackVoidSocket));
/**
* \returns zero on success, -1 on failure.
*
* Do not allow any further Send calls. This method is typically
* implemented for Tcp sockets by a half close.
*/
virtual int ShutdownSend (void) = 0;
/**
* \returns zero on success, -1 on failure.
*
* Do not allow any further Recv calls. This method is typically
* implemented for Tcp sockets by a half close.
*/
virtual int ShutdownRecv (void) = 0;
/**
* \brief Initiate a connection to a remote host
* \param address IP Address of remote.
* \param portNumber Port number of remote
* \param connectionSucceeded this callback is invoked when the connection request
* initiated by the user is successfully completed. The callback is passed
* back a pointer to the same socket object.
* \param connectionFailed this callback is invoked when the connection request
* initiated by the user is unsuccessfully completed. The callback is passed
* back a pointer to the same socket object.
* \param halfClose XXX When exactly is this callback invoked ? If it invoked when the
* other side closes the connection ? Or when I call Close ?
*/
void Connect(const Ipv4Address & address,
uint16_t portNumber,
Callback<void, Socket*> connectionSucceeded = MakeCallback(&Socket::DummyCallbackVoidSocket),
Callback<void, Socket*> connectionFailed = MakeCallback(&Socket::DummyCallbackVoidSocket),
Callback<void, Socket*> halfClose = MakeCallback(&Socket::DummyCallbackVoidSocket));
/**
* \brief Accept connection requests from remote hosts
* \param connectionRequest Callback for connection request from peer.
* This user callback is passed a pointer to this socket, the
* ip address and the port number of the connection originator.
* This callback must return true to accept the incoming connection,
* false otherwise. If the connection is accepted, the
* "newConnectionCreated" callback will be invoked later to give access
* to the user to the socket created to match this new connection. If the
* user does not explicitely specify this callback, all incoming
* connections will be refused.
* \param newConnectionCreated Callback for new connection: when a new
* is accepted, it is created and the corresponding socket is passed
* back to the user through this callback. This user callback is passed
* a pointer to the new socket, and the ip address and port number
* of the connection originator.
* \param closeRequested Callback for connection close request from peer.
* XXX: when is this callback invoked ?
*/
int Accept(Callback<bool, Socket*, const Ipv4Address&, uint16_t> connectionRequest =
MakeCallback(&Socket::RefuseAllConnections),
Callback<void, Socket*, const Ipv4Address&, uint16_t> newConnectionCreated =
MakeCallback (&Socket::DummyCallbackVoidSocketIpv4AddressUi16),
Callback<void, Socket*> closeRequested = MakeCallback (&Socket::DummyCallbackVoidSocket));
/**
* \brief Send data (or dummy data) to the remote host
* \param buffer Data to send (nil if dummy data).
* \param size Number of bytes to send.
* \param dataSent Data sent callback.
* \returns -1 in case of error or the number of bytes copied in the
* internal buffer and accepted for transmission.
*/
int Send (const uint8_t* buffer,
uint32_t size,
Callback<void, Socket*, uint32_t> dataSent = MakeCallback (&Socket::DummyCallbackVoidSocketUi32));
public:
// Define the BSD Socket API, with some slight variations.
// \brief Bind the socket to a particular port number
// \param Port number to bind. If zero is specified, an available
// transient port is assigned.
// \return Port number assigned, or -1 if port already in use.
virtual PortId_t Bind(PortId_t = 0);
// \brief Close a socket.
// After the Close call, the socket is no longer valid, and cannot
// safely be used for subsequent operations.
// \param Callback for close completed.
virtual void Close(ns3::Callback<void, Socket*>
= MakeCallback(&Socket::CBIgnoreVS));
// \brief Initiate a connection to a remote host
// \param IP Address of remote.
// \param Port number of remote
// \param Callback for connection succeeded
// \param Callback for connection failed
// \param Callback for connection close requested by peer
virtual void Connect(const IPAddr&, // IPAddress of peer
PortId_t, // Port number
ns3::Callback<void, Socket*> = // COnnection succeeded callback,
MakeCallback(&Socket::CBIgnoreVS),
ns3::Callback<void, Socket*> = // Connection failed callback
MakeCallback(&Socket::CBIgnoreVS),
ns3::Callback<void, Socket*> = // CloseRequested callback
MakeCallback(&Socket::CBIgnoreVS));
/**
* \brief Send data to a specified peer.
* \param address IP Address of remote host
* \param port port number
* \param buffer Data to send (nil if dummy data).
* \param size Number of bytes to send.
* \param dataSent Data sent callback.
* \returns -1 in case of error or the number of bytes copied in the
* internal buffer and accepted for transmission.
*/
int SendTo(const Ipv4Address &address,
uint16_t port,
const uint8_t *buffer,
uint32_t size,
Callback<void, Socket*, uint32_t> dataSent = MakeCallback (&Socket::DummyCallbackVoidSocketUi32));
// \brief Specify the number of pending connections to buffer
// while not blocked on accept. We include this for completeness,
// but with the callback approach to connection acceptance this
// does nothing.
virtual void Listen(uint32_t);
/**
* \brief Receive data
* \param Received data callback. Invoked whenever new data is received.
*
* If you wish to transport only dummy packets, this method is not a very
* efficient way to receive these dummy packets: it will trigger a memory
* allocation to hold the dummy memory into a buffer which can be passed
* to the user. Instead, consider using the RecvDummy method.
*/
void Recv(Callback<void, Socket*, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> =
MakeCallback (&Socket::DummyCallbackVoidSocketBufferUi32Ipv4AddressUi16));
// \brief Accept connection requests from remote hosts
// \param Callback for connection request from peer
// \param Callback for new connection
// \param Callback for connection close request from peer
virtual void Accept(
// Connection request callback
ns3::Callback<bool, Socket*, const IPAddr&, PortId_t> =
MakeCallback(&Socket::CBIgnoreBSIP),
// New connection callback
ns3::Callback<void, Socket*, const IPAddr&, PortId_t> =
MakeCallback(&Socket::CBIgnoreVSIP),
// CloseRequested callback
ns3::Callback<void, Socket*> =
MakeCallback(&Socket::CBIgnoreVS));
// \brief Send data (or dummy data) to the remote host
// \param Data to send (nil if dummy data).
// NOTE. The data (if any) is copied by this call, so pointers
// to local data is allowed and processed correctly.
// \param Number of bytes to send.
// \param Data sent callback. A suitable "ignore" callback
// is used if not specified.
virtual void Send(char*, // Data to send
uint32_t, // Number of bytes
ns3::Callback<void, Socket*, uint32_t> =
MakeCallback(&CBIgnoreVSU)); // Sent cb
// \brief Send data to a specified peer.
// \param IP Address of remote host
// \param port number
// \param Data to send (nil if dummy data).
// NOTE. The data (if any) is copied by this call, so pointers
// to local data is allowed and processed correctly.
// \param Number of bytes to send.
// \param Data sent callback
virtual void SendTo(const IPAddr&, // IP Address of remote peer
PortId_t, // Port number of remote peer
char*, // Data to send
uint32_t, // Number of bytes
ns3::Callback<void, Socket*, uint32_t> =
MakeCallback(&Socket::CBIgnoreVSU)); // Sent cb
// \brief Receive data
// Note that due to the callback nature of the ns3 implementation,
// there is no data pointer provided here. Rather, the callback
// will specify where the data can be found, and the callback should
// copy it to a local buffer if needed at that time.
// \param Received data callback.
virtual void Recv(ns3::Callback<void, Socket*, char*, uint32_t,
const IPAddr&, PortId_t> =
MakeCallback(&Socket::CBIgnoreVSCUIP));
/**
* \brief Receive data
* \param Received data callback. Invoked whenever new data is received.
*
* This method is included because it is vastly more efficient than the
* Recv method when you use dummy payload.
*/
void RecvDummy(Callback<void, Socket*, uint32_t,const Ipv4Address&, uint16_t> =
MakeCallback (&Socket::DummyCallbackVoidSocketUi32Ipv4AddressUi16));
private:
// upcalls
// The members below are all callbacks, created with MakeCallback,
ns3::Callback<void, Socket*> m_cbCloseComplete; // Socket Closed upcall
ns3::Callback<void, Socket*> m_cbCloseRequested; // Close req by peer
ns3::Callback<void, Socket*> m_cbConnectionSucceeded;// Connection successful
ns3::Callback<void, Socket*> m_cbConnectionFailed; // Connection failed
virtual void DoClose(Callback<void, Socket*> closeCompleted) = 0;
virtual void DoConnect(const Ipv4Address & address,
uint16_t portNumber,
Callback<void, Socket*> connectionSucceeded,
Callback<void, Socket*> connectionFailed,
Callback<void, Socket*> halfClose) = 0;
virtual int DoAccept(Callback<bool, Socket*, const Ipv4Address&, uint16_t> connectionRequest,
Callback<void, Socket*, const Ipv4Address&, uint16_t> newConnectionCreated,
Callback<void, Socket*> closeRequested) = 0;
virtual int DoSend (const uint8_t* buffer,
uint32_t size,
Callback<void, Socket*, uint32_t> dataSent) = 0;
virtual int DoSendTo(const Ipv4Address &address,
uint16_t port,
const uint8_t *buffer,
uint32_t size,
Callback<void, Socket*, uint32_t> dataSent) = 0;
virtual void DoRecv(Callback<void, Socket*, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> receive) = 0;
virtual void DoRecvDummy(Callback<void, Socket*, uint32_t,const Ipv4Address&, uint16_t>) = 0;
// \brief For TCP sockets, the cbSent upcall call is made when the data packet
// is sent, but not acknowledged. For UDP sockets, it is called
// immediately.
ns3::Callback<void, Socket*, uint32_t> m_cbSent; // Data delivered
// \brief For the cbRecv callback, the char* to the data may be nil if
// no actual data is present.
ns3::Callback<void, Socket*, char*, uint32_t,
const IPAddr&, PortId_t> m_cbRecv;
// \brief The cbConnectionRequest callback is called when a socket has
// called Listen, and indicates a remote peer has sent a connection
// request. The callback can return false to indicate the connection
// is to be rejected, for example in a peer-to-peer application that
// wants to limit the number of connections at any one time.
ns3::Callback<bool, Socket*, const IPAddr&, PortId_t> m_cbConnectionRequest;
// \brief The cbNewConnection callback is called when a connection request
// from a peer has been received and accepted by the process owning
// this socket. Note the Socket* passed to the upcall is a new
// socket. The original socket using accept is still accepting connections.
ns3::Callback<void, Socket*, const IPAddr&, PortId_t> m_cbNewConnection;
static bool RefuseAllConnections (Socket* socket, const Ipv4Address& address, uint16_t port);
static void DummyCallbackVoidSocket (Socket *socket);
static void DummyCallbackVoidSocketUi32 (Socket *socket, uint32_t);
static void DummyCallbackVoidSocketUi32Ipv4AddressUi16 (Socket *socket, uint32_t, const Ipv4Address &, uint16_t);
static void DummyCallbackVoidSocketBufferUi32Ipv4AddressUi16 (Socket *socket, const uint8_t *, uint32_t,
const Ipv4Address &, uint16_t);
static void DummyCallbackVoidSocketIpv4AddressUi16 (Socket *socket, const Ipv4Address &, uint16_t);
};
} //namespace ns3
#endif
#endif /* SOCKET_H */

View File

@@ -28,11 +28,11 @@ UdpEndPoint::UdpEndPoint (Ipv4Address address, uint16_t port)
{}
void
UdpEndPoint::SetSocket (DatagramSocket *socket)
UdpEndPoint::SetSocket (UdpSocket *socket)
{
m_socket = socket;
}
DatagramSocket *
UdpSocket *
UdpEndPoint::GetSocket (void) const
{
return m_socket;

View File

@@ -27,17 +27,17 @@
namespace ns3 {
class DatagramSocket;
class UdpSocket;
class UdpEndPoint : public Ipv4EndPoint
{
public:
UdpEndPoint (Ipv4Address address, uint16_t port);
void SetSocket (DatagramSocket *socket);
DatagramSocket *GetSocket (void) const;
void SetSocket (UdpSocket *socket);
UdpSocket *GetSocket (void) const;
private:
DatagramSocket *m_socket;
UdpSocket *m_socket;
};
}//namespace ns3

251
src/node/udp-socket.cc Normal file
View File

@@ -0,0 +1,251 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 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-socket.h"
#include "udp.h"
#include "udp-end-point.h"
#include "node.h"
#include "ipv4-l4-demux.h"
namespace ns3 {
UdpSocket::UdpSocket (Node *node)
: m_endPoint (0),
m_node (node),
m_errno (ENOTERROR),
m_shutdownSend (false),
m_shutdownRecv (false),
m_connected (false)
{
NS_ASSERT (GetUdp () != 0);
}
UdpSocket::~UdpSocket ()
{
delete m_endPoint;
}
Node *
UdpSocket::GetNode (void) const
{
return m_node;
}
int
UdpSocket::Bind (void)
{
m_endPoint = GetUdp ()->Allocate ();
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
int
UdpSocket::Bind (Ipv4Address address)
{
m_endPoint = GetUdp ()->Allocate (address);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
int
UdpSocket::Bind (uint16_t port)
{
m_endPoint = GetUdp ()->Allocate (port);
if (m_endPoint == 0)
{
return -1;
}
m_endPoint->SetSocket (this);
return 0;
}
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;
}
enum Socket::SocketErrno
UdpSocket::GetErrno (void) const
{
return m_errno;
}
int
UdpSocket::ShutdownSend (void)
{
m_shutdownSend = true;
return 0;
}
int
UdpSocket::ShutdownRecv (void)
{
m_shutdownRecv = false;
return 0;
}
void
UdpSocket::DoClose(ns3::Callback<void, Socket*> closeCompleted)
{
// XXX: we should set the close state and check it in all API methods.
if (!closeCompleted.IsNull ())
{
closeCompleted (this);
}
}
void
UdpSocket::DoConnect(const Ipv4Address & address,
uint16_t portNumber,
ns3::Callback<void, Socket*> connectionSucceeded,
ns3::Callback<void, Socket*> connectionFailed,
ns3::Callback<void, Socket*> halfClose)
{
m_defaultAddress = address;
m_defaultPort = portNumber;
if (!connectionSucceeded.IsNull ())
{
connectionSucceeded (this);
}
m_connected = true;
}
int
UdpSocket::DoAccept(ns3::Callback<bool, Socket*, const Ipv4Address&, uint16_t> connectionRequest,
ns3::Callback<void, Socket*, const Ipv4Address&, uint16_t> newConnectionCreated,
ns3::Callback<void, Socket*> closeRequested)
{
// calling accept on a udp socket is a programming error.
m_errno = EOPNOTSUPP;
return -1;
}
int
UdpSocket::DoSend (const uint8_t* buffer,
uint32_t size,
ns3::Callback<void, Socket*, uint32_t> dataSent)
{
if (!m_connected)
{
m_errno = ENOTCONN;
return -1;
}
Packet p;
if (buffer == 0)
{
p = Packet (size);
}
else
{
p = Packet (buffer, size);
}
return DoSendPacketTo (p, m_defaultAddress, m_defaultPort, dataSent);
}
int
UdpSocket::DoSendPacketTo (const Packet &p, Ipv4Address daddr, uint16_t dport,
ns3::Callback<void, Socket*, uint32_t> dataSent)
{
if (m_endPoint == 0)
{
if (Bind () == -1)
{
NS_ASSERT (m_endPoint == 0);
return -1;
}
NS_ASSERT (m_endPoint != 0);
}
if (m_shutdownSend)
{
m_errno = ESHUTDOWN;
return -1;
}
GetUdp ()->Send (p, m_endPoint->GetLocalAddress (), daddr,
m_endPoint->GetLocalPort (), dport);
if (!dataSent.IsNull ())
{
dataSent (this, p.GetSize ());
}
return 0;
}
int
UdpSocket::DoSendTo(const Ipv4Address &address,
uint16_t port,
const uint8_t *buffer,
uint32_t size,
ns3::Callback<void, Socket*, uint32_t> dataSent)
{
if (m_connected)
{
m_errno = EISCONN;
return -1;
}
Packet p;
if (buffer == 0)
{
p = Packet (size);
}
else
{
p = Packet (buffer, size);
}
return DoSendPacketTo (p, address, port, dataSent);
}
void
UdpSocket::DoRecv(ns3::Callback<void, Socket*, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> callback)
{
m_rxCallback = callback;
}
void
UdpSocket::DoRecvDummy(ns3::Callback<void, Socket*, uint32_t,const Ipv4Address&, uint16_t> callback)
{
m_dummyRxCallback = callback;
}
void
UdpSocket::ForwardUp (Packet &p, Ipv4Address saddr, uint16_t sport)
{
if (m_shutdownRecv)
{
return;
}
if (!m_dummyRxCallback.IsNull ())
{
m_dummyRxCallback (this, p.GetSize (), saddr, sport);
}
if (!m_rxCallback.IsNull ())
{
m_rxCallback (this, p.PeekData (), p.GetSize (), saddr, sport);
}
}
Udp *
UdpSocket::GetUdp (void) const
{
return m_node->GetUdp ();
}
}//namespace ns3

96
src/node/udp-socket.h Normal file
View File

@@ -0,0 +1,96 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 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_SOCKET_H
#define UDP_SOCKET_H
#include <stdint.h>
#include "ns3/callback.h"
#include "socket.h"
namespace ns3 {
class UdpEndPoint;
class Node;
class Packet;
class Udp;
class UdpSocket : public Socket
{
public:
/**
* Create an unbound udp socket.
*/
UdpSocket (Node *node);
virtual ~UdpSocket ();
virtual enum SocketErrno GetErrno (void) const;
virtual Node *GetNode (void) const;
virtual int Bind (void);
virtual int Bind (Ipv4Address address);
virtual int Bind (uint16_t port);
virtual int Bind (Ipv4Address address, uint16_t port);
virtual int ShutdownSend (void);
virtual int ShutdownRecv (void);
private:
virtual void DoClose(ns3::Callback<void, Socket*> closeCompleted);
virtual void DoConnect(const Ipv4Address & address,
uint16_t portNumber,
ns3::Callback<void, Socket*> connectionSucceeded,
ns3::Callback<void, Socket*> connectionFailed,
ns3::Callback<void, Socket*> halfClose);
virtual int DoAccept(ns3::Callback<bool, Socket*, const Ipv4Address&, uint16_t> connectionRequest,
ns3::Callback<void, Socket*, const Ipv4Address&, uint16_t> newConnectionCreated,
ns3::Callback<void, Socket*> closeRequested);
virtual int DoSend (const uint8_t* buffer,
uint32_t size,
ns3::Callback<void, Socket*, uint32_t> dataSent);
virtual int DoSendTo(const Ipv4Address &address,
uint16_t port,
const uint8_t *buffer,
uint32_t size,
ns3::Callback<void, Socket*, uint32_t> dataSent);
virtual void DoRecv(ns3::Callback<void, Socket*, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t>);
virtual void DoRecvDummy(ns3::Callback<void, Socket*, uint32_t,const Ipv4Address&, uint16_t>);
private:
friend class Udp;
// invoked by Udp class
void ForwardUp (Packet &p, Ipv4Address saddr, uint16_t sport);
Udp *GetUdp (void) const;
int DoSendPacketTo (const Packet &p, Ipv4Address daddr, uint16_t dport,
ns3::Callback<void, Socket*, uint32_t> dataSent);
UdpEndPoint *m_endPoint;
Node *m_node;
Ipv4Address m_defaultAddress;
uint16_t m_defaultPort;
Callback<void,Socket*,uint32_t,const Ipv4Address &,uint16_t> m_dummyRxCallback;
Callback<void,Socket*,uint8_t const*,uint32_t,const Ipv4Address &,uint16_t> m_rxCallback;
enum SocketErrno m_errno;
bool m_shutdownSend;
bool m_shutdownRecv;
bool m_connected;
};
}//namespace ns3
#endif /* UDP_SOCKET_H */

View File

@@ -27,10 +27,10 @@
#include "udp-header.h"
#include "ipv4-end-point-demux.h"
#include "udp-end-point.h"
#include "datagram-socket.h"
#include "node.h"
#include "ipv4.h"
#include "l3-demux.h"
#include "udp-socket.h"
namespace ns3 {
@@ -54,6 +54,12 @@ Udp::CreateTraceResolver (TraceContext const &context)
return new EmptyTraceResolver (context);
}
Socket *
Udp::CreateSocket (void)
{
return new UdpSocket (m_node);
}
UdpEndPoint *
Udp::Allocate (void)
{
@@ -102,7 +108,7 @@ Udp::Receive(Packet& packet,
{
return;
}
DatagramSocket *socket = endPoint->GetSocket ();
UdpSocket *socket = endPoint->GetSocket ();
socket->ForwardUp (packet, source, udpHeader.GetSource ());
NS_ASSERT (socket != 0);
}

View File

@@ -35,6 +35,7 @@ namespace ns3 {
class Node;
class TraceResolver;
class TraceContext;
class Socket;
class Udp : public Ipv4L4Protocol {
public:
@@ -45,6 +46,8 @@ public:
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
Socket *CreateSocket (void);
UdpEndPoint *Allocate (void);
UdpEndPoint *Allocate (Ipv4Address address);
UdpEndPoint *Allocate (uint16_t port);