From: g0dil Date: Mon, 20 Aug 2007 23:06:51 +0000 (+0000) Subject: Reorganize examples X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=77a726fdfa20680c691ba528fdad979422ef829c;p=senf.git Reorganize examples Examples/RateStuffer: documentation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@402 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Examples/Doxyfile b/Examples/Doxyfile index 1cfe419..48505f2 100644 --- a/Examples/Doxyfile +++ b/Examples/Doxyfile @@ -1,7 +1,3 @@ -@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 diff --git a/Examples/Mainpage.dox b/Examples/Mainpage.dox index f8ef7eb..9557a71 100644 --- a/Examples/Mainpage.dox +++ b/Examples/Mainpage.dox @@ -1,170 +1,17 @@ /** \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 - -
-    # scons -u
-    # ./sniffer loop
-    < Hit Ctrl-C when you've seen enough >
-    # ./sniffer scheduler
-    < Hit Ctrl-C when you've seen enough >
-    
- - 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 +
+ +
Sniffer
Simple packet sniffer + reading packets from a packet socket and dumping packet parse to stdout
- \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 Boost.Function 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 - libSocket API reference \n - libPackets API reference \n - libUtils API reference - */ +
RateStuffer
Example application + showing of the PPI infrastructure
+
+ \endhtmlonly +*/ // Local Variables: diff --git a/Examples/RateStuffer/Doxyfile b/Examples/RateStuffer/Doxyfile new file mode 100644 index 0000000..ed23663 --- /dev/null +++ b/Examples/RateStuffer/Doxyfile @@ -0,0 +1,7 @@ +@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 diff --git a/Examples/RateStuffer/Mainpage.dox b/Examples/RateStuffer/Mainpage.dox new file mode 100644 index 0000000..9f51da2 --- /dev/null +++ b/Examples/RateStuffer/Mainpage.dox @@ -0,0 +1,187 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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: +
+    # nc -u -l -p 44345
+    
+ + The next command starts the \c ratestuffer +
+    # cd .../Examples/RateStuffer
+    # scons -u
+    # ./ratestuffer
+    
+ + We should now see '' messages arriving in the first window once per second. We now can + start another \c netcat to send packets to the input port. + +
+    # nc -u localhost 44344
+    < type any text here >
+    
+ + 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 packet->clone() 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 "\n" + \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 } + */ + + +// 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: diff --git a/Examples/RateStuffer/SConscript b/Examples/RateStuffer/SConscript index 6d9f231..dec0b30 100644 --- a/Examples/RateStuffer/SConscript +++ b/Examples/RateStuffer/SConscript @@ -5,3 +5,7 @@ import SENFSCons SENFSCons.Binary( env, 'ratestuffer', SENFSCons.GlobSources(), LIBS = [ 'PPI', 'Scheduler', 'Packets', 'Socket', 'Utils' ] ); + +SENFSCons.Doxygen(env, extra_sources=[ + env.Dia2Png('ratestuffer.dia') +]) diff --git a/Examples/RateStuffer/ratestuffer.cc b/Examples/RateStuffer/ratestuffer.cc index ea29427..7c1d1c7 100644 --- a/Examples/RateStuffer/ratestuffer.cc +++ b/Examples/RateStuffer/ratestuffer.cc @@ -46,53 +46,73 @@ namespace module = senf::ppi::module; 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 diff --git a/Examples/RateStuffer/ratestuffer.dia b/Examples/RateStuffer/ratestuffer.dia new file mode 100644 index 0000000..3056cd9 Binary files /dev/null and b/Examples/RateStuffer/ratestuffer.dia differ diff --git a/Examples/RateStuffer/screenshot.png b/Examples/RateStuffer/screenshot.png new file mode 100644 index 0000000..28d8495 Binary files /dev/null and b/Examples/RateStuffer/screenshot.png differ diff --git a/Examples/Sniffer/Doxyfile b/Examples/Sniffer/Doxyfile new file mode 100644 index 0000000..7818719 --- /dev/null +++ b/Examples/Sniffer/Doxyfile @@ -0,0 +1,6 @@ +@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 diff --git a/Examples/Sniffer/Mainpage.dox b/Examples/Sniffer/Mainpage.dox new file mode 100644 index 0000000..4c41d5f --- /dev/null +++ b/Examples/Sniffer/Mainpage.dox @@ -0,0 +1,196 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 + +
+    # scons -u
+    # ./sniffer loop
+    < Hit Ctrl-C when you've seen enough >
+    # ./sniffer scheduler
+    < Hit Ctrl-C when you've seen enough >
+    
+ + 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 Boost.Function 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 + libSocket API reference \n + libPackets API reference \n + libUtils API reference + */ + + +// 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: diff --git a/Examples/Sniffer/SConscript b/Examples/Sniffer/SConscript index 6c1c57a..e30f7c9 100644 --- a/Examples/Sniffer/SConscript +++ b/Examples/Sniffer/SConscript @@ -6,3 +6,5 @@ import SENFSCons SENFSCons.Binary(env, 'sniffer', SENFSCons.GlobSources(), LIBS = [ 'Scheduler', 'Packets', 'Socket', 'Utils' ], OBJECTS = [ '#/Packets/DefaultBundle/DefaultBundle.o' ]); + +SENFSCons.Doxygen(env) diff --git a/PPI/Doxyfile b/PPI/Doxyfile index 73ee2a5..6b2f429 100644 --- a/PPI/Doxyfile +++ b/PPI/Doxyfile @@ -5,4 +5,5 @@ GENERATE_TAGFILE = doc/ppi.tag 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" diff --git a/PPI/Module.hh b/PPI/Module.hh index e5551ed..5ae07e9 100644 --- a/PPI/Module.hh +++ b/PPI/Module.hh @@ -126,7 +126,9 @@ namespace module { void destroy(); +#ifndef DOXYGEN virtual void macro_SENF_PPI_MODULE_missing() = 0; +#endif private: virtual void init(); diff --git a/PPI/Setup.hh b/PPI/Setup.hh index 12e7d90..57215b1 100644 --- a/PPI/Setup.hh +++ b/PPI/Setup.hh @@ -34,7 +34,9 @@ namespace senf { namespace ppi { - + +#ifndef DOXYGEN + void connect(connector::ActiveOutput & source, connector::PassiveInput & target); void connect(connector::PassiveOutput & source, connector::ActiveInput & target); @@ -52,7 +54,14 @@ namespace ppi { void connect(M1 & source, M2 & target, typename boost::enable_if< boost::is_base_of >::type * = 0, typename boost::enable_if< boost::is_base_of >::type * = 0); - + +#else + + template + void connect(Source & source, Target & target); + +#endif + void run(); void init(); diff --git a/doclib/Doxyfile.global b/doclib/Doxyfile.global index b2d6303..bdae4f0 100644 --- a/doclib/Doxyfile.global +++ b/doclib/Doxyfile.global @@ -25,7 +25,7 @@ SEARCHENGINE = YES 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" diff --git a/doclib/SConscript b/doclib/SConscript index e72656b..3712380 100644 --- a/doclib/SConscript +++ b/doclib/SConscript @@ -11,19 +11,20 @@ def modules(): # 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: @@ -34,11 +35,29 @@ def modules(): 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