docs: Add guide on how to simulate real apps in ndnSIM

Change-Id: I3694a8791b9540fc1b926a83ff55421b47e0f2a2
diff --git a/docs/Doxyfile b/docs/Doxyfile
index dfe0463..b8d1823 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -764,7 +764,7 @@
                          doxygen.hpp
 
 # For example:
-# ../../../build/utils/ns3-dev-print-introspected-doxygen-debug --log --group Ndn > introspected-doxygen.hpp
+# ../../../build/utils/ns3-dev-print-introspected-doxygen-debug --group=Ndn > introspected-doxygen.hpp
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/docs/log-sources.hpp b/docs/log-sources.hpp
deleted file mode 100644
index e69de29..0000000
--- a/docs/log-sources.hpp
+++ /dev/null
diff --git a/docs/source/guide-to-simulate-real-apps.rst b/docs/source/guide-to-simulate-real-apps.rst
index ab73f8d..5d7b8ac 100644
--- a/docs/source/guide-to-simulate-real-apps.rst
+++ b/docs/source/guide-to-simulate-real-apps.rst
@@ -1,4 +1,216 @@
-Simulating real applications
-============================
+Simulating real NDN applications
+================================
 
-TODO
+The version of `ndn-cxx library <http://named-data.net/doc/ndn-cxx/>`__ bundled with ndnSIM includes
+a modified version of :ndnsim:`ndn::Face` to directly send and receive Interest and Data packets to
+and from the simulated instances of NFD.  With this modification, ndnSIM enables support to simulate
+real NDN applications written against the ndn-cxx, if they satisfy requirements listed in this guide
+or can be modified to satisfy these requirements.
+
+
+Requirements
+++++++++++++
+
+#. **Source code of the application must be available**
+
+   The application (parts of the application) needs to be compiled against the ndnSIM version of
+   ndn-cxx library.
+
+#. **Source code should separate** ``main`` **function from the functional components of the
+   application that will be simulated**
+
+   The entry point to the application (its functional component) will be NS-3 application class,
+   which should be able to create and destroy an instance of the simulated component when scheduled
+   by the scenario.
+
+#. **The application should not use global variables, if they define a state for the application
+   instance**
+
+   ndnSIM should be able to create multiple different instances of the application, e.g., for each
+   simulated node.
+
+   Exception to this requirement is :ndnsim:`ndn::Scheduler <ndn::util::scheduler::Scheduler>`: its
+   implementation has been rewired to use NS-3's scheduling routines.
+
+#. **The application MUST NOT contain any GUI or command-line terminal interactions**
+
+#. **The application SHOULD NOT use disk operations, unless application instances access unique
+   parts of the file system**
+
+   In the simulated environment, all application instances will be accessing the same local file
+   system, which can result in undefined behavior if not properly handled.
+
+#. **The application MUST use a subset of** :ndnsim:`ndn::Face` **API:**
+
+   - If the application create :ndnsim:`ndn::Face`, it MUST BE created either with a default
+     constructor or constructor that accepts a single ``boost::asio::io_service`` parameter.
+
+     .. code-block:: c++
+
+         // Supported
+         ndn::Face face1();
+         ndn::Face face2(ioService);
+
+         // Not supported in ndnSIM
+         ndn::Face face4(host_name, port_number)
+         ndn::Face face3(transport);
+         // and others
+
+   - :ndnsim:`ndn::Face::getIoService()` should be used only to obtain a reference to
+     ``boost::asio::io_service``.  **Application MUST NOT use any methods of**
+     ``boost::asio::io_service``, **otherwise the simulation will crash.**
+
+     .. code-block:: c++
+
+         ndn::Face face;
+         ...
+         // Supported (the rewired Scheduler implementation does not access io_service methods)
+         Scheduler scheduler(face.getIoService());
+
+         // Not supported in ndnSIM and will result in crash
+         face.getIoService().stop();
+
+
+   - Application should avoid use of :ndnsim:`Face::processEvents` or use it with caution
+
+     In real applications, processEvents blocks until some data is received or the timeout callback
+     is called. In this case, any variables created before calling this method will still exist
+     after the method returns. However, in ndnSIM, such an assumption cannot be made, since the
+     scope of a variable is local.
+
+    .. code-block:: c++
+
+        void
+        foo
+        {
+          ndn::Face face;
+          face.expressInterest(...);
+          face.setInterestFilter(...);
+
+          // ndnSIM version of processEvents will not block!
+          face.processEvents();
+        }
+        // after existing foo scope, face variable is deallocated and all scheduled operations
+        // will be canceled
+
+#. **Application (simulated component) MUST NOT create instances of** ``boost::asio::io_service``
+   **and use their methods**
+
+   ``boost::asio::io_service`` is inherently incompatible with NS-3, as both are providing mechanisms
+   for asynchronous event processing.
+
+#. We also recommend that functional part of the application accepts reference to the
+   :ndnsim:`KeyChain` instance, instead of creating instance itself.
+
+   When simulating non-security aspects of the application, in simulation scenario it will be
+   possible to use a dummy implementation of the :ndnsim:`KeyChain` that does not perform crypto
+   operations, but signs Data and Interests with fake signatures.
+
+   For example, this can be achieved by enabling the constructor of the real application to accept a reference
+   to the :ndnsim:`KeyChain`:
+
+    .. code-block:: c++
+
+        // Real applications should accept a reference to the KeyChain instance
+        RealApp::RealApp(KeyChain& keyChain)
+          : m_keyChain(keyChain)
+        {
+        }
+
+
+How to simulate real applications using ndnSIM
+++++++++++++++++++++++++++++++++++++++++++++++
+
+To simulate a real application, the simulation scenario should contain a class derived from
+``ns3::Application``.  This class needs to create an instance of the :ndnsim:`ndn::Face` and/or real
+application in the overloaded ``StartApplication`` method.  This class also need to ensure that the
+created instance is not deallocated until ``StopApplication`` method is called.
+
+For example, if the functional class of the real application looks like:
+
+.. literalinclude:: ../../examples/ndn-cxx-simple/real-app.hpp
+    :language: c++
+    :linenos:
+    :lines: 23-75
+
+
+The corresponding NS-3 "entry point" application class can be like this:
+
+.. literalinclude:: ../../examples/ndn-cxx-simple/real-app-starter.hpp
+    :language: c++
+    :linenos:
+    :lines: 25-65
+
+.. note::
+   There is a requirement that :ndnsim:`ndn::Face` MUST BE created within the context of a specific
+   ``ns3::Node``.  In simple words this means that :ndnsim:`ndn::Face` constructor must be called
+   somewhere within the overloaded ``StartApplication`` method.
+
+   Attempt to create a :ndnsim:`ndn::Face` outside ``ns3::Node`` (e.g., if the example included
+   member variable ``Face m_face`` in ``RealAppStarter`` class) will result in simulation crash.
+
+The final step is to actually write a simulation scenario that defines network topology, routing
+information between nodes, on which nodes the application should be installed and when it should be
+started and stopped.
+
+For the trivial example, let us assume that we have only one simulation node and we want to start
+the application at time moment 6.5 seconds.  This scenario can look like:
+
+.. literalinclude:: ../../examples/ndn-cxx-simple.cpp
+    :language: c++
+    :linenos:
+    :lines: 20-
+
+
+Example of a real application simulation
+++++++++++++++++++++++++++++++++++++++++
+
+To demonstrate functionality of ndnSIM in a more complex and realistic case, we will use the NDN
+ping application included as part of `NDN Essential Tools`_.
+
+For this example, we used a `scenario template repository`_ as a base to write simulation-specific
+extensions and define scenarios, and the `final version of the scenario is available in GitHub
+<https://github.com/named-data-ndnSIM/scenario-ndn-ping>`__.
+
+The following lists steps we did to simulate `ndnping` and `ndnpingserver` apps on a simple
+three-node topology:
+
+- forked `scenario template repository`_
+
+- imported the latest version of `NDN Essential Tools`_ source code as a git submodule
+
+- updated the build script (``wscript``) to compile the source code of ``ndnping`` and
+  ``ndnpingserver`` (with the exception of compilation units that contain ``main`` function) against
+  ndnSIM
+
+  `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/74269dc4de6afe2b6e13a0bcc8c0faac350d8fa3>`__
+
+- defined ``PingClient`` and ``PingServer`` classes to hold state of application instances
+
+  `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/4f087a16e3171af38c05b53c6cfd9e752e7cda72>`__
+
+- defined ``PingClientApp`` and ``PingServerApp`` NS-3 applications, that create and destroy
+  instances of ``PingClient`` and ``PingServer`` per NS-3 logic.
+
+  `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/2b317860f55b71b34ffdccac31444246d9b804fe>`__
+
+- defined a simple scenario that creates a three node topology, installs NDN stacks, and installs
+  ``PingClientApp`` and ``PingServerApp`` applications on different simulation nodes.
+
+  `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/2b317860f55b71b34ffdccac31444246d9b804fe>`__
+
+After all these steps, the repository is ready to run the simulation (see `README.md
+<https://github.com/named-data-ndnSIM/scenario-ndn-ping/blob/master/README.md>`__ for more details).
+
+
+.. note::
+   The listed steps did not include any modification of `NDN Essential Tools`_ source code.
+   However, this was not the case when we initially attempted to run the simulation, as the source
+   code was violating a few requirements of this guide.  `The changes that we made
+   <https://github.com/named-data/ndn-tools/commit/1e7a7b20c93014e86639e3d07f357c95b48b34ac>`__ are
+   an example of how to adapt the source code to be compatible with ndnSIM simulations.
+
+
+.. _NDN Essential Tools: http://github.com/named-data/ndn-tools
+
+.. _scenario template repository: https://github.com/named-data-ndnSIM/scenario-template
diff --git a/examples/ndn-cxx-simple.cpp b/examples/ndn-cxx-simple.cpp
new file mode 100644
index 0000000..22497e0
--- /dev/null
+++ b/examples/ndn-cxx-simple.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2011-2015  Regents of the University of California.
+ *
+ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
+ * contributors.
+ *
+ * ndnSIM is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * ndnSIM 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
+ * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "ndn-cxx-simple/real-app.hpp"
+#include "ndn-cxx-simple/real-app-starter.hpp"
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/ndnSIM-module.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED(RealAppStarter);
+
+int
+main(int argc, char* argv[])
+{
+  CommandLine cmd;
+  cmd.Parse(argc, argv);
+
+  Ptr<Node> node = CreateObject<Node>();
+
+  ndn::StackHelper ndnHelper;
+  ndnHelper.Install(node);
+
+  ndn::AppHelper appHelper("RealAppStarter");
+  appHelper.Install(node)
+    .Start(Seconds(6.5));
+
+  Simulator::Stop(Seconds(20.0));
+
+  Simulator::Run();
+  Simulator::Destroy();
+
+  return 0;
+}
+
+} // namespace ns3
+
+int
+main(int argc, char* argv[])
+{
+  return ns3::main(argc, argv);
+}
diff --git a/examples/ndn-cxx-simple/real-app-starter.hpp b/examples/ndn-cxx-simple/real-app-starter.hpp
new file mode 100644
index 0000000..00119e5
--- /dev/null
+++ b/examples/ndn-cxx-simple/real-app-starter.hpp
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2011-2015  Regents of the University of California.
+ *
+ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
+ * contributors.
+ *
+ * ndnSIM is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * ndnSIM 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
+ * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NDNSIM_EXAMPLES_NDN_CXX_SIMPLE_REAL_APP_STARTER_HPP
+#define NDNSIM_EXAMPLES_NDN_CXX_SIMPLE_REAL_APP_STARTER_HPP
+
+#include "real-app.hpp"
+
+#include "ns3/ndnSIM/helper/ndn-stack-helper.hpp"
+#include "ns3/application.h"
+
+namespace ns3 {
+
+// Class inheriting from ns3::Application
+class RealAppStarter : public Application
+{
+public:
+  static TypeId
+  GetTypeId()
+  {
+    static TypeId tid = TypeId("RealAppStarter")
+      .SetParent<Application>()
+      .AddConstructor<RealAppStarter>();
+
+    return tid;
+  }
+
+protected:
+  // inherited from Application base class.
+  virtual void
+  StartApplication()
+  {
+    // Create an instance of the app, and passing the dummy version of KeyChain (no real signing)
+    m_instance.reset(new app::RealApp(ndn::StackHelper::getKeyChain()));
+    m_instance->run(); // can be omitted
+  }
+
+  virtual void
+  StopApplication()
+  {
+    // Stop and destroy the instance of the app
+    m_instance.reset();
+  }
+
+private:
+  std::unique_ptr<app::RealApp> m_instance;
+};
+
+} // namespace ns3
+
+#endif // NDNSIM_EXAMPLES_NDN_CXX_SIMPLE_REAL_APP_STARTER_HPP
diff --git a/examples/ndn-cxx-simple/real-app.hpp b/examples/ndn-cxx-simple/real-app.hpp
new file mode 100644
index 0000000..0aa2f38
--- /dev/null
+++ b/examples/ndn-cxx-simple/real-app.hpp
@@ -0,0 +1,77 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2011-2015  Regents of the University of California.
+ *
+ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
+ * contributors.
+ *
+ * ndnSIM is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * ndnSIM 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
+ * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NDNSIM_EXAMPLES_NDN_CXX_SIMPLE_REAL_APP_HPP
+#define NDNSIM_EXAMPLES_NDN_CXX_SIMPLE_REAL_APP_HPP
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/interest.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/util/scheduler.hpp>
+
+#include <iostream>
+
+namespace app {
+
+class RealApp
+{
+public:
+  RealApp(ndn::KeyChain& keyChain)
+    : m_keyChain(keyChain)
+    , m_faceProducer(m_faceConsumer.getIoService())
+    , m_scheduler(m_faceConsumer.getIoService())
+  {
+    // register prefix and set interest filter on producer face
+    m_faceProducer.setInterestFilter("/hello", std::bind(&RealApp::respondToAnyInterest, this, _2),
+                                     std::bind([]{}), std::bind([]{}));
+
+    // use scheduler to send interest later on consumer face
+    m_scheduler.scheduleEvent(ndn::time::seconds(2), [this] {
+        m_faceConsumer.expressInterest(ndn::Interest("/hello/world"),
+                                       std::bind([] { std::cout << "Hello!" << std::endl; }),
+                                       std::bind([] { std::cout << "Bye!.." << std::endl; }));
+      });
+  }
+
+  void
+  run()
+  {
+    m_faceConsumer.processEvents(); // ok (will not block and do nothing)
+    // m_faceConsumer.getIoService().run(); // will crash
+  }
+
+private:
+  void
+  respondToAnyInterest(const ndn::Interest& interest)
+  {
+    auto data = std::make_shared<ndn::Data>(interest.getName());
+    m_keyChain.sign(*data);
+    m_faceProducer.put(*data);
+  }
+
+private:
+  ndn::KeyChain& m_keyChain;
+  ndn::Face m_faceConsumer;
+  ndn::Face m_faceProducer;
+  ndn::Scheduler m_scheduler;
+};
+
+} // namespace app
+
+#endif // NDNSIM_EXAMPLES_NDN_CXX_SIMPLE_REAL_APP_HPP