4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief Connectors non-inline non-template implementation */
26 #include "Connectors.hh"
27 #include "Connectors.ih"
32 #include "ModuleManager.hh"
33 #include <senf/Utils/Console/Console.hh>
35 //#include "Connectors.mpp"
37 ///////////////////////////////cc.p////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////////////
40 // senf::ppi::connector::Connector
42 prefix_ senf::ppi::connector::Connector::~Connector()
45 Connector & peer (*peer_);
47 if (! peer.initializationScheduled())
48 peer.enqueueInitializable();
49 peer.v_disconnected();
53 prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
55 // The connector is not registered -> route() or noroute() statement missing
57 "senf::ppi::connector::Connector::connect(): (source) "
58 "Missing route() or noroute()" );
59 // The connector is already connected
61 "senf::ppi::connector::Connector::connect(): (source) "
62 "duplicate connection" );
63 // The target connector is not registered -> route() or noroute() statement missing
64 SENF_ASSERT( target.module_,
65 "senf::ppi::connector::Connector::connect(): (target) "
66 "Missing route() or noroute()" );
67 // The target connector is already connected
68 SENF_ASSERT( ! target.peer_,
69 "senf::ppi::connector::Connector::connect(): (target) "
70 "duplicate connection" );
71 if (! (packetTypeID() == typeid(void) ||
72 target.packetTypeID() == typeid(void) ||
73 packetTypeID() == target.packetTypeID()) )
74 throw IncompatibleConnectorsException()
75 << ": " << prettyName(packetTypeID())
76 << " [in module " << prettyName(typeid(*module_)) << "] "
77 << ", " << prettyName(target.packetTypeID())
78 << " [in module " << prettyName(typeid(*target.module_)) << "]";
83 if (! initializationScheduled())
84 enqueueInitializable();
85 if (! peer().initializationScheduled())
86 peer().enqueueInitializable();
93 senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::traceState_ (
94 senf::ppi::connector::Connector::NO_TRACING);
96 prefix_ void senf::ppi::connector::Connector::trace(Packet const & p, char const * label)
98 if (traceState_ == NO_TRACING)
101 std::string type (prettyName(p.typeId().id()));
102 log << "PPI packet trace: " << label << " 0x" << std::hex << p.id() << " "
103 << type.substr(21, type.size()-22) << " on " << & module() << " "
104 << prettyName(typeid(module())) << " connector 0x" << this << "\n";
105 if (traceState_ == TRACE_CONTENTS)
110 prefix_ void senf::ppi::connector::Connector::throttleTrace(char const * label,
113 if (traceState_ == NO_TRACING)
116 log << "PPI throttling trace: " << label << " " << type << " on " << & module()
117 << " " << prettyName(typeid(module())) << " connector 0x" << this << "\n";
121 namespace senf { namespace ppi { namespace connector {
123 SENF_CONSOLE_REGISTER_ENUM_MEMBER(
124 Connector, TraceState, (NO_TRACING)(TRACE_IDS)(TRACE_CONTENTS) );
130 struct ConsoleRegister
135 ConsoleRegister::ConsoleRegister()
137 #ifndef SENF_PPI_NOTRACE
138 senf::ppi::ModuleManager::instance().consoleDir()
139 .add("tracing", senf::console::factory::Command(
140 SENF_FNP(senf::ppi::connector::Connector::TraceState,
141 senf::ppi::connector::Connector::tracing, ()))
142 .doc("Log every packet sent or received by any module.\n"
143 "There are three different tracing levels:\n"
145 " NO_TRACING don't output any tracing information\n"
146 " TRACE_IDS trace packet id's but do not show packet contents\n"
147 " TRACE_CONTENTS trace complete packet contents\n"
149 "A log message is generated whenever the packet traverses a connector. The\n"
150 "TRACE_IDS log message has the following format:\n"
152 " PPI packet trace: <direction> <packet-id> <packet-type>\n"
153 " on <module-id> <module-type> connector <connector-id>\n"
154 " PPI throttling trace: <direction> <throttle-msg>\n"
155 " on <module-id> <module-type> connector <connector-id>\n"
159 " direction 'IN' for packets/throttle notifications entering the module,\n"
160 " 'OUT' for packets/throttle notifications leaving it\n"
161 " packet-id Numeric unique packet id. This value is unique for packets\n"
162 " alive at the same time, packets at different times may (and\n"
163 " will) share id's\n"
164 " packet-type The type of the packet header\n"
165 " module-id Unique module id\n"
166 " module-type Type of the module the packet is sent to/from\n"
167 " connector-id Unique connector id\n"
168 " throttle-msg Type of throttling event\n")
171 senf::ppi::ModuleManager::instance().consoleDir()
172 .add("tracing", senf::console::factory::Command(
173 SENF_FNP(void, senf::ppi::connector::Connector::tracing,
174 (senf::ppi::connector::Connector::TraceState)))
175 .arg("state", "new tracing state")
180 ConsoleRegister consoleRegister;
184 prefix_ void senf::ppi::connector::Connector::disconnect()
186 // Cannot disconnected a non-connected connector
188 "senf::ppi::connector::Connector::disconnect(): Not connected" );
190 Connector & peer (*peer_);
194 if (! initializationScheduled())
195 enqueueInitializable();
196 if (! peer.initializationScheduled())
197 peer.enqueueInitializable();
200 peer.v_disconnected();
203 prefix_ std::type_info const & senf::ppi::connector::Connector::packetTypeID()
208 prefix_ void senf::ppi::connector::Connector::unregisterConnector()
211 module_->unregisterConnector(*this);
214 prefix_ void senf::ppi::connector::Connector::setModule(module::Module & module)
219 prefix_ void senf::ppi::connector::Connector::v_disconnected()
222 prefix_ void senf::ppi::connector::Connector::v_connected()
225 ///////////////////////////////////////////////////////////////////////////
226 // senf::ppi::connector::PassiveConnector
228 prefix_ senf::ppi::connector::PassiveConnector::~PassiveConnector()
230 // Must be here and NOT in base so it is called before destructing the routes_ member
231 unregisterConnector();
234 prefix_ void senf::ppi::connector::PassiveConnector::v_disconnected()
236 Connector::v_disconnected();
240 prefix_ void senf::ppi::connector::PassiveConnector::v_connected()
242 Connector::v_connected();
243 peer_ = & dynamic_cast<ActiveConnector&>(Connector::peer());
246 ////////////////////////////////////////
249 prefix_ void senf::ppi::connector::PassiveConnector::v_init()
251 Routes::const_iterator i (routes_.begin());
252 Routes::const_iterator const i_end (routes_.end());
253 for (; i != i_end; ++i)
254 if ((*i)->throttled())
257 remoteThrottled_ = false;
264 prefix_ void senf::ppi::connector::PassiveConnector::registerRoute(ForwardingRoute & route)
266 routes_.push_back(&route);
269 prefix_ void senf::ppi::connector::PassiveConnector::unregisterRoute(ForwardingRoute & route)
271 Routes::iterator i (std::find(routes_.begin(), routes_.end(), &route));
272 if (i != routes_.end())
276 prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent()
279 prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle()
281 if (std::find_if(routes_.begin(), routes_.end(),
282 boost::bind(&ForwardingRoute::throttled, _1)) == routes_.end()) {
283 remoteThrottled_ = false;
284 if (!nativeThrottled_)
287 SENF_PPI_THROTTLE_TRACE("OUT", "not forwarding unthrottle event");
290 ///////////////////////////////////////////////////////////////////////////
291 // senf::ppi::connector::ActiveConnector
293 prefix_ senf::ppi::connector::ActiveConnector::~ActiveConnector()
295 // Must be here and NOT in base so it is called before destructing the routes_ member
296 unregisterConnector();
299 prefix_ void senf::ppi::connector::ActiveConnector::v_disconnected()
301 Connector::v_disconnected();
305 prefix_ void senf::ppi::connector::ActiveConnector::v_connected()
307 Connector::v_connected();
308 peer_ = & dynamic_cast<PassiveConnector&>(Connector::peer());
311 ////////////////////////////////////////
314 prefix_ void senf::ppi::connector::ActiveConnector::v_init()
320 prefix_ void senf::ppi::connector::ActiveConnector::notifyThrottle()
322 SENF_PPI_THROTTLE_TRACE("IN ", "throttle");
325 if (throttleCallback_)
327 NotifyRoutes::const_iterator i (notifyRoutes_.begin());
328 NotifyRoutes::const_iterator const i_end (notifyRoutes_.end());
329 for (; i != i_end; ++i)
330 (*i)->notifyThrottle();
334 prefix_ void senf::ppi::connector::ActiveConnector::notifyUnthrottle()
336 SENF_PPI_THROTTLE_TRACE("IN ", "unthrottle");
339 if (unthrottleCallback_)
340 unthrottleCallback_();
341 NotifyRoutes::const_iterator i (notifyRoutes_.begin());
342 NotifyRoutes::const_iterator const i_end (notifyRoutes_.end());
343 for (; i != i_end; ++i)
344 (*i)->notifyUnthrottle();
348 prefix_ void senf::ppi::connector::ActiveConnector::registerRoute(ForwardingRoute & route)
350 notifyRoutes_.push_back(&route);
353 prefix_ void senf::ppi::connector::ActiveConnector::unregisterRoute(ForwardingRoute & route)
355 NotifyRoutes::iterator i (std::find(notifyRoutes_.begin(), notifyRoutes_.end(), &route));
356 if (i != notifyRoutes_.end())
357 notifyRoutes_.erase(i);
360 ///////////////////////////////////////////////////////////////////////////
361 // senf::ppi::connector::InputConnector
363 prefix_ senf::Packet senf::ppi::connector::InputConnector::operator()()
368 Packet p ( queue_.back());
371 SENF_PPI_TRACE(p, "IN ");
374 SENF_PPI_TRACE(Packet(), "IN ");
379 prefix_ void senf::ppi::connector::InputConnector::v_disconnected()
381 Connector::v_disconnected();
385 prefix_ void senf::ppi::connector::InputConnector::v_connected()
387 Connector::v_connected();
388 peer_ = & dynamic_cast<OutputConnector&>(Connector::peer());
391 ////////////////////////////////////////
394 prefix_ void senf::ppi::connector::InputConnector::v_requestEvent()
397 prefix_ void senf::ppi::connector::InputConnector::v_enqueueEvent()
400 prefix_ void senf::ppi::connector::InputConnector::v_dequeueEvent()
403 ///////////////////////////////////////////////////////////////////////////
404 // senf::ppi::connector::OutputConnector
406 prefix_ void senf::ppi::connector::OutputConnector::v_disconnected()
408 Connector::v_disconnected();
412 prefix_ void senf::ppi::connector::OutputConnector::v_connected()
414 Connector::v_connected();
415 peer_ = & dynamic_cast<InputConnector&>(Connector::peer());
418 ///////////////////////////////////////////////////////////////////////////
419 // senf::ppi::connector::GenericActiveInput
421 ////////////////////////////////////////
424 prefix_ void senf::ppi::connector::GenericActiveInput::v_requestEvent()
429 ///////////////////////////////////////////////////////////////////////////
430 // senf::ppi::connector::GenericPassiveInput
432 prefix_ void senf::ppi::connector::GenericPassiveInput::v_disconnected()
434 PassiveConnector::v_disconnected();
435 InputConnector::v_disconnected();
439 prefix_ void senf::ppi::connector::GenericPassiveInput::v_connected()
441 PassiveConnector::v_connected();
442 InputConnector::v_connected();
443 peer_ = & dynamic_cast<GenericActiveOutput&>(Connector::peer());
446 ////////////////////////////////////////
449 prefix_ void senf::ppi::connector::GenericPassiveInput::v_enqueueEvent()
453 qdisc_->update(*this, QueueingDiscipline::ENQUEUE);
456 prefix_ void senf::ppi::connector::GenericPassiveInput::v_dequeueEvent()
459 qdisc_->update(*this, QueueingDiscipline::DEQUEUE);
462 prefix_ void senf::ppi::connector::GenericPassiveInput::qdisc(QueueingDiscipline::None_t)
467 prefix_ void senf::ppi::connector::GenericPassiveInput::v_unthrottleEvent()
469 size_type n (queueSize());
472 size_type nn (queueSize());
479 ///////////////////////////////////////////////////////////////////////////
480 // senf::ppi::connector::GenericPassiveOutput
482 prefix_ void senf::ppi::connector::GenericPassiveOutput::v_disconnected()
484 PassiveConnector::v_disconnected();
485 OutputConnector::v_disconnected();
489 prefix_ void senf::ppi::connector::GenericPassiveOutput::v_connected()
491 PassiveConnector::v_connected();
492 OutputConnector::v_connected();
493 peer_ = & dynamic_cast<GenericActiveInput&>(Connector::peer());
496 ///////////////////////////////////////////////////////////////////////////
497 // senf::ppi::connector::GenericActiveInput
499 prefix_ void senf::ppi::connector::GenericActiveInput::v_disconnected()
501 ActiveConnector::v_disconnected();
502 InputConnector::v_disconnected();
506 prefix_ void senf::ppi::connector::GenericActiveInput::v_connected()
508 ActiveConnector::v_connected();
509 InputConnector::v_connected();
510 peer_ = & dynamic_cast<GenericPassiveOutput&>(Connector::peer());
513 ///////////////////////////////////////////////////////////////////////////
514 // senf::ppi::connector::GenericActiveOutput
516 prefix_ void senf::ppi::connector::GenericActiveOutput::v_disconnected()
518 ActiveConnector::v_disconnected();
519 OutputConnector::v_disconnected();
523 prefix_ void senf::ppi::connector::GenericActiveOutput::v_connected()
525 ActiveConnector::v_connected();
526 OutputConnector::v_connected();
527 peer_ = & dynamic_cast<GenericPassiveInput&>(Connector::peer());
531 ///////////////////////////////cc.e////////////////////////////////////////
533 //#include "Connectors.mpp"
539 // comment-column: 40
540 // c-file-style: "senf"
541 // indent-tabs-mode: nil
542 // ispell-local-dictionary: "american"
543 // compile-command: "scons -u test"