remove DatagramSocket, use Socket base class for UdpSocket subclass.
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Mon, 30 Apr 2007 16:23:10 +0200
changeset 453 ddbb935800d8
parent 452 e4712748b5a0
child 461 3cde302c4300
remove DatagramSocket, use Socket base class for UdpSocket subclass.
SConstruct
examples/simple-p2p.cc
samples/main-p2p-net-device-if.cc
samples/main-simple.cc
src/node/datagram-socket.cc
src/node/datagram-socket.h
src/node/onoff-application.cc
src/node/onoff-application.h
src/node/socket.cc
src/node/socket.h
src/node/udp-end-point.cc
src/node/udp-end-point.h
src/node/udp-socket.cc
src/node/udp-socket.h
src/node/udp.cc
src/node/udp.h
--- a/SConstruct	Mon Apr 30 10:37:57 2007 +0200
+++ b/SConstruct	Mon Apr 30 16:23:10 2007 +0200
@@ -200,7 +200,6 @@
     'ipv4.cc',
     'ipv4-end-point.cc',
     'udp-end-point.cc',
-    'datagram-socket.cc',
     'udp.cc',
     'capability.cc',
     'arp-header.cc',
@@ -218,13 +217,13 @@
     '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 @@
     '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 @@
     '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')
--- a/examples/simple-p2p.cc	Mon Apr 30 10:37:57 2007 +0200
+++ b/examples/simple-p2p.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -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"
--- a/samples/main-p2p-net-device-if.cc	Mon Apr 30 10:37:57 2007 +0200
+++ b/samples/main-p2p-net-device-if.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -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 @@
 };
 
 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 @@
 }
 
 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 @@
 }
 
 static void
-PrintTraffic (DatagramSocket *socket)
+PrintTraffic (Socket *socket)
 {
-  socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
+  socket->RecvDummy (MakeCallback (&SocketPrinter));
 }
 
 
@@ -200,10 +201,10 @@
   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");
 
--- a/samples/main-simple.cc	Mon Apr 30 10:37:57 2007 +0200
+++ b/samples/main-simple.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -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 @@
 }
 
 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 @@
 }
 
 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 @@
   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);
--- a/src/node/datagram-socket.cc	Mon Apr 30 10:37:57 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/src/node/datagram-socket.h	Mon Apr 30 10:37:57 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 */
--- a/src/node/onoff-application.cc	Mon Apr 30 10:37:57 2007 +0200
+++ b/src/node/onoff-application.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -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 @@
                         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::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 @@
   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;
 }
--- a/src/node/onoff-application.h	Mon Apr 30 10:37:57 2007 +0200
+++ b/src/node/onoff-application.h	Mon Apr 30 16:23:10 2007 +0200
@@ -36,7 +36,7 @@
 
 class Ipv4Address;
 class RandomVariable;
-class DatagramSocket;
+class Socket;
 class DataRate;
 
 class OnOffApplication : public Application {
@@ -69,7 +69,7 @@
   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 @@
   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:
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/socket.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -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
--- a/src/node/socket.h	Mon Apr 30 10:37:57 2007 +0200
+++ b/src/node/socket.h	Mon Apr 30 16:23:10 2007 +0200
@@ -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 Node;
 
-class IPAddr;
-class L4Protocol;
-class Process;
-
-// \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);
-  
-public:
-  // Define the BSD Socket API, with some slight variations.
+  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 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.
+   * \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));
 
-  // \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));
+  /**
+   * \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 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 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));
   
-  // \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 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 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.
+   *
+   * 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 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
-
-  // \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
+  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 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 */
 
 
--- a/src/node/udp-end-point.cc	Mon Apr 30 10:37:57 2007 +0200
+++ b/src/node/udp-end-point.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -28,11 +28,11 @@
 {}
 
 void 
-UdpEndPoint::SetSocket (DatagramSocket *socket)
+UdpEndPoint::SetSocket (UdpSocket *socket)
 {
   m_socket = socket;
 }
-DatagramSocket *
+UdpSocket *
 UdpEndPoint::GetSocket (void) const
 {
   return m_socket;
--- a/src/node/udp-end-point.h	Mon Apr 30 10:37:57 2007 +0200
+++ b/src/node/udp-end-point.h	Mon Apr 30 16:23:10 2007 +0200
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/udp-socket.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/udp-socket.h	Mon Apr 30 16:23:10 2007 +0200
@@ -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 */
--- a/src/node/udp.cc	Mon Apr 30 10:37:57 2007 +0200
+++ b/src/node/udp.cc	Mon Apr 30 16:23:10 2007 +0200
@@ -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 @@
   return new EmptyTraceResolver (context);
 }
 
+Socket *
+Udp::CreateSocket (void)
+{
+  return new UdpSocket (m_node);
+}
+
 UdpEndPoint *
 Udp::Allocate (void)
 {
@@ -102,7 +108,7 @@
     {
       return;
     }
-  DatagramSocket *socket = endPoint->GetSocket ();
+  UdpSocket *socket = endPoint->GetSocket ();
   socket->ForwardUp (packet, source, udpHeader.GetSource ());
   NS_ASSERT (socket != 0);
 }
--- a/src/node/udp.h	Mon Apr 30 10:37:57 2007 +0200
+++ b/src/node/udp.h	Mon Apr 30 16:23:10 2007 +0200
@@ -35,6 +35,7 @@
 class Node;
 class TraceResolver;
 class TraceContext;
+class Socket;
 
 class Udp : public Ipv4L4Protocol {
 public:
@@ -45,6 +46,8 @@
 
   virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
 
+  Socket *CreateSocket (void);
+
   UdpEndPoint *Allocate (void);
   UdpEndPoint *Allocate (Ipv4Address address);
   UdpEndPoint *Allocate (uint16_t port);