added more tests to increase test coverage
[senf.git] / PPI / AnnotationRouter.hh
1 // $Id$
2 //
3 // Copyright (C) 2008 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief AnnotationRouter public header */
25
26 #ifndef HH_SENF_PPI_AnnotationRouter_
27 #define HH_SENF_PPI_AnnotationRouter_ 1
28
29 // Custom includes
30 #include <boost/ptr_container/ptr_map.hpp>
31 #include "../Utils/String.hh"
32 #include "Module.hh"
33 #include "Connectors.hh"
34
35 //#include "AnnotationRouter.mpp"
36 ///////////////////////////////hh.p////////////////////////////////////////
37
38 namespace senf {
39 namespace ppi {
40 namespace module {
41
42     /** \brief %Route packets to destination according to some annotation value
43
44         This router takes packet on a single input and directs them to one of it outputs depending
45         on a \ref packet_usage_annotation "packet annotation". Each output connected
46         will be associated with a single annotation value. Incoming packets for which no matching
47         output is found are directed to a default output. If this output is left unconnected, those
48         packets will be dropped.
49
50         The \a AnnotationType template parameter defines the routing key. This annotation must
51         support the following operations:
52         \li Comparison with '<' (\c LessThanComparable concept)
53         \li Copy construction and copy assignment (\c Copyable und \c Assignable concepts)
54             (e.g. via compiler synthesized copy constructor and assignment operator)
55         \li Output streaming to an ostream via '\c <<' (for error description purposes) (\c
56             OutputStreamable concept)
57
58         The following annotation can be used to route the packets according to a mac address.
59         \code
60         struct TargetInterface
61         {
62             senf::MACAddress mac;
63
64             bool operator< (TargetInterface const & other) 
65                 { return mac < other.mac; }
66
67             TargetInterface(senf::MACAddress const & m) 
68                 : mac (m) {}
69         };
70
71         std::ostream & operator<<(std::ostream & os, TargetInterface const & v)
72             { os << v.mac; return os; }
73         \endcode
74
75         The additional senf::MACAddress constructor allows to construct an instance directly from a
76         mac address and allows to pass a senf::MACAddress value as routing key directly:
77
78         \code
79         senf::ppi::module::AnnotationRouter<TargetInterface> router;
80
81         senf::ppi::connect(router, target1, senf::MACAddress::from_string("00:1a:2b:04:06:08"));
82         \endcode
83
84         The special senf::ppi::connect() overload takes a third argument, the routing key. This must
85         be an AnnotationType value or must be (explicitly) convertible to AnnotationType.
86
87         The input will be throttled whenever any of the outputs except \a defaultOutput are
88         throttled.
89
90         \ingroup routing_modules
91
92         \todo Call Module::v_init() on every connection change and remove disconnected connections
93         from the container 
94      */
95     template <class AnnotationType>
96     class AnnotationRouter : public Module
97     {
98         SENF_PPI_MODULE(AnnotationRouter);
99     public:
100         connector::PassiveInput<> input;
101         connector::ActiveOutput<> defaultOutput;
102         
103         AnnotationRouter();
104
105         struct DuplicateKeyException : public senf::Exception
106         { DuplicateKeyException(AnnotationType const & key) 
107               : senf::Exception("Duplicate senf::ppi::module::AnnotationRouter routing key ")
108                 { append( senf::str(key)); } };
109
110     private:
111         connector::ActiveOutput<> & newOutput(AnnotationType const & key);
112
113 #ifndef DOXYGEN
114         // I didn't get template friend functions to work ...
115     public:
116 #endif
117         template <class Target>
118         connector::GenericActiveOutput & connect(Target & target, AnnotationType const & key);
119
120     private:
121         void request();
122         
123         typedef boost::ptr_map<AnnotationType, connector::ActiveOutput<> > Outputs;
124         Outputs outputs_;
125     };
126
127 }
128
129 #ifndef DOXYGEN
130
131     template <class Target, class AnnotationType, class ArgType>
132     connector::GenericActiveOutput & connect(
133         module::AnnotationRouter<AnnotationType> & source, Target & target, 
134         ArgType const & key);
135
136 #endif
137
138 }}
139
140 ///////////////////////////////hh.e////////////////////////////////////////
141 //#include "AnnotationRouter.cci"
142 #include "AnnotationRouter.ct"
143 #include "AnnotationRouter.cti"
144 #endif
145
146 \f
147 // Local Variables:
148 // mode: c++
149 // fill-column: 100
150 // comment-column: 40
151 // c-file-style: "senf"
152 // indent-tabs-mode: nil
153 // ispell-local-dictionary: "american"
154 // compile-command: "scons -u test"
155 // End: