-@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global"
+@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global"
-PROJECT_NAME = Examples
-TAGFILES = "$(TOPDIR)/Utils/doc/Utils.tag" "$(TOPDIR)/Socket/doc/Socket.tag" "$(TOPDIR)/Packets/doc/Packets.tag" "$(TOPDIR)/Scheduler/doc/Scheduler.tag" "$(TOPDIR)/doc/overview.tag"
-GENERATE_TAGFILE = doc/Examples.tag
-
-EXAMPLE_PATH = "Sniffer"
\ No newline at end of file
+PROJECT_NAME = Examples
/** \mainpage Examples
- \ref sniffer
-*/
-
-/** \page sniffer Sniffer: A simple example application
-
- \dontinclude Sniffer.cc
-
- The Sniffer application is a simple command line network sniffer like \c tcpdump or \c
- tethereal. The application uses a packet socket to read Ethernet packets from the \c eth0
- interface and dumps the parsed packets out to the standard output.
-
- To try out the example application, check out the library, go to the \c Sniffer
- directory and execute
-
- <pre>
- # scons -u
- # ./sniffer loop
- < Hit Ctrl-C when you've seen enough >
- # ./sniffer scheduler
- < Hit Ctrl-C when you've seen enough >
- </pre>
-
- We will now look at the code which is found in \c Sniffer.cc in the \c Sniffer directory. The
- code starts out by including the necessary headers
-
- \skip // Custom includes
- \until membind
-
- (The additional includes found in the source but not shown here are part of a short-time fix
- which will be removed as soon as possible). The example application now contains a helper
- routine to produce a packet hexdump. We will skip this routine here. The example includes two
- implementations, one using blocking calls and a while loop, the other using the senf::Scheduler
- for asynchronous event notification. They are implemented in \c loop_main() and \c
- scheduler_main(). They will be documented below. For now, we skip these implementations and go
- straight to the \c main() function
-
- \skip int main(
- \until return 1;
- \until }
-
- This routine simply interprets the first command line argument and dispatches to the required
- implementation.
-
- Now lets go back and study each implementation in detail.
-
- \dontinclude Sniffer.cc
-
- \section example_loop A Blocking Implementation
-
- This implementation is found in the \c loop_main function.
-
- \skip loop_main
- \until try
-
- We catch all exceptions in a \c try block. This is good for a deliverable binary. When debugging
- the application, it might be better to let the exception \c abort the execution so you can get a
- backtrace of the exception origin in the debugger.
-
- We now create a packet socket and bind it to the \c eth0 interface. A packet socket is a linux
- specific type of socket which returns ethernet packets directly from the network wire. By
- uncommenting the last line, you may switch the interface into promiscuous mode.
-
- \until //
-
- We will now read packets from the socket forever, that is until the user hits Ctrl-C
-
- \skip while
- \until read
-
- The next step is, to parse the data read from the socket as an Ethernet packet
-
- \until ;
-
- Lets digest this line step by step: We declare a variable named \c packet as a smart pointer to
- an \c EthernetPacket instance. \c ptr is a typedef member of all Packet classes for the
- corresponding smart pointer type. We then initialize this pointer with a call to the static \c
- create member of the \c Packet class. This member takes the type of Packet to parse as a
- template argument. We pass \c EthernetPacket here. The function takes an iterator range as an
- argument, and we pass it the complete packet just read by giving the range \c begin() to \c
- end() of our just read \c data string.
-
- The next step is to write out the packet to the standard output
+ \htmlonly
+ <dl>
+
+ <dt><a href="../../Sniffer/doc/html/index.html">Sniffer</a></dt><dd>Simple packet sniffer
+ reading packets from a packet socket and dumping packet parse to stdout</dd>
- \until \n\n
-
- The \c dump call will write out a complete representation of the parsed packet data. The Packet
- library will \e not try to interpret payload data as long as no exact indication of the payload
- type is available (example: A UDP Payload is not parsed further unless you explicitly tell the
- library, how to parse it). Tools like \c tethereal guess the payload type by checking port
- numbers and the payload data, however this is not advisable for a general purpose packet
- library.
-
- The next line, \c hexdump, will write out the \e last packet component. Packets are managed as a
- chain of headers. The last header is normally a \c DataPacket holding the payload data.
-
- That's it. We finish of by catching the exception and giving as much detail as possible if an
- exception is caught
-
- \until ;
- \until }
- \until }
-
- The \c prettyName function from the \c Utils library is used, to get a nice, printable
- representation of the \e dynamic type of the exception instance. It is an interface to the g++
- demangler. This is necessary since the \c name member of the C++ \c type_info instance is a
- mangled name in \c g++.
-
- That's it for the simple blocking implementation.
-
- \section example_scheduler Using the Scheduler
-
- However, we have another one which uses the Scheduler. We do this as it will be most of the
- time: We define a class which manages reading the packets and dumping them out.
-
- \until }
-
- The class constructor binds the socket defined as a data member to the correct interface.
-
- \until add
-
- The public \c run() member is called to run the sniffer. It first adds the socket to the
- Scheduler. The \c add() call takes two Arguments, the socket to bind to (which can be a lot of
- things and must not necessarily be a socket instance) and callback to call, whenever there is an
- event on that socket. A third argument may be specified to restrict the events, on which the
- function is called, here we have left out this argument which defaults to
- senf::Scheduler::EV_ALL.
-
- The callback is specified as a <a
- href="http://www.boost.org/doc/html/function.html">Boost.Function</a> object. We use the \c
- senf::membind helper from the Utils library to build such a function object. This helper takes
- an arbitrary class member and binds it to a specific instance.
-
- \until }
-
- Calling the Schedulers \c process() method will start the event loop. This call does not return
- (ok, it does return in special cases if \c senf::Scheduler::terminate() is called which does not
- apply here).
-
- \until {
-
- The \c dumpPacket() member is called by the scheduler whenever an event on the socket is
- encountered. The scheduler always passes two arguments: The socket and an event id which
- identifies the type of event which triggered the call.
-
- \until };
-
- The body is absolutely identical to the body of the \c while loop of the blocking
- implementation. However, the scheduler guarantees, that a read on the socket will not block if
- the socket is triggered to be readable (even if the socket is not set to non-blocking mode).
-
- We now only need to provide the \c scheduler_main() function to run this code
-
- \until 0;
- \until }
-
- This function is straight forward. The exception handling is the same as in \c loop_main(). The
- code then just creates a \c Sniffer instance and calls it's \c run() member.
-
- \see \ref components \n
- \ref build \n
- <a href="../../../Socket/doc/html/index.html"><b>libSocket API reference</b></a> \n
- <a href="../../../Packets/doc/html/index.html"><b>libPackets API reference</b></a> \n
- <a href="../../../Utils/doc/html/index.html"><b>libUtils API reference</b></a>
- */
+ <dt><a href="../../RateStuffer/doc/html/index.html">RateStuffer</a></dt><dd>Example application
+ showing of the PPI infrastructure</dd>
+ </dl>
+ \endhtmlonly
+*/
\f
// Local Variables:
--- /dev/null
+@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global"
+
+PROJECT_NAME = RateStuffer
+TAGFILES = "$(TOPDIR)/Utils/doc/Utils.tag" "$(TOPDIR)/Socket/doc/Socket.tag" "$(TOPDIR)/Packets/doc/Packets.tag" "$(TOPDIR)/Scheduler/doc/Scheduler.tag" "$(TOPDIR)/PPI/doc/PPI.tag"
+ALPHABETICAL_INDEX = NO
+
+EXAMPLE_PATH = "."
\ No newline at end of file
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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.
+//
+// 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.
+
+/** \mainpage RateStuffer: A simple example featuring 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
+
+ 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
+ # scons -u
+ # ./ratestuffer
+ </pre>
+
+ We should now see '<idle>' messages arriving in the first window once per second. We now can
+ start another \c netcat to send packets to the input port.
+
+ <pre>
+ # nc -u localhost 44344
+ < type any text here >
+ </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)
+
+ \image html screenshot.png
+
+ \section setup Module setup
+
+ \image html ratestuffer.png
+
+ 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.
+
+ The \a queue feeds the packets into a senf::ppi::module::PriorityJoin. The CopyPacketGenerator
+ \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
+ 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.
+
+ \section code Example code
+
+ \dontinclude ratestuffer.cc
+
+ The code starts out including the necessary header files
+
+ \skip Custom
+ \skip #include
+ \until Setup
+
+ We also define some namepsace aliases
+
+ \skip namespace
+ \until senf::ppi;
+
+ The RateStuffer application is based on two additional modules.
+
+ \subsection ratefilter The RateFilter module
+
+ The RateFilter module simply forwards packets at a fixed rate.
+
+ \skip class
+ \until };
+
+ Both connectors of the RateFilter module are active. The module is driven by a
+ senf::ppi::IntervalTimer.
+
+ \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().
+
+ \until }
+
+ The event handler is quite simple: Every \a interval nanoseconds a packet is read from \a input
+ 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).
+
+ \subsection generator The CopyPacketGenerator
+
+ We need an additional module to provide the stuffing packets. The CopyPacketGenerator provides
+ an unlimited stream of clone's of a template packet.
+
+ \skip class
+ \until };
+
+ This module is very simple.
+
+ \until }
+
+ We save the template packet and initialize the \a output connector to call
+ CopyPacketGenerator::request() whenever a packet is requested.
+
+ \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.
+
+ \subsection main Connecting the modules
+
+ The applications main() method starts out by initializing the socket handles
+
+ \skip main
+ \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.
+
+ \until udpWriter
+
+ Next all the modules are allocated:
+
+ \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
+
+ \until udpWriter
+
+ The \ref senf::ppi::connect() calls now setup the necessary connections.
+
+ \until run
+
+ The module setup is complete, \ref senf::ppi::run() is called to enter the event loop.
+
+ \until }
+ */
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u doc"
+// mode: flyspell
+// mode: auto-fill
+// End:
SENFSCons.Binary( env, 'ratestuffer', SENFSCons.GlobSources(),
LIBS = [ 'PPI', 'Scheduler', 'Packets', 'Socket', 'Utils' ] );
+
+SENFSCons.Doxygen(env, extra_sources=[
+ env.Dia2Png('ratestuffer.dia')
+])
namespace connector = senf::ppi::connector;
namespace ppi = senf::ppi;
-namespace {
-
- class RateFilter
- : public module::Module
- {
- SENF_PPI_MODULE(RateFilter);
- public:
-
- connector::ActiveInput input;
- connector::ActiveOutput output;
-
- RateFilter(senf::ClockService::clock_type interval) : timer(interval) {
- route(input,output);
- route(input,timer);
- registerEvent(&RateFilter::timeout, timer);
- }
-
- private:
- void timeout() {
- output(input());
- }
-
- ppi::IntervalTimer timer;
- };
-
- class CopyPacketGenerator
- : public module::Module
- {
- SENF_PPI_MODULE(CopyPacketGenerator);
- public:
-
- connector::PassiveOutput output;
-
- CopyPacketGenerator(senf::Packet p) : packet(p) {
- noroute(output);
- output.onRequest(&CopyPacketGenerator::request);
- }
-
- private:
- void request() {
- output(packet);
- }
-
- senf::Packet packet;
- };
+// ////////////////////////////////////////////////////////////////////////
+// RateFilter
+
+class RateFilter
+ : public module::Module
+{
+ SENF_PPI_MODULE(RateFilter);
+public:
+
+ connector::ActiveInput input;
+ connector::ActiveOutput output;
+
+ RateFilter(senf::ClockService::clock_type interval);
+
+private:
+ void timeout();
+
+ ppi::IntervalTimer timer;
+};
+
+RateFilter::RateFilter(senf::ClockService::clock_type interval)
+ : timer(interval)
+{
+ route(input,timer);
+ route(timer,output);
+ registerEvent(&RateFilter::timeout, timer);
+}
+
+void RateFilter::timeout()
+{
+ output(input());
}
+// ////////////////////////////////////////////////////////////////////////
+// CopyPacketGenerator
+
+class CopyPacketGenerator
+ : public module::Module
+{
+ SENF_PPI_MODULE(CopyPacketGenerator);
+public:
+
+ connector::PassiveOutput output;
+
+ CopyPacketGenerator(senf::Packet p);
+
+private:
+ void request();
+
+ senf::Packet packet;
+};
+
+CopyPacketGenerator::CopyPacketGenerator(senf::Packet p)
+ : packet(p)
+{
+ noroute(output);
+ output.onRequest(&CopyPacketGenerator::request);
+}
+
+void CopyPacketGenerator::request()
+{
+ output(packet);
+}
+
+// ////////////////////////////////////////////////////////////////////////
+// ////////////////////////////////////////////////////////////////////////
+
// Module setup:
//
// 'O' = active connector
--- /dev/null
+@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global"
+
+PROJECT_NAME = Sniffer
+TAGFILES = "$(TOPDIR)/Utils/doc/Utils.tag" "$(TOPDIR)/Socket/doc/Socket.tag" "$(TOPDIR)/Packets/doc/Packets.tag" "$(TOPDIR)/Scheduler/doc/Scheduler.tag"
+
+EXAMPLE_PATH = "."
\ No newline at end of file
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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.
+//
+// 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.
+
+/** \mainpage Sniffer: A simple example application
+
+ \dontinclude Sniffer.cc
+
+ The Sniffer application is a simple command line network sniffer like \c tcpdump or \c
+ tethereal. The application uses a packet socket to read Ethernet packets from the \c eth0
+ interface and dumps the parsed packets out to the standard output.
+
+ To try out the example application, check out the library, go to the \c Sniffer
+ directory and execute
+
+ <pre>
+ # scons -u
+ # ./sniffer loop
+ < Hit Ctrl-C when you've seen enough >
+ # ./sniffer scheduler
+ < Hit Ctrl-C when you've seen enough >
+ </pre>
+
+ We will now look at the code which is found in \c Sniffer.cc in the \c Sniffer directory. The
+ code starts out by including the necessary headers
+
+ \skip // Custom includes
+ \until membind
+
+ (The additional includes found in the source but not shown here are part of a short-time fix
+ which will be removed as soon as possible). The example application now contains a helper
+ routine to produce a packet hexdump. We will skip this routine here. The example includes two
+ implementations, one using blocking calls and a while loop, the other using the senf::Scheduler
+ for asynchronous event notification. They are implemented in \c loop_main() and \c
+ scheduler_main(). They will be documented below. For now, we skip these implementations and go
+ straight to the \c main() function
+
+ \skip int main(
+ \until return 1;
+ \until }
+
+ This routine simply interprets the first command line argument and dispatches to the required
+ implementation.
+
+ Now lets go back and study each implementation in detail.
+
+ \dontinclude Sniffer.cc
+
+ \section example_loop A Blocking Implementation
+
+ This implementation is found in the \c loop_main function.
+
+ \skip loop_main
+ \until try
+
+ We catch all exceptions in a \c try block. This is good for a deliverable binary. When debugging
+ the application, it might be better to let the exception \c abort the execution so you can get a
+ backtrace of the exception origin in the debugger.
+
+ We now create a packet socket and bind it to the \c eth0 interface. A packet socket is a linux
+ specific type of socket which returns ethernet packets directly from the network wire. By
+ uncommenting the last line, you may switch the interface into promiscuous mode.
+
+ \until //
+
+ We will now read packets from the socket forever, that is until the user hits Ctrl-C
+
+ \skip while
+ \until read
+
+ The next step is, to parse the data read from the socket as an Ethernet packet
+
+ \until ;
+
+ Lets digest this line step by step: We declare a variable named \c packet as a smart pointer to
+ an \c EthernetPacket instance. \c ptr is a typedef member of all Packet classes for the
+ corresponding smart pointer type. We then initialize this pointer with a call to the static \c
+ create member of the \c Packet class. This member takes the type of Packet to parse as a
+ template argument. We pass \c EthernetPacket here. The function takes an iterator range as an
+ argument, and we pass it the complete packet just read by giving the range \c begin() to \c
+ end() of our just read \c data string.
+
+ The next step is to write out the packet to the standard output
+
+ \until \n\n
+
+ The \c dump call will write out a complete representation of the parsed packet data. The Packet
+ library will \e not try to interpret payload data as long as no exact indication of the payload
+ type is available (example: A UDP Payload is not parsed further unless you explicitly tell the
+ library, how to parse it). Tools like \c tethereal guess the payload type by checking port
+ numbers and the payload data, however this is not advisable for a general purpose packet
+ library.
+
+ The next line, \c hexdump, will write out the \e last packet component. Packets are managed as a
+ chain of headers. The last header is normally a \c DataPacket holding the payload data.
+
+ That's it. We finish of by catching the exception and giving as much detail as possible if an
+ exception is caught
+
+ \until ;
+ \until }
+ \until }
+
+ The \c prettyName function from the \c Utils library is used, to get a nice, printable
+ representation of the \e dynamic type of the exception instance. It is an interface to the g++
+ demangler. This is necessary since the \c name member of the C++ \c type_info instance is a
+ mangled name in \c g++.
+
+ That's it for the simple blocking implementation.
+
+ \section example_scheduler Using the Scheduler
+
+ However, we have another one which uses the Scheduler. We do this as it will be most of the
+ time: We define a class which manages reading the packets and dumping them out.
+
+ \until }
+
+ The class constructor binds the socket defined as a data member to the correct interface.
+
+ \until add
+
+ The public \c run() member is called to run the sniffer. It first adds the socket to the
+ Scheduler. The \c add() call takes two Arguments, the socket to bind to (which can be a lot of
+ things and must not necessarily be a socket instance) and callback to call, whenever there is an
+ event on that socket. A third argument may be specified to restrict the events, on which the
+ function is called, here we have left out this argument which defaults to
+ senf::Scheduler::EV_ALL.
+
+ The callback is specified as a <a
+ href="http://www.boost.org/doc/html/function.html">Boost.Function</a> object. We use the \c
+ senf::membind helper from the Utils library to build such a function object. This helper takes
+ an arbitrary class member and binds it to a specific instance.
+
+ \until }
+
+ Calling the Schedulers \c process() method will start the event loop. This call does not return
+ (ok, it does return in special cases if \c senf::Scheduler::terminate() is called which does not
+ apply here).
+
+ \until {
+
+ The \c dumpPacket() member is called by the scheduler whenever an event on the socket is
+ encountered. The scheduler always passes two arguments: The socket and an event id which
+ identifies the type of event which triggered the call.
+
+ \until };
+
+ The body is absolutely identical to the body of the \c while loop of the blocking
+ implementation. However, the scheduler guarantees, that a read on the socket will not block if
+ the socket is triggered to be readable (even if the socket is not set to non-blocking mode).
+
+ We now only need to provide the \c scheduler_main() function to run this code
+
+ \until 0;
+ \until }
+
+ This function is straight forward. The exception handling is the same as in \c loop_main(). The
+ code then just creates a \c Sniffer instance and calls it's \c run() member.
+
+ \see \ref components \n
+ \ref build \n
+ <a href="../../../Socket/doc/html/index.html"><b>libSocket API reference</b></a> \n
+ <a href="../../../Packets/doc/html/index.html"><b>libPackets API reference</b></a> \n
+ <a href="../../../Utils/doc/html/index.html"><b>libUtils API reference</b></a>
+ */
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// mode: flyspell
+// mode: auto-fill
+// End:
SENFSCons.Binary(env, 'sniffer', SENFSCons.GlobSources(),
LIBS = [ 'Scheduler', 'Packets', 'Socket', 'Utils' ],
OBJECTS = [ '#/Packets/DefaultBundle/DefaultBundle.o' ]);
+
+SENFSCons.Doxygen(env)
RECURSIVE = Yes
SHOW_DIRECTORIES = Yes
-TAGFILES = "$(TOPDIR)/Packets/doc/Packets.tag" "$(TOPDIR)/Socket/doc/Socket.tag"
+TAGFILES = "$(TOPDIR)/Packets/doc/Packets.tag" "$(TOPDIR)/Socket/doc/Socket.tag" "$(TOPDIR)/Utils/doc/Utils.tag" "$(TOPDIR)/Scheduler/doc/Scheduler.tag"
+GENERATE_TAGFILE = "doc/PPI.tag"
void destroy();
+#ifndef DOXYGEN
virtual void macro_SENF_PPI_MODULE_missing() = 0;
+#endif
private:
virtual void init();
namespace senf {
namespace ppi {
-
+
+#ifndef DOXYGEN
+
void connect(connector::ActiveOutput & source, connector::PassiveInput & target);
void connect(connector::PassiveOutput & source, connector::ActiveInput & target);
void connect(M1 & source, M2 & target,
typename boost::enable_if< boost::is_base_of<module::Module, M1> >::type * = 0,
typename boost::enable_if< boost::is_base_of<module::Module, M2> >::type * = 0);
-
+
+#else
+
+ template <class Source, class Target>
+ void connect(Source & source, Target & target);
+
+#endif
+
void run();
void init();
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
-PREDEFINED = DOXYGEN
+PREDEFINED = DOXYGEN SENF_PPI_MODULE(x)=
EXPAND_AS_DEFINED = prefix_
HTML_HEADER = "$(TOPDIR)/doclib/doxy-header.html"
# Naja ... etwas rumgehackt aber was solls ...
global EXTRA_MODULES
mods = {}
- ix = len(env.Dir('#').abspath)+1
- ex = dict((env.Dir(p).abspath,True) for n,p in EXTRA_MODULES)
+ pathbase = len(env.Dir('#').abspath)+1
for module in env.Alias('all_docs')[0].sources:
if module.name != 'html.stamp' : continue
- if not ex.get(module.dir.abspath):
- mods[module.dir.dir.dir.abspath] = [ module.dir.dir.dir.name, module.dir.abspath[ix:], 0 ]
+ mods[module.dir.dir.dir.abspath] = [ module.dir.dir.dir.name,
+ module.dir.abspath[pathbase:],
+ 0 ]
+
rv = []
keys = mods.keys()
keys.sort()
for mod in keys:
i = 0
while i < len(rv):
- if mod.startswith(rv[i] + '/'):
+ if len(rv[i]) > pathbase and mod.startswith(rv[i] + '/'):
level = mods[rv[i]][2] + 1
i += 1
while i < len(rv) and mods[rv[i]][2] >= level:
i += 1
if i == len(rv):
rv.append(mod)
- return [ (name, env.Dir(path).abspath[ix:], 0) for name,path in EXTRA_MODULES
- ] + [ ( (((not mods[mod][2]) and 'lib') or '') + mods[mod][0],
- mods[mod][1],
- mods[mod][2])
- for mod in rv ]
+
+ for mod in keys:
+ if mods[mod][2] == 0:
+ mods[mod][0] = 'lib' + mods[mod][0]
+
+ n = 0
+ for name,path in EXTRA_MODULES:
+ path = env.Dir(path).dir.dir.abspath
+ i = 0
+ while i < len(rv):
+ if rv[i] == path:
+ mods[rv[i]][0] = name
+ m = 1
+ while i+m < len(rv) and mods[rv[i+m]][2] > mods[rv[i]][2]:
+ m += 1
+ rv[n:n] = rv[i:i+m]
+ rv[i+m:i+2*m] = []
+ i += m
+ n += m
+ else:
+ i += 1
+
+ return ( tuple(mods[mod]) for mod in rv )
def indices():
ix = len(env.Dir('#').abspath)+1