switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / Examples / RateStuffer / Mainpage.dox
index 9f51da2..6d034eb 100644 (file)
@@ -1,42 +1,49 @@
 // $Id$
 //
-// Copyright (C) 2007 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-//     Stefan Bund <g0dil@berlios.de>
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
 //
-// This program 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 2 of the License, or
-// (at your option) any later version.
+// The contents of this file are subject to the Fraunhofer FOKUS Public License
+// Version 1.0 (the "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at 
+// http://senf.berlios.de/license.html
 //
-// 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.
+// The Fraunhofer FOKUS Public License Version 1.0 is based on, 
+// but modifies the Mozilla Public License Version 1.1.
+// See the full license text for the amendments.
 //
-// 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.
+// Software distributed under the License is distributed on an "AS IS" basis, 
+// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
+// for the specific language governing rights and limitations under the License.
+//
+// The Original Code is Fraunhofer FOKUS code.
+//
+// The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
+// (registered association), Hansastraße 27 c, 80686 Munich, Germany.
+//
+// Contributor(s):
+//   Stefan Bund <g0dil@berlios.de>
+
 
-/** \mainpage RateStuffer: A simple example featuring the Packet Processing Infrastructure
+using namespace senf::ppi::module;
+
+/** \mainpage Example introducing the Packet Processing Infrastructure
 
     This example application implements a simple PPI application: It will read UDP packets from an
     input port and will forward them to another port at a fixed packet rate. If the input stream
     does not provide enough packets, empty UDP packets will be sent instead.
-    
+
     \section run Running the example
 
     Running the example is a little bit more complicated since we need to provide example UDP
     packets so we can see the application at work. We do this using \c netcat. We open several shell
-    windows and run the folling commands, each in it's own window
+    windows and run the following commands, each in it's own window
 
     The first command listens for incoming UDP packets on port 44345:
     <pre>
     # nc -u -l -p 44345
     </pre>
-    
+
     The next command starts the \c ratestuffer
     <pre>
     # cd .../Examples/RateStuffer
     </pre>
 
     Whenever we send out a packet with CR in the last window we should see it appear in the first
-    one. If we send out packets faster than 1 packet per seccond, they will still only be forwarded
-    with a speed of 1 packet / seccond. If the kernel UDP buffer overflows, packets would be dropped
-    (however, this buffer is prohibitively large) 
+    one. If we send out packets faster than 1 packet per second, they will start to be discarded if
+    more than two packets are in flight.
 
     \image html screenshot.png
 
     \section setup Module setup
 
-    \image html ratestuffer.png
+    \diaimage ratestuffer.dia
 
     Above image depicts the module setup implementing the rate stuffer. A
-    senf::ppi::module::ActiveSocketReader reads the incoming UDP packets and sends them into a
-    senf::ppi::module::PassiveQueue.
+    senf::ppi::module::ActiveSocketSource reads the incoming UDP packets and sends them into a
+    senf::ppi::module::PassiveQueue (via a senf::ppi::module::ThrottleBarrier).
 
-    The \a queue feeds the packets into a senf::ppi::module::PriorityJoin. The CopyPacketGenerator
+    The \a queue feeds the packets into a senf::ppi::module::PriorityJoin. The CloneSource
     \a generator is fed as second input into the \a join to provide the stuffing packets.
 
     The RateFilter \a rateFilter reads packets from it's input at a fixed rate and writes them into
-    the senf::ppi::module::PassiveSocketWriter \a udpWriter. The senf::ppi::module::PriorityJoin
+    the senf::ppi::module::PassiveSocketSink \a udpSink. The senf::ppi::module::PriorityJoin
     ensures that read requests of the RateStuffer's input are always serviced, either from the \a
     queue or, if the \a queue output is throttled, from the \a generator.
 
+    The \a barrier is not strictly necessary. However, it makes the behavior of the RateStuffer
+    predictable in the case where packets need to be dropped. Without the
+    senf::ppi::module::ThrottleBarrier, the packets will be left in the kernel socket queue. Packets
+    will only start to be dropped when that queue fills up. The size of this queue cannot be easily
+    manipulated and it's initial size is immense. So to stop the kernel queue from filling up with
+    increasingly out-of-date packets, we add the \a barrier which will explicitly read and drop
+    excess packets.
+
     \section code Example code
 
     \dontinclude ratestuffer.cc
 
     \skip Custom
     \skip #include
-    \until Setup
+    \until PPI
 
-    We also define some namepsace aliases
+    We also define some namespace aliases
 
     \skip namespace
     \until senf::ppi;
 
-    The RateStuffer application is based on two additional modules.
+    The RateStuffer application is based on one additional application module.
 
     \subsection ratefilter The RateFilter module
 
 
     \until }
 
-    The event is initialized to fire eery \a interval nanoseconds.  The traffic is routed 'accross'
-    the timer which controls the traffic. The timer is then registered to call
-    RateFilter::timeout().
+    The event is initialized to fire every \a interval nanoseconds.  The traffic is routed 'across'
+    the timer which controls the traffic. This routing lets the module automatically handle
+    throttling events. The timer is registered to call RateFilter::timeout().
 
     \until }
 
     and forwarded to \a output.
 
     This is all there is to the RateFilter module. Due to the routing setup, the timer will
-    automatically be disabled if either \a input or \a output become throttled (which is not even
-    needed here).
+    automatically be disabled should either \a input or \a output become throttled. However, in this
+    specific case this should never happen: The \a input is connected (via the \a join) to the
+    senf::ppi::module::CloneSource, which will never throttle. The \a output is connected to a UDP
+    socket which also never throttles.
 
-    \subsection generator The CopyPacketGenerator
+    \subsection ratestuffer The RateStuffer subnet
 
-    We need an additional module to provide the stuffing packets. The CopyPacketGenerator provides
-    an unlimited stream of clone's of a template packet.
+    We decide to implement the RateStuffer as a subnet or collection. This is a simple struct or
+    class which contains all the modules necessary for a specific functionality. The modules are
+    initialized and connected in the class's constructor. External connectors are exported as
+    references to the corresponding module connectors:
 
     \skip class
-    \until };
+    \until rateFilter
 
-    This module is very simple. 
+    First the needed modules are declared. We have
+    - the \a barrier to discard incoming packets sent to fast
+    - the \a queue to receive incoming packets and create throttling notifications
+    - the \a generator to create the stuffing packets
+    - the \a join to combine the input stream from the \a queue with the stuffing packet stream
+    - the \a rateFilter to generate the fixed rate output stream
 
-    \until }
+    \until output
 
-    We save the template packet and initialize the \a output connector to call
-    CopyPacketGenerator::request() whenever a packet is requested.
+    Here we declare the external connectors. The subnetwork exports a single input and output
+    connector. The external connectors are declared as \e references.
 
-    \until }
+    \until output
+
+    The constructor now initializes all the local objects. We pass the template \a packet to the \a
+    generator and set the timing \a interval of the \a rateFilter.
+
+    The \a input and \a output connector references are bound to the corresponding connectors we
+    want to expose: \a input to the \a barrier's \a input and \a output to the \a rateFilter's \a
+    output.
+
+    \until };
 
-    The handler just provides \a packet on each request. This is ok as long as the packets are not
-    changed, in which case we would return <tt>packet->clone()</tt> instead.
+    The constructor body sets up the connections within the subnetwork. Finally, we set the queueing
+    discipline of the \a queue. This Completes the RateStuffer. This subnetwork can now be used like
+    a module.
 
-    \subsection main Connecting the modules
+    \subsection main Application setup
 
     The applications main() method starts out by initializing the socket handles
 
     \until 44345
 
     The \a inputSocket is listening on port 44344 while the \a outputSocket will send packets to
-    port 44345 on localhost. The \a outputSocket uses a ConnectedUDPv4SocketHandle which is
-    compatible with the senf::ppi::module::PassiveSocketWriter module.
+    port 44345 on localhost. The \a outputSocket uses the senf::ConnectedUDPv4SocketProtocol which
+    is compatible with the senf::ppi::module::PassiveSocketSink module.
 
-    \until udpWriter
+    \until udpSink
 
-    Next all the modules are allocated:
+    Here we allocate the components:
 
-    \li \a udpReader to read the packets from \a inputSocket
-    \li \a queue to convert the active output of senf::ppi::module::ActiveSocketReader into a
-        passive output
-    \li \a generator to provide the stuffing in the form of packets containing <tt>"<idle>\n"</tt>
-    \li \a join to combine the two packet streams (from \a udpReader and from \a generator) into a
-        single stream
-    \li \a rateFilter to generate the fixed rate packet stream of 1 packet every 1000000000
-        nanoseconds and
-    \li \a udpWriter to send the packets to \a outputSocket
+    - \a udpSource to read the packets from \a inputSocket
+    - \a stuffer for the real work and
+    - \a udpSink to send the packets to \a outputSocket
 
-    \until udpWriter
+    \until udpSink
 
-    The \ref senf::ppi::connect() calls now setup the necessary connections.
-    
-    \until run
+    The \ref senf::ppi::connect() calls setup the necessary connections.
 
     The module setup is complete, \ref senf::ppi::run() is called to enter the event loop.