plugins/ip-faces: ip-faces plugin, which implements ndn::TcpFace
This commit also includes a basic example showing how to work with
TcpFace. The code compiles and passes basic tests, but requires more
work and proper documentation
Refs #1006 (http://redmine.named-data.net/)
diff --git a/examples/ndn-simple-tcp.cc b/examples/ndn-simple-tcp.cc
new file mode 100644
index 0000000..641348a
--- /dev/null
+++ b/examples/ndn-simple-tcp.cc
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 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>
+ */
+// ndn-simple-tcp.cc
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/point-to-point-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/ndnSIM-module.h"
+
+using namespace ns3;
+
+/**
+ * This scenario simulates a very simple network topology:
+ *
+ *
+ * +----------+ 1Mbps +--------+ 1Mbps +----------+
+ * | consumer | <------------> | router | <------------> | producer |
+ * +----------+ 10ms +--------+ 10ms +----------+
+ * \ /
+ * -------------------- tcp face --------------------
+ *
+ * Consumer requests data from producer with frequency 10 interests per second
+ * (interests contain constantly increasing sequence number).
+ *
+ * For every received interest, producer replies with a data packet, containing
+ * 1024 bytes of virtual payload.
+ *
+ * To run scenario and see what is happening, use the following command:
+ *
+ * NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-simple-tcp
+ */
+
+int
+main (int argc, char *argv[])
+{
+ Packet::EnablePrinting ();
+
+ // setting default parameters for PointToPoint links and channels
+ Config::SetDefault ("ns3::PointToPointNetDevice::DataRate", StringValue ("1Mbps"));
+ Config::SetDefault ("ns3::PointToPointChannel::Delay", StringValue ("10ms"));
+ Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("20"));
+
+ // Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+
+ // Creating nodes
+ NodeContainer nodes;
+ nodes.Create (3);
+
+ // Connecting nodes using two links
+ PointToPointHelper p2p;
+ NetDeviceContainer link1 = p2p.Install (nodes.Get (0), nodes.Get (1));
+ NetDeviceContainer link2 = p2p.Install (nodes.Get (1), nodes.Get (2));
+
+ // Install NDN stack on all nodes
+ ndn::StackHelper ndnHelper;
+ ndnHelper.SetDefaultRoutes (false);
+ ndnHelper.InstallAll ();
+
+ InternetStackHelper ipStack;
+ ipStack.SetIpv6StackInstall (false);
+ ipStack.InstallAll ();
+
+ Ipv4AddressHelper ipAddressHelper;
+ ipAddressHelper.SetBase (Ipv4Address ("10.1.1.0"), Ipv4Mask ("255.255.255.0"));
+ ipAddressHelper.Assign (link1);
+
+ ipAddressHelper.SetBase (Ipv4Address ("10.1.2.0"), Ipv4Mask ("255.255.255.0"));
+ ipAddressHelper.Assign (link2);
+
+ Ipv4StaticRoutingHelper ipStaticRouting;
+ ipStaticRouting.GetStaticRouting (nodes.Get (0)->GetObject<Ipv4> ())->
+ AddNetworkRouteTo (Ipv4Address ("10.1.2.0"), Ipv4Mask ("255.255.255.0"),
+ Ipv4Address ("10.1.1.2"),
+ 1, 1);
+
+ ipStaticRouting.GetStaticRouting (nodes.Get (2)->GetObject<Ipv4> ())->
+ AddNetworkRouteTo (Ipv4Address ("10.1.1.0"), Ipv4Mask ("255.255.255.0"),
+ Ipv4Address ("10.1.2.1"),
+ 1, 1);
+
+ ndn::IpFacesHelper ipFacesHelper;
+ ipFacesHelper.InstallAll ();
+ ipFacesHelper.CreateTcpFace (nodes.Get (0), Ipv4Address ("10.1.2.2"), "/tcp-route");
+
+ // Installing applications
+
+ // Consumer
+ ndn::AppHelper consumerHelper ("ns3::ndn::ConsumerCbr");
+ // Consumer will request /tcp-route/0, /tcp-route/1, ...
+ consumerHelper.SetPrefix ("/tcp-route");
+ consumerHelper.SetAttribute ("Frequency", StringValue ("10")); // 10 interests a second
+ consumerHelper.Install (nodes.Get (0)).
+ Start (Seconds (3)); // first node
+
+ // Producer
+ ndn::AppHelper producerHelper ("ns3::ndn::Producer");
+ // Producer will reply to all requests starting with /prefix
+ producerHelper.SetPrefix ("/tcp-route");
+ producerHelper.SetAttribute ("PayloadSize", StringValue("1024"));
+ producerHelper.Install (nodes.Get (2)); // last node
+
+ Simulator::Stop (Seconds (20.0));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
diff --git a/examples/wscript b/examples/wscript
index 49a0c5c..c5c35eb 100644
--- a/examples/wscript
+++ b/examples/wscript
@@ -94,3 +94,7 @@
obj = bld.create_ns3_program('ndn-simple-with-link-failure', all_modules)
obj.source = 'ndn-simple-with-link-failure.cc'
+
+ if 'ip-faces' in bld.env['NDN_plugins']:
+ obj = bld.create_ns3_program('ndn-simple-tcp', all_modules)
+ obj.source = 'ndn-simple-tcp.cc'
diff --git a/plugins/ip-faces/ndn-ip-face-stack.cc b/plugins/ip-faces/ndn-ip-face-stack.cc
new file mode 100644
index 0000000..94faea4
--- /dev/null
+++ b/plugins/ip-faces/ndn-ip-face-stack.cc
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 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-ip-face-stack.h"
+#include "ndn-tcp-face.h"
+
+#include "ns3/ndn-l3-protocol.h"
+
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ns3/packet.h"
+
+#include "ns3/socket.h"
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/simulator.h"
+
+NS_LOG_COMPONENT_DEFINE ("ndn.IpFaceStack");
+
+namespace ns3 {
+namespace ndn {
+
+NS_OBJECT_ENSURE_REGISTERED (IpFaceStack);
+
+const uint16_t NDN_IP_STACK_PORT = 9695;
+
+TypeId
+IpFaceStack::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ndn::IpFaceStack")
+ .SetGroupName ("Ndn")
+ .SetParent<Object> ()
+ .AddConstructor<IpFaceStack> ()
+
+ .AddAttribute ("EnableTCP", "Enable ability to create TCP faces",
+ BooleanValue (true),
+ MakeBooleanAccessor (&IpFaceStack::m_enableTcp),
+ MakeBooleanChecker ())
+
+ // .AddAttribute ("EnableUDP", "Enable ability to create UDP faces",
+ // BooleanValue (true),
+ // MakeBooleanAccessor (&IpFaceStack::m_enableUdp),
+ // MakeBooleanChecker ())
+ ;
+ return tid;
+}
+
+IpFaceStack::IpFaceStack ()
+{
+}
+
+IpFaceStack::~IpFaceStack ()
+{
+}
+
+void
+IpFaceStack::NotifyNewAggregate ()
+{
+ if (m_node == 0)
+ {
+ m_node = GetObject<Node> ();
+ if (m_node != 0)
+ {
+ Simulator::ScheduleWithContext (m_node->GetId (), Seconds (0.1), &IpFaceStack::StartServer, this);
+ }
+ }
+}
+
+// Application Methods
+void
+IpFaceStack::StartServer () // Called at time specified by Start
+{
+ NS_LOG_FUNCTION (this);
+
+ if (m_enableTcp)
+ {
+ m_tcpServer = Socket::CreateSocket (m_node, TcpSocketFactory::GetTypeId ());
+
+ m_tcpServer->Bind (InetSocketAddress (Ipv4Address::GetAny (), NDN_IP_STACK_PORT));
+ m_tcpServer->Listen ();
+
+ m_tcpServer->SetAcceptCallback (MakeCallback (&IpFaceStack::OnTcpConnectionRequest, this),
+ MakeCallback (&IpFaceStack::OnTcpConnectionAccept, this));
+
+ }
+}
+
+bool
+IpFaceStack::OnTcpConnectionRequest (Ptr< Socket > sock, const Address &addr)
+{
+ NS_LOG_FUNCTION (this << sock << InetSocketAddress::ConvertFrom (addr));
+ return true; // accept all connections from anybody
+}
+
+void
+IpFaceStack::OnTcpConnectionAccept (Ptr<Socket> socket, const Address &addr)
+{
+ NS_LOG_FUNCTION (this << socket << InetSocketAddress::ConvertFrom (addr));
+
+ Ptr<L3Protocol> ndn = m_node->GetObject<L3Protocol> ();
+ Ptr<TcpFace> face = CreateObject<TcpFace> (m_node, socket, InetSocketAddress::ConvertFrom (addr).GetIpv4 ());
+
+ ndn->AddFace (face);
+ face->SetUp (true);
+
+ socket->SetCloseCallbacks (MakeCallback (&TcpFace::OnTcpConnectionClosed, face),
+ MakeCallback (&TcpFace::OnTcpConnectionClosed, face));
+}
+
+} // namespace ndn
+} // namespace ns3
diff --git a/plugins/ip-faces/ndn-ip-face-stack.h b/plugins/ip-faces/ndn-ip-face-stack.h
new file mode 100644
index 0000000..83cf4cb
--- /dev/null
+++ b/plugins/ip-faces/ndn-ip-face-stack.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ * Alexander Afanasyev
+ *
+ * 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>
+ */
+
+#ifndef NDN_IP_FACE_STACK_H
+#define NDN_IP_FACE_STACK_H
+
+#include "ns3/application.h"
+#include "ns3/socket.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ptr.h"
+#include "ns3/ndn-name.h"
+
+#include <map>
+
+namespace ns3 {
+
+class Packet;
+
+namespace ndn {
+
+class Face;
+
+/**
+ * @ingroup ndn
+ * @brief Application that provides functionality of creating IP-based faces on NDN nodes
+ *
+ * The class implements virtual calls onInterest, onNack, and onContentObject
+ */
+class IpFaceStack: public Object
+{
+public:
+ static TypeId GetTypeId ();
+
+ /**
+ * @brief Default constructor
+ */
+ IpFaceStack ();
+ virtual ~IpFaceStack ();
+
+protected:
+ void
+ NotifyNewAggregate ();
+
+private:
+ void
+ StartServer ();
+
+ bool
+ OnTcpConnectionRequest (Ptr< Socket > sock, const Address &addr);
+
+ void
+ OnTcpConnectionAccept (Ptr< Socket > sock, const Address &addr);
+
+ void
+ OnTcpConnectionClosed (Ptr< Socket > sock);
+
+protected:
+ Ptr<Node> m_node;
+
+ bool m_enableTcp;
+ // bool m_enableUdp;
+
+ Ptr<Socket> m_tcpServer;
+};
+
+} // namespace ndn
+} // namespace ns3
+
+#endif // NDN_IP_FACE_STACK_H
diff --git a/plugins/ip-faces/ndn-ip-faces-helper.cc b/plugins/ip-faces/ndn-ip-faces-helper.cc
new file mode 100644
index 0000000..efd956f
--- /dev/null
+++ b/plugins/ip-faces/ndn-ip-faces-helper.cc
@@ -0,0 +1,86 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ * Alexander Afanasyev
+ *
+ * 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-ip-faces-helper.h"
+#include "ndn-ip-face-stack.h"
+
+#include "ns3/ndn-stack-helper.h"
+#include "ns3/node-container.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ndn-tcp-face.h"
+
+NS_LOG_COMPONENT_DEFINE ("ndn.IpFacesHelper");
+
+using namespace std;
+
+namespace ns3 {
+namespace ndn {
+
+void
+IpFacesHelper::Install (Ptr<Node> node)
+{
+ Ptr<IpFaceStack> stack = CreateObject<IpFaceStack> ();
+ node->AggregateObject (stack);
+}
+
+void
+IpFacesHelper::Install (const NodeContainer &nodes)
+{
+ for (NodeContainer::Iterator node = nodes.Begin ();
+ node != nodes.End ();
+ node ++)
+ {
+ Install (*node);
+ }
+}
+
+void
+IpFacesHelper::InstallAll ()
+{
+ Install (NodeContainer::GetGlobal ());
+}
+
+
+static void
+CreateTcpFaceStep2 (Ptr<Node> node, Ipv4Address address, const std::string &prefix)
+{
+ Ptr<Face> face = TcpFace::CreateOrGetFace (node, address);
+ ndn::StackHelper::AddRoute (node, prefix, face, 1);
+}
+
+static void
+CreateTcpFaceStep1 (Ptr<Node> node, Ipv4Address address, const std::string &prefix)
+{
+ TcpFace::CreateOrGetFace (node, address);
+
+ Simulator::ScheduleWithContext (node->GetId (), Seconds (1.0), CreateTcpFaceStep2, node, address, prefix);
+}
+
+void
+IpFacesHelper::CreateTcpFace (Ptr<Node> node, Ipv4Address address, const std::string &prefix)
+{
+ Simulator::ScheduleWithContext (node->GetId (), Seconds (1.0), CreateTcpFaceStep1, node, address, prefix);
+}
+
+
+} // namespace ndn
+} // namespace ns3
diff --git a/plugins/ip-faces/ndn-ip-faces-helper.h b/plugins/ip-faces/ndn-ip-faces-helper.h
new file mode 100644
index 0000000..3ea8859
--- /dev/null
+++ b/plugins/ip-faces/ndn-ip-faces-helper.h
@@ -0,0 +1,73 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ * Alexander Afanasyev
+ *
+ * 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>
+ */
+
+#ifndef NDN_IP_FACES_HELPER_H
+#define NDN_IP_FACES_HELPER_H
+
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+
+namespace ns3 {
+
+class Node;
+class NodeContainer;
+class Channel;
+
+namespace ndn {
+
+/**
+ * @ingroup ndn
+ * @brief Helper for NDN IP-based face creation
+ */
+class IpFacesHelper
+{
+public:
+ /**
+ * @brief Install IpFaceStack interface on a node
+ * @param node Node to install IpFaceStack interface
+ */
+ void
+ Install (Ptr<Node> node);
+
+ /**
+ * @brief Install IpFaceStack interface on nodes
+ * @param nodes NodeContainer to install IpFaceStack interface
+ */
+ void
+ Install (const NodeContainer &nodes);
+
+ /**
+ * @brief Install IpFaceStack interface on all nodes
+ */
+ void
+ InstallAll ();
+
+ /**
+ * @brief Create TCP face
+ */
+ void
+ CreateTcpFace (Ptr<Node> node, Ipv4Address address, const std::string &prefix);
+};
+
+} // namespace ndn
+} // namespace ns3
+
+#endif // NDN_IP_FACES_HELPER_H
diff --git a/plugins/ip-faces/ndn-tcp-face.cc b/plugins/ip-faces/ndn-tcp-face.cc
new file mode 100644
index 0000000..c1d9321
--- /dev/null
+++ b/plugins/ip-faces/ndn-tcp-face.cc
@@ -0,0 +1,295 @@
+/* -*- 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-tcp-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.TcpFace");
+
+namespace ns3 {
+namespace ndn {
+
+const uint16_t NDN_IP_STACK_PORT = 9695;
+
+TcpFace::FaceMap TcpFace::s_map;
+
+class TcpBoundaryHeader : public Header
+{
+public:
+ static TypeId GetTypeId (void)
+ {
+ static TypeId tid = TypeId ("ns3::ndn::TcpFace::BoundaryHeader")
+ .SetGroupName ("Ndn")
+ .SetParent<Header> ()
+ ;
+ return tid;
+ }
+
+ TcpBoundaryHeader ()
+ : m_length (0)
+ {
+ }
+
+ TcpBoundaryHeader (Ptr<Packet> packet)
+ : m_length (packet->GetSize ())
+ {
+
+ }
+
+ TcpBoundaryHeader (uint32_t length)
+ : m_length (length)
+ {
+ }
+
+ uint32_t
+ GetLength () const
+ {
+ return m_length;
+ }
+
+ virtual TypeId
+ GetInstanceTypeId (void) const
+ {
+ return TcpBoundaryHeader::GetTypeId ();
+ }
+
+ virtual void
+ Print (std::ostream &os) const
+ {
+ os << "[" << m_length << "]";
+ }
+
+ virtual uint32_t
+ GetSerializedSize (void) const
+ {
+ return 4;
+ }
+
+ virtual void
+ Serialize (Buffer::Iterator start) const
+ {
+ start.WriteU32 (m_length);
+ }
+
+ virtual uint32_t
+ Deserialize (Buffer::Iterator start)
+ {
+ m_length = start.ReadU32 ();
+ return 4;
+ }
+
+private:
+ uint32_t m_length;
+};
+
+NS_OBJECT_ENSURE_REGISTERED (TcpFace);
+
+TypeId
+TcpFace::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::ndn::TcpFace")
+ .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
+ */
+TcpFace::TcpFace (Ptr<Node> node, Ptr<Socket> socket, Ipv4Address address)
+ : Face (node)
+ , m_socket (socket)
+ , m_address (address)
+ , m_pendingPacketLength (0)
+{
+ SetMetric (1); // default metric
+}
+
+TcpFace::~TcpFace ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+TcpFace& TcpFace::operator= (const TcpFace &)
+{
+ return *this;
+}
+
+void
+TcpFace::RegisterProtocolHandler (ProtocolHandler handler)
+{
+ NS_LOG_FUNCTION (this);
+
+ Face::RegisterProtocolHandler (handler);
+
+ m_socket->SetRecvCallback (MakeCallback (&TcpFace::ReceiveFromTcp, this));
+}
+
+bool
+TcpFace::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
+TcpFace::ReceiveFromTcp (Ptr< Socket > clientSocket)
+{
+ NS_LOG_FUNCTION (this << clientSocket);
+ TcpBoundaryHeader hdr;
+
+ if (m_pendingPacketLength > 0)
+ {
+ if (clientSocket->GetRxAvailable () >= m_pendingPacketLength)
+ {
+ Ptr<Packet> realPacket = clientSocket->Recv (m_pendingPacketLength, 0);
+ NS_LOG_DEBUG ("+++ Expected " << m_pendingPacketLength << " bytes, got " << realPacket->GetSize () << " bytes");
+ if (realPacket == 0)
+ return;
+
+ Receive (realPacket);
+ }
+ else
+ return; // still not ready
+ }
+
+ m_pendingPacketLength = 0;
+
+ while (clientSocket->GetRxAvailable () >= hdr.GetSerializedSize ())
+ {
+ Ptr<Packet> boundary = clientSocket->Recv (hdr.GetSerializedSize (), 0);
+ if (boundary == 0)
+ return; // no idea why it would happen...
+
+ NS_LOG_DEBUG ("Expected 4 bytes, got " << boundary->GetSize () << " bytes");
+
+ boundary->RemoveHeader (hdr);
+ NS_LOG_DEBUG ("Header specifies length: " << hdr.GetLength ());
+ m_pendingPacketLength = hdr.GetLength ();
+
+ if (clientSocket->GetRxAvailable () >= hdr.GetLength ())
+ {
+ Ptr<Packet> realPacket = clientSocket->Recv (hdr.GetLength (), 0);
+ if (realPacket == 0)
+ {
+ NS_LOG_DEBUG ("Got nothing, but requested at least " << hdr.GetLength ());
+ return;
+ }
+
+ NS_LOG_DEBUG ("Receiving data " << hdr.GetLength () << " bytes, got " << realPacket->GetSize () << " bytes");
+
+ Receive (realPacket);
+ m_pendingPacketLength = 0;
+ }
+ else
+ {
+ return;
+ }
+ }
+}
+
+void
+TcpFace::OnTcpConnectionClosed (Ptr<Socket> socket)
+{
+ NS_LOG_FUNCTION (this << socket);
+ s_map.erase (m_address);
+}
+
+Ipv4Address
+TcpFace::GetAddress () const
+{
+ return m_address;
+}
+
+Ptr<TcpFace>
+TcpFace::GetFaceByAddress (const Ipv4Address &address)
+{
+ FaceMap::iterator i = s_map.find (address);
+ if (i != s_map.end ())
+ return i->second;
+ else
+ return 0;
+}
+
+Ptr<TcpFace>
+TcpFace::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, TcpSocketFactory::GetTypeId ());
+ Ptr<TcpFace> face = CreateObject<TcpFace> (node, socket, address);
+
+ socket->SetConnectCallback (MakeCallback (&TcpFace::OnConnect, face),
+ MakeNullCallback< void, Ptr< Socket > > ());
+ socket->Connect (InetSocketAddress (address, NDN_IP_STACK_PORT));
+
+ s_map.insert (std::make_pair (address, face));
+
+ return face;
+}
+
+void
+TcpFace::OnConnect (Ptr<Socket> socket)
+{
+ NS_LOG_FUNCTION (this << socket);
+
+ Ptr<L3Protocol> ndn = GetNode ()->GetObject<L3Protocol> ();
+
+ ndn->AddFace (this);
+ this->SetUp (true);
+
+ socket->SetCloseCallbacks (MakeCallback (&TcpFace::OnTcpConnectionClosed, this),
+ MakeCallback (&TcpFace::OnTcpConnectionClosed, this));
+}
+
+std::ostream&
+TcpFace::Print (std::ostream& os) const
+{
+ os << "dev=tcp(" << GetId () << ")";
+ return os;
+}
+
+} // namespace ndn
+} // namespace ns3
+
diff --git a/plugins/ip-faces/ndn-tcp-face.h b/plugins/ip-faces/ndn-tcp-face.h
new file mode 100644
index 0000000..6e9763e
--- /dev/null
+++ b/plugins/ip-faces/ndn-tcp-face.h
@@ -0,0 +1,111 @@
+/* -*- 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_TCP_FACE_H
+#define NDN_TCP_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 TCP/IP NDN face
+ *
+ * \see NdnAppFace, NdnNetDeviceFace, NdnIpv4Face, NdnUdpFace
+ */
+class TcpFace : public Face
+{
+public:
+ static TypeId
+ GetTypeId ();
+
+ /**
+ * @brief A singleton method allowing creation and lookup of faces
+ *
+ * All created TCP faces are stored internally in the map, and if the same face is created, it will simply be looked up
+ */
+ static Ptr<TcpFace>
+ CreateOrGetFace (Ptr<Node> node, Ipv4Address address);
+
+ /**
+ * \brief Constructor
+ *
+ * @param node Node associated with the face
+ */
+ TcpFace (Ptr<Node> node, Ptr<Socket> socket, Ipv4Address address);
+ virtual ~TcpFace();
+
+ ////////////////////////////////////////////////////////////////////
+ // methods overloaded from NdnFace
+ virtual void
+ RegisterProtocolHandler (ProtocolHandler handler);
+
+ void
+ OnTcpConnectionClosed (Ptr<Socket> socket);
+
+ Ipv4Address
+ GetAddress () const;
+
+ static Ptr<TcpFace>
+ GetFaceByAddress (const Ipv4Address &addr);
+
+private:
+ void
+ OnConnect (Ptr<Socket> socket);
+
+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:
+ TcpFace (const TcpFace &); ///< \brief Disabled copy constructor
+ TcpFace& operator= (const TcpFace &); ///< \brief Disabled copy operator
+
+ void
+ ReceiveFromTcp (Ptr< Socket > clientSocket);
+
+private:
+ Ptr<Socket> m_socket;
+ Ipv4Address m_address;
+ uint32_t m_pendingPacketLength;
+
+ typedef std::map<Ipv4Address, Ptr<TcpFace> > FaceMap;
+ static FaceMap s_map;
+};
+
+} // namespace ndn
+} // namespace ns3
+
+#endif // NDN_TCP_FACE_H
diff --git a/wscript b/wscript
index f53492a..4cc1ee2 100644
--- a/wscript
+++ b/wscript
@@ -67,7 +67,7 @@
Logs.error ("Please upgrade your distribution or install custom boost libraries (http://ndnsim.net/faq.html#boost-libraries)")
return
- conf.env['NDN_plugins'] = ['topology']
+ conf.env['NDN_plugins'] = ['topology', 'ip-faces']
if Options.options.enable_ndn_plugins:
conf.env['NDN_plugins'] = conf.env['NDN_plugins'] + Options.options.enable_ndn_plugins.split(',')
@@ -181,6 +181,13 @@
module.source.extend (bld.path.ant_glob(['plugins/mobility/*.cc']))
module.full_headers.extend ([p.path_from(bld.path) for p in bld.path.ant_glob(['plugins/mobility/**/*.h'])])
+ if 'ip-faces' in bld.env['NDN_plugins']:
+ headers.source.extend ([
+ "plugins/ip-faces/ndn-ip-faces-helper.h",
+ ])
+ module.source.extend (bld.path.ant_glob(['plugins/ip-faces/*.cc']))
+ module.full_headers.extend ([p.path_from(bld.path) for p in bld.path.ant_glob(['plugins/ip-faces/**/*.h'])])
+
# bld.install_files('${INCLUDEDIR}/%s%s/ns3/ndnSIM' % (wutils.APPNAME, wutils.VERSION), ndnSIM_headers, relative_trick=True)
# bld.install_files('$PREFIX/include', ndnSIM_headers)