plugins/ip-faces: Initial implementation of UdpFace

Refs #1006 (http://redmine.named-data.net/)
diff --git a/model/ndn-l3-protocol.cc b/model/ndn-l3-protocol.cc
index e89c9ea..0c0332f 100644
--- a/model/ndn-l3-protocol.cc
+++ b/model/ndn-l3-protocol.cc
@@ -49,6 +49,7 @@
 namespace ndn {
 
 const uint16_t L3Protocol::ETHERNET_FRAME_TYPE = 0x7777;
+const uint16_t L3Protocol::IP_STACK_PORT = 9695;
 
 NS_OBJECT_ENSURE_REGISTERED (L3Protocol);
 
diff --git a/model/ndn-l3-protocol.h b/model/ndn-l3-protocol.h
index 406e194..552bd19 100644
--- a/model/ndn-l3-protocol.h
+++ b/model/ndn-l3-protocol.h
@@ -74,9 +74,9 @@
    */
   static TypeId GetTypeId ();
 
-  static const uint16_t ETHERNET_FRAME_TYPE; ///< \brief Ethernet Frame Type of Ndn
-  // static const uint16_t IP_PROTOCOL_TYPE;    ///< \brief IP protocol type of Ndn
-  // static const uint16_t UDP_PORT;            ///< \brief UDP port of Ndn
+  static const uint16_t ETHERNET_FRAME_TYPE; ///< @brief Ethernet Frame Type of Ndn
+  static const uint16_t IP_STACK_PORT;       ///< @brief TCP/UDP port for NDN stack
+  // static const uint16_t IP_PROTOCOL_TYPE;    ///< \brief IP protocol type of NDN
 
   /**
    * \brief Default constructor. Creates an empty stack without forwarding strategy set
diff --git a/plugins/ip-faces/ndn-ip-face-stack.cc b/plugins/ip-faces/ndn-ip-face-stack.cc
index 94faea4..cbb5e24 100644
--- a/plugins/ip-faces/ndn-ip-face-stack.cc
+++ b/plugins/ip-faces/ndn-ip-face-stack.cc
@@ -38,8 +38,6 @@
     
 NS_OBJECT_ENSURE_REGISTERED (IpFaceStack);
 
-const uint16_t NDN_IP_STACK_PORT = 9695;
-
 TypeId
 IpFaceStack::GetTypeId (void)
 {
@@ -53,10 +51,10 @@
                    MakeBooleanAccessor (&IpFaceStack::m_enableTcp),
                    MakeBooleanChecker ())
 
-    // .AddAttribute ("EnableUDP", "Enable ability to create UDP faces",
-    //                BooleanValue (true),
-    //                MakeBooleanAccessor (&IpFaceStack::m_enableUdp),
-    //                MakeBooleanChecker ())
+    .AddAttribute ("EnableUDP", "Enable ability to create UDP faces",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&IpFaceStack::m_enableUdp),
+                   MakeBooleanChecker ())
     ;
   return tid;
 }
@@ -92,12 +90,20 @@
     {
       m_tcpServer = Socket::CreateSocket (m_node, TcpSocketFactory::GetTypeId ());
   
-      m_tcpServer->Bind (InetSocketAddress (Ipv4Address::GetAny (), NDN_IP_STACK_PORT));
+      m_tcpServer->Bind (InetSocketAddress (Ipv4Address::GetAny (), L3Protocol::IP_STACK_PORT));
       m_tcpServer->Listen ();
 
       m_tcpServer->SetAcceptCallback (MakeCallback (&IpFaceStack::OnTcpConnectionRequest, this),
                                       MakeCallback (&IpFaceStack::OnTcpConnectionAccept, this));
+    }
 
+  if (m_enableUdp)
+    {
+      // m_udpServer = Socket::CreateSocket (m_node, UdpSocketFactory::GetTypeId ());  
+      // m_udpServer->Bind (InetSocketAddress (Ipv4Address::GetAny (), L3Protocol::IP_STACK_PORT));
+      
+      // m_udpServer->SetRecvCallback (MakeCallback (&IpFaceStack::HandleRead, this));
+      // #error "Broken"
     }
 }
 
diff --git a/plugins/ip-faces/ndn-ip-face-stack.h b/plugins/ip-faces/ndn-ip-face-stack.h
index 83cf4cb..bf15b3e 100644
--- a/plugins/ip-faces/ndn-ip-face-stack.h
+++ b/plugins/ip-faces/ndn-ip-face-stack.h
@@ -76,9 +76,10 @@
   Ptr<Node> m_node;
   
   bool m_enableTcp;
-  // bool m_enableUdp;
+  bool m_enableUdp;
   
   Ptr<Socket> m_tcpServer;
+  Ptr<Socket> m_udpServer;
 };
 
 } // namespace ndn
diff --git a/plugins/ip-faces/ndn-tcp-face.cc b/plugins/ip-faces/ndn-tcp-face.cc
index c1d9321..4ef8908 100644
--- a/plugins/ip-faces/ndn-tcp-face.cc
+++ b/plugins/ip-faces/ndn-tcp-face.cc
@@ -37,8 +37,6 @@
 namespace ns3 {
 namespace ndn {
 
-const uint16_t NDN_IP_STACK_PORT = 9695;
-
 TcpFace::FaceMap TcpFace::s_map;
 
 class TcpBoundaryHeader : public Header
@@ -262,7 +260,7 @@
   
   socket->SetConnectCallback (MakeCallback (&TcpFace::OnConnect, face),
                               MakeNullCallback< void, Ptr< Socket > > ());
-  socket->Connect (InetSocketAddress (address, NDN_IP_STACK_PORT));
+  socket->Connect (InetSocketAddress (address, L3Protocol::IP_STACK_PORT));
 
   s_map.insert (std::make_pair (address, face));
 
@@ -286,7 +284,7 @@
 std::ostream&
 TcpFace::Print (std::ostream& os) const
 {
-  os << "dev=tcp(" << GetId () << ")";
+  os << "dev=tcp(" << GetId () << ", " << m_address << ")";
   return os;
 }
 
diff --git a/plugins/ip-faces/ndn-udp-face.cc b/plugins/ip-faces/ndn-udp-face.cc
new file mode 100644
index 0000000..4ebff28
--- /dev/null
+++ b/plugins/ip-faces/ndn-udp-face.cc
@@ -0,0 +1,161 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *
+ */
+
+#include "ndn-udp-face.h"
+#include "ns3/ndn-l3-protocol.h"
+
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/pointer.h"
+#include "ns3/tcp-socket-factory.h"
+
+#include "ns3/ndn-name.h"
+
+using namespace std;
+
+NS_LOG_COMPONENT_DEFINE ("ndn.UdpFace");
+
+namespace ns3 {
+namespace ndn {
+
+UdpFace::FaceMap UdpFace::s_map;
+
+NS_OBJECT_ENSURE_REGISTERED (UdpFace);
+
+TypeId
+UdpFace::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::ndn::UdpFace")
+    .SetParent<Face> ()
+    .SetGroupName ("Ndn")
+    ;
+  return tid;
+}
+
+/**
+ * By default, Ndn face are created in the "down" state.  Before
+ * becoming useable, the user must invoke SetUp on the face
+ */
+UdpFace::UdpFace (Ptr<Node> node, Ptr<Socket> socket, Ipv4Address address)
+  : Face (node)
+  , m_socket (socket)
+  , m_address (address)
+{
+  SetMetric (1); // default metric
+}
+
+UdpFace::~UdpFace ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+UdpFace& UdpFace::operator= (const UdpFace &)
+{
+  return *this;
+}
+
+void
+UdpFace::RegisterProtocolHandler (ProtocolHandler handler)
+{
+  NS_LOG_FUNCTION (this);
+
+  Face::RegisterProtocolHandler (handler);
+
+  m_socket->SetRecvCallback (MakeCallback (&UdpFace::ReceiveFromUdp, this));
+}
+
+bool
+UdpFace::SendImpl (Ptr<Packet> packet)
+{
+  NS_LOG_FUNCTION (this << packet);
+  Ptr<Packet> boundary = Create<Packet> ();
+  TcpBoundaryHeader hdr (packet);
+  boundary->AddHeader (hdr);
+  
+  m_socket->Send (boundary);
+  m_socket->Send (packet);
+
+  return true;
+}
+
+void
+UdpFace::ReceiveFromUdp (Ptr< Socket > clientSocket)
+{
+  NS_LOG_FUNCTION (this << clientSocket);
+
+  Ptr<Packet> packet;
+  Address from;
+  while ((packet = socket->RecvFrom (from)))
+    {
+      Receive (realPacket);
+    }
+  }
+}
+
+Ipv4Address
+UdpFace::GetAddress () const
+{
+  return m_address;
+}
+
+Ptr<UdpFace>
+UdpFace::GetFaceByAddress (const Ipv4Address &address)
+{
+  FaceMap::iterator i = s_map.find (address);
+  if (i != s_map.end ())
+    return i->second;
+  else
+    return 0;
+}
+
+Ptr<UdpFace>
+UdpFace::CreateOrGetFace (Ptr<Node> node, Ipv4Address address)
+{
+  NS_LOG_FUNCTION (address);
+
+  FaceMap::iterator i = s_map.find (address);
+  if (i != s_map.end ())
+    return i->second;
+  
+  Ptr<Socket> socket = Socket::CreateSocket (node, UdpSocketFactory::GetTypeId ());
+  Ptr<UdpFace> face = CreateObject<UdpFace> (node, socket, address);
+
+  Ptr<L3Protocol> ndn = GetNode ()->GetObject<L3Protocol> ();
+  
+  ndn->AddFace (this);
+  this->SetUp (true);
+
+  s_map.insert (std::make_pair (address, face));
+
+  return face;
+}
+    
+std::ostream&
+UdpFace::Print (std::ostream& os) const
+{
+  os << "dev=udp(" << GetId () << ")";
+  return os;
+}
+
+} // namespace ndn
+} // namespace ns3
+
diff --git a/plugins/ip-faces/ndn-udp-face.h b/plugins/ip-faces/ndn-udp-face.h
new file mode 100644
index 0000000..54f5fe3
--- /dev/null
+++ b/plugins/ip-faces/ndn-udp-face.h
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_UDP_FACE_H
+#define NDN_UDP_FACE_H
+
+#include "ns3/ndn-face.h"
+#include "ns3/socket.h"
+#include "ns3/ptr.h"
+
+#include <map>
+
+namespace ns3 {
+namespace ndn {
+  
+/**
+ * \ingroup ndn-face
+ * \brief Implementation of UDP/IP NDN face
+ *
+ * \see ndn::AppFace, ndn::NetDeviceFace, ndn::Ipv4Face, ndn::TcpFace
+ */
+class UdpFace : public Face
+{
+public:
+  static TypeId
+  GetTypeId ();
+
+  /**
+   * @brief A singleton method allowing creation and lookup of faces
+   *
+   * All created UDP faces are stored internally in the map, and if the same face is created, it will simply be looked up
+   */
+  static Ptr<UdpFace>
+  CreateOrGetFace (Ptr<Node> node, Ipv4Address address);
+  
+  /**
+   * \brief Constructor
+   *
+   * @param node Node associated with the face
+   */
+  UdpFace (Ptr<Node> node, Ptr<Socket> socket, Ipv4Address address);
+  virtual ~UdpFace();
+
+  ////////////////////////////////////////////////////////////////////
+  // methods overloaded from NdnFace
+  virtual void
+  RegisterProtocolHandler (ProtocolHandler handler);
+
+  Ipv4Address
+  GetAddress () const;
+
+  static Ptr<UdpFace>
+  GetFaceByAddress (const Ipv4Address &addr);
+
+protected:
+  // also from NdnFace
+  virtual bool
+  SendImpl (Ptr<Packet> p);
+
+public:
+  /**
+   * @brief Print out name of the NdnFace to the stream
+   */
+  virtual std::ostream&
+  Print (std::ostream &os) const;
+  ////////////////////////////////////////////////////////////////////
+
+private:  
+  UdpFace (const UdpFace &); ///< \brief Disabled copy constructor
+  UdpFace& operator= (const UdpFace &); ///< \brief Disabled copy operator
+
+  void
+  ReceiveFromUdp (Ptr< Socket > clientSocket);
+
+private:
+  Ptr<Socket> m_socket;
+  Ipv4Address m_address;
+
+  typedef std::map<Ipv4Address, Ptr<UdpFace> > FaceMap;
+  static FaceMap s_map;
+};
+
+} // namespace ndn
+} // namespace ns3
+
+#endif // NDN_UDP_FACE_H