Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / src / net / module.cpp
blob23f618973692e1b5689e8c9785e68710d1e33350
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "stdnet.h"
19 #include "nel/net/service.h"
20 #include "nel/net/module.h"
21 #include "nel/net/module_manager.h"
22 #include "nel/net/inet_address.h"
23 #include "nel/net/module_message.h"
24 #include "nel/net/module_gateway.h"
25 #include "nel/net/module_socket.h"
27 #ifdef DEBUG_NEW
28 #define new DEBUG_NEW
29 #endif
31 using namespace std;
32 using namespace NLMISC;
33 using namespace NLNET;
35 namespace NLNET
38 //////////////////////////////////////
39 // Module interceptor implementation
40 //////////////////////////////////////
41 IModuleInterceptable::IModuleInterceptable()
42 : _Registrar(NULL)
46 IModuleInterceptable::~IModuleInterceptable()
48 if (_Registrar != NULL)
49 _Registrar->unregisterInterceptor(this);
52 void IModuleInterceptable::registerInterceptor(IInterceptorRegistrar *registrar)
54 nlassert(registrar != NULL);
56 _Registrar = registrar;
58 _Registrar->registerInterceptor(this);
61 void IModuleInterceptable::interceptorUnregistered(IInterceptorRegistrar *registrar)
63 nlassert(registrar == _Registrar);
65 _Registrar = NULL;
68 IInterceptorRegistrar *IModuleInterceptable::getRegistrar()
70 return _Registrar;
74 //////////////////////////////////////
75 // Module factory implementation
76 //////////////////////////////////////
78 IModuleFactory::IModuleFactory(const std::string &moduleClassName)
79 : _ModuleClassName(moduleClassName)
83 IModuleFactory::~IModuleFactory()
85 // Delete any module that still exist
86 while (!_ModuleInstances.empty())
88 CRefPtr<IModule> sanityCheck(*(_ModuleInstances.begin()));
90 IModuleManager::getInstance().deleteModule(sanityCheck);
92 // container is cleared by deleteModule (see below)
93 // make sure the module is effectively destroyed
94 // NB : is the code assert here, this mean that some user code
95 // (or eventualy NeL code) have kept a smart pointer on the module
96 // and this is bad. All smart pointer MUST be released when the
97 // factory is about to be removed.
98 nlassertex(sanityCheck == NULL, ("Some code have kept pointer on module '%s'", sanityCheck->getModuleName().c_str()));
101 // if the context is still active
102 if (INelContext::isContextInitialised() && IModuleManager::isInitialized())
103 // This factory is no longer available
104 IModuleManager::getInstance().unregisterModuleFactory(this);
107 const std::string &IModuleFactory::getModuleClassName() const
109 return _ModuleClassName;
113 void IModuleFactory::deleteModule(IModule *module)
115 set<TModulePtr>::iterator it(_ModuleInstances.find(module));
116 nlassert(it != _ModuleInstances.end());
118 CRefPtr<IModule> sanityCheck(module);
120 // removing this smart ptr must release the module
121 _ModuleInstances.erase(it);
123 nlassert(sanityCheck == NULL);
126 void IModuleFactory::registerModuleInFactory(TModulePtr module)
128 nlassert(module != NULL);
130 nlassert(_ModuleInstances.find(module) == _ModuleInstances.end());
132 // keep track of the module
133 _ModuleInstances.insert(module);
135 module->setFactory(this);
138 //////////////////////////////////////
139 // CModuleTask implementation
140 //////////////////////////////////////
141 CModuleTask::CModuleTask (class CModuleBase * /*module */)
142 : _FailInvoke(false)
144 // module->queueModuleTask(this);
148 void CModuleTask::initMessageQueue(CModuleBase * /* module */)
152 void CModuleTask::flushMessageQueue(CModuleBase *module)
154 // process any queued message
155 while (!module->_SyncMessages.empty())
157 IModuleProxy *proxy = module->_SyncMessages.front().first;
158 CMessage &msg = module->_SyncMessages.front().second;
160 module->_onProcessModuleMessage(proxy, msg);
162 module->_SyncMessages.pop_front();
166 void CModuleTask::processPendingMessage(CModuleBase *module)
168 flushMessageQueue(module);
172 //////////////////////////////////////
173 // Module base implementation
174 //////////////////////////////////////
176 CModuleBase::CModuleBase()
177 : _CurrentSender(NULL),
178 _CurrentMessage(NULL),
179 _CurrentMessageFailed(false),
180 _MessageDispatchTask(NULL),
181 _ModuleFactory(NULL),
182 _ModuleId(INVALID_MODULE_ID)
184 // register module itself in the interceptor list
185 IModuleInterceptable::registerInterceptor(this);
188 CModuleBase::~CModuleBase()
190 // deleting a module from it's own current task is forbiden
191 nlassert(_ModuleTasks.empty()
192 || CCoTask::getCurrentTask() != _ModuleTasks.front());
194 // terminate and release any pending module task
195 while (!_ModuleTasks.empty())
197 CModuleTask *task = _ModuleTasks.front();
199 // deleting the task will waiting it to terminate
200 delete task;
202 _ModuleTasks.erase(_ModuleTasks.begin());
205 if (_MessageDispatchTask)
207 // delete reception task
208 delete _MessageDispatchTask;
211 // unregister all interceptors
212 while (!_ModuleInterceptors.empty())
214 IModuleInterceptable *interceptor = *(_ModuleInterceptors.begin());
215 unregisterInterceptor(interceptor);
219 void CModuleBase::registerInterceptor(IModuleInterceptable *interceptor)
221 // check that this interceptor not already registered
222 nlassert(find(_ModuleInterceptors.begin(), _ModuleInterceptors.end(), interceptor) == _ModuleInterceptors.end());
224 // insert the interceptor in the list
225 _ModuleInterceptors.push_back(interceptor);
228 void CModuleBase::unregisterInterceptor(IModuleInterceptable *interceptor)
230 TInterceptors::iterator it = find(_ModuleInterceptors.begin(), _ModuleInterceptors.end(), interceptor);
231 nlassert(it != _ModuleInterceptors.end());
233 _ModuleInterceptors.erase(it);
235 interceptor->interceptorUnregistered(this);
238 TModuleId CModuleBase::getModuleId() const
240 return _ModuleId;
243 const std::string &CModuleBase::getModuleName() const
245 return _ModuleName;
248 const std::string &CModuleBase::getModuleClassName() const
250 return _ModuleFactory->getModuleClassName();
253 const std::string &CModuleBase::getModuleFullyQualifiedName() const
255 if (_FullyQualifedModuleName.empty())
257 nlassertex(!_ModuleName.empty(), ("Call to CModuleBase::getModuleFullyQualifiedName before module name have been set (did you call from module constructor ?)"));
258 // build the name
259 string hostName;
260 if (IService::isServiceInitialized())
261 hostName = IService::getInstance()->getHostName();
262 else
263 hostName = ::NLNET::CInetAddress::localHost().hostName();
264 // int pid = ::getpid();
266 _FullyQualifedModuleName = IModuleManager::getInstance().getUniqueNameRoot()+":"+_ModuleName;
269 return _FullyQualifedModuleName;
272 std::string CModuleBase::getModuleManifest() const
274 string manifest;
276 // call each interceptor in order to build the manifest
277 TInterceptors::const_iterator first(_ModuleInterceptors.begin()), last(_ModuleInterceptors.end());
278 for (; first != last; ++first)
280 IModuleInterceptable *interceptor = *first;
282 manifest += interceptor->buildModuleManifest() + " ";
285 if (!manifest.empty() && manifest[manifest.size()-1] == ' ')
286 manifest.resize(manifest.size()-1);
288 return manifest;
291 void CModuleBase::onReceiveModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message)
293 H_AUTO(CModuleBase_onReceiveModuleMessage);
295 if (!_ModuleTasks.empty())
297 // there is a task running, queue in the message
298 _SyncMessages.push_back(make_pair(senderModuleProxy, message));
300 else
302 // go in user code for processing
303 if (_MessageDispatchTask != NULL)
305 // process the message in the co task
306 _CurrentSender = senderModuleProxy;
307 _CurrentMessage = &message;
309 _MessageDispatchTask->resume();
311 if (_CurrentMessageFailed)
312 throw IModule::EInvokeFailed();
314 else
316 // normal processing by the main task
317 _onProcessModuleMessage(senderModuleProxy, message);
322 void CModuleBase::_receiveModuleMessageTask()
324 H_AUTO(CModuleBase__receiveModuleMessageTask);
326 while (!_MessageDispatchTask->isTerminationRequested())
328 // we have a message to dispatch
331 // take a copy of the message to dispatch
332 IModuleProxy *currentSender = _CurrentSender;
333 CMessage currentMessage = *_CurrentMessage;
334 _onProcessModuleMessage(currentSender, currentMessage);
335 _CurrentMessageFailed = false;
337 catch (const NLMISC::Exception &e)
339 nlwarning("In module task '%s' (cotask message receiver), exception '%e' thrown", typeid(this).name(), e.what());
340 // an exception have been thrown
341 _CurrentMessageFailed = true;
343 catch (...)
345 nlwarning("In module task '%s' (cotask message receiver), unknown exception thrown", typeid(this).name());
346 // an exception have been thrown
347 _CurrentMessageFailed = true;
349 // switch to main task
350 _MessageDispatchTask->yield();
355 void CModuleBase::queueModuleTask(CModuleTask *task)
357 _ModuleTasks.push_back(task);
360 CModuleTask *CModuleBase::getActiveModuleTask()
362 if (_ModuleTasks.empty())
363 return NULL;
365 return _ModuleTasks.front();
369 const std::string &CModuleBase::getInitStringHelp()
371 static string help;
372 return help;
375 // Init base module, init module name
376 bool CModuleBase::initModule(const TParsedCommandLine &initInfo)
378 // read module init param for base module .
380 if (initInfo.getParam("base.useCoTaskDispatch"))
382 // init the message dispatch task
383 // NLNET_START_MODULE_TASK(CModuleBase, _receiveModuleMessageTask);
384 // TModuleTask<className> *task = new TModuleTask<className>(this, &className::methodName);
385 _MessageDispatchTask = new TModuleTask<CModuleBase>(this, TModuleTask<CModuleBase>::TMethodPtr(&CModuleBase::_receiveModuleMessageTask));
388 // register this module in the command executor
389 registerCommandsHandler();
391 return true;
394 const std::string &CModuleBase::getCommandHandlerName() const
396 return getModuleName();
400 void CModuleBase::plugModule(IModuleSocket *moduleSocket)
402 CModuleSocket *sock = dynamic_cast<CModuleSocket*>(moduleSocket);
403 nlassert(sock != NULL);
405 TModuleSockets::iterator it(_ModuleSockets.find(moduleSocket));
406 if (it != _ModuleSockets.end())
407 throw EModuleAlreadyPluggedHere();
410 // ok, we can plug the module
412 sock->_onModulePlugged(this);
414 // all fine, store the socket pointer.
415 _ModuleSockets.insert(moduleSocket);
418 void CModuleBase::unplugModule(IModuleSocket *moduleSocket)
420 CModuleSocket *sock = dynamic_cast<CModuleSocket*>(moduleSocket);
421 nlassert(sock != NULL);
423 TModuleSockets::iterator it(_ModuleSockets.find(moduleSocket));
424 if (it == _ModuleSockets.end())
425 throw EModuleNotPluggedHere();
427 sock->_onModuleUnplugged(TModulePtr(this));
429 _ModuleSockets.erase(it);
432 void CModuleBase::getPluggedSocketList(std::vector<IModuleSocket*> &resultList)
434 TModuleSockets::iterator first(_ModuleSockets.begin()), last(_ModuleSockets.end());
435 for (; first != last; ++first)
437 resultList.push_back(*first);
441 /** Do a module operation invocation.
442 * Caller MUST be in a module task to call this method.
443 * The call is blocking until receptions of the operation
444 * result message (or a module down)
446 void CModuleBase::invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg)
448 H_AUTO(CModuleBase_invokeModuleOperation);
450 nlassert(opMsg.getType() == CMessage::Request);
452 // check that we are running in a coroutine task
453 CModuleTask *task = dynamic_cast<CModuleTask *>(CCoTask::getCurrentTask());
454 nlassert(task != NULL);
455 // send the message to the module
456 destModule->sendModuleMessage(this, opMsg);
458 // fill the invoke stack
459 _InvokeStack.push_back(destModule);
461 for (;;)
463 // yield and wait for messages
464 task->yield();
466 if (task->mustFailInvoke())
468 nlassert(!_InvokeStack.empty());
469 // empty the invoke stack
470 _InvokeStack.pop_back();
472 task->resetFailInvoke();
474 throw EInvokeFailed();
477 while (!_SyncMessages.empty())
479 IModuleProxy *proxy = _SyncMessages.front().first;
480 CMessage &msg = _SyncMessages.front().second;
481 if (msg.getType() == CMessage::Response)
483 // we have the response message
484 nlassert(proxy == destModule);
485 resultMsg = msg;
486 // remove this message form the queue
487 _SyncMessages.pop_front();
488 // empty the invoke stack
489 _InvokeStack.pop_back();
490 // stop reading received message now
491 return;
493 else if (msg.getType() == CMessage::Except)
495 // the other side returned an exception !
497 // empty the invoke stack
498 _InvokeStack.pop_back();
500 throw EInvokeFailed();
502 else
504 // another message, dispatch it normally
505 // CMessage::TMessageType msgType = msg.getType();
506 // try
507 // {
508 _onProcessModuleMessage(proxy, msg);
509 // }
510 // catch(...)
511 // {
512 // nlwarning("Some exception where throw will dispatching message '%s' from '%s' to '%s'",
513 // msg.getName().c_str(),
514 // proxy->getModuleName().c_str(),
515 // this->getModuleName().c_str());
517 // if (msgType == CMessage::Request)
518 // {
519 // // send back an exception message
520 // CMessage except;
521 // except.setType("EXCEPT", CMessage::Except);
522 // proxy->sendModuleMessage(this, except);
523 // }
525 // }
527 // remove this message form the queue
528 _SyncMessages.pop_front();
534 void CModuleBase::_onModuleUp(IModuleProxy *removedProxy)
536 H_AUTO(CModuleBase__onModuleUp);
538 // call the normal callback in the interceptor list
539 TInterceptors::iterator first(_ModuleInterceptors.begin()), last(_ModuleInterceptors.end());
540 for (;first != last; ++first)
542 IModuleInterceptable *interceptor = *first;
543 interceptor->onModuleUp(removedProxy);
547 void CModuleBase::_onModuleDown(IModuleProxy *removedProxy)
549 H_AUTO(CModuleBase__onModuleDown);
551 // remove any message from the message queue that come from this proxy
553 TMessageList::iterator first(_SyncMessages.begin()), last(_SyncMessages.end());
554 for (; first != last; ++first)
556 if (first->first == removedProxy)
558 _SyncMessages.erase(first);
559 first = _SyncMessages.begin();
563 // check the invocation stack also
565 TInvokeStack::iterator first(_InvokeStack.begin()), last(_InvokeStack.end());
566 for (; first != last; ++first)
568 if (*first == removedProxy)
570 // at least, we need either a running task or the default dispatch task activated
571 nlassert(!_ModuleTasks.empty() || _MessageDispatchTask != NULL);
573 // gasp, we lost one of the module needed to managed the invocation stack!
574 // make each call generate an exception
575 while (first != _InvokeStack.end())
577 // The module task can be either the first in the module task list or
578 // the co routine dispatching task if it is activated
579 CModuleTask *task = !_ModuleTasks.empty() ? _ModuleTasks.front() : _MessageDispatchTask;
580 task->failInvoke();
581 // switch to task to unstack one level
582 task->resume();
584 break;
589 // call the normal callback in the interceptor list
590 TInterceptors::iterator first(_ModuleInterceptors.begin()), last(_ModuleInterceptors.end());
591 for (;first != last; ++first)
593 (*first)->onModuleDown(removedProxy);
597 bool CModuleBase::_onProcessModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message)
599 H_AUTO(CModuleBase__OnProcessModuleMessage);
601 // try the call on each interceptor
602 bool result;
603 result = false;
607 TInterceptors::iterator first(_ModuleInterceptors.begin()), last(_ModuleInterceptors.end());
608 for (;first != last; ++first)
610 if ((*first)->onProcessModuleMessage(senderModuleProxy, message))
612 result = true;
613 break;
617 catch(...)
619 nlwarning("Some exception where throw will dispatching message '%s' from '%s' to '%s'",
620 message.getName().c_str(),
621 senderModuleProxy->getModuleName().c_str(),
622 this->getModuleName().c_str());
624 if (message.getType() == CMessage::Request)
626 // send back an exception message
627 CMessage except;
628 except.setType("EXCEPT", CMessage::Except);
629 senderModuleProxy->sendModuleMessage(this, except);
631 // here we return true because the message have been processed
632 // (even if the processing have raised some exception !)
633 result = true;
636 return result;
639 void CModuleBase::setFactory(IModuleFactory *factory)
641 nlassert(_ModuleFactory == NULL);
643 _ModuleFactory = factory;
646 IModuleFactory *CModuleBase::getFactory()
648 return _ModuleFactory;
651 NLMISC_CLASS_COMMAND_IMPL(CModuleBase, plug)
653 nlunreferenced(human);
654 nlunreferenced(quiet);
655 nlunreferenced(rawCommandString);
657 if (args.size() != 1)
658 return false;
660 IModuleSocket *socket = IModuleManager::getInstance().getModuleSocket(args[0]);
662 if (socket == NULL)
664 log.displayNL("Unknown socket named '%s'", args[0].c_str());
665 return true;
668 plugModule(socket);
670 if (_ModuleSockets.find(socket) == _ModuleSockets.end())
672 log.displayNL("Failed to plug the module '%s' into the socket '%s'",
673 getModuleName().c_str(),
674 socket->getSocketName().c_str());
676 else
677 log.displayNL("Module '%s' plugged into the socket '%s'",
678 getModuleName().c_str(),
679 socket->getSocketName().c_str());
681 return true;
684 NLMISC_CLASS_COMMAND_IMPL(CModuleBase, unplug)
686 nlunreferenced(human);
687 nlunreferenced(quiet);
688 nlunreferenced(rawCommandString);
690 if (args.size() != 1)
691 return false;
693 IModuleSocket *socket = IModuleManager::getInstance().getModuleSocket(args[0]);
695 if (socket == NULL)
697 log.displayNL("Unknown socket named '%s'", args[0].c_str());
698 return true;
701 if (_ModuleSockets.find(socket) == _ModuleSockets.end())
703 log.displayNL("The module '%s' is not plugged in the socket '%s'",
704 getModuleName().c_str(),
705 socket->getSocketName().c_str());
706 return true;
709 unplugModule(socket);
711 if (_ModuleSockets.find(socket) != _ModuleSockets.end())
712 log.displayNL("Failed to unplug the module '%s' from the socket '%s'",
713 getModuleName().c_str(),
714 socket->getSocketName().c_str());
715 else
716 log.displayNL("Module '%s' unplugged out of the socket '%s'",
717 getModuleName().c_str(),
718 socket->getSocketName().c_str());
720 return true;
723 NLMISC_CLASS_COMMAND_IMPL(CModuleBase, sendPing)
725 nlunreferenced(human);
726 nlunreferenced(quiet);
727 nlunreferenced(rawCommandString);
729 if (args.size() != 1)
730 return false;
732 string modName = args[0];
734 // look in each socket
735 vector<IModuleSocket*> sockets;
736 this->getPluggedSocketList(sockets);
738 for (uint i=0; i<sockets.size(); ++i)
740 IModuleSocket *socket = sockets[i];
741 vector<IModuleProxy*> proxList;
742 socket->getModuleList(proxList);
744 for (uint i=0; i<proxList.size(); ++i)
746 if (proxList[i]->getModuleName() == modName)
748 // we found it !
749 CMessage ping("DEBUG_MOD_PING");
750 proxList[i]->sendModuleMessage(this, ping);
751 log.displayNL("Ping debug message send to '%s'", modName.c_str());
752 return true;
757 log.displayNL("Can't find a route to send message to module '%s'", modName.c_str());
759 return true;
762 NLMISC_CLASS_COMMAND_IMPL(CModuleBase, dump)
764 nlunreferenced(human);
765 nlunreferenced(quiet);
766 nlunreferenced(rawCommandString);
768 if (args.size() != 0)
769 return false;
771 log.displayNL("---------------------------");
772 log.displayNL("Dumping base module state :");
773 log.displayNL("---------------------------");
774 log.displayNL(" Module name : '%s'", getModuleName().c_str());
775 log.displayNL(" Module full name : '%s'", getModuleFullyQualifiedName().c_str());
776 log.displayNL(" Module class : '%s'", _ModuleFactory->getModuleClassName().c_str());
777 log.displayNL(" Module ID : %u", _ModuleId);
778 log.displayNL(" The module is plugged into %u sockets :", _ModuleSockets.size());
780 TModuleSockets::iterator first(_ModuleSockets.begin()), last(_ModuleSockets.end());
781 for (; first != last; ++first)
783 IModuleSocket *ps = *first;
784 vector<IModuleProxy*> proxies;
785 ps->getModuleList(proxies);
787 log.displayNL(" Socket '%s', %u modules reachable :", ps->getSocketName().c_str(), proxies.size()-1);
789 for (uint i=0; i<proxies.size(); ++i)
791 string name = proxies[i]->getModuleName();
792 if (name.find('/') != string::npos)
793 name = name.substr(name.find('/')+1);
794 if (name != getModuleFullyQualifiedName())
796 log.displayNL(" Module '%s' (Module Proxy ID : %u, class : '%s')",
797 proxies[i]->getModuleName().c_str(),
798 proxies[i]->getModuleProxyId(),
799 proxies[i]->getModuleClassName().c_str());
805 return true;
809 /************************************************************************
810 * CModuleProxy impl
811 ************************************************************************/
813 CModuleProxy::CModuleProxy(TModulePtr localModule, TModuleId localModuleId, const std::string &moduleClassName, const std::string &fullyQualifiedModuleName, const std::string &moduleManifest)
814 : _ModuleProxyId(localModuleId),
815 _ForeignModuleId(INVALID_MODULE_ID),
816 _LocalModule(localModule),
817 _ModuleClassName(CStringMapper::map(moduleClassName)),
818 _FullyQualifiedModuleName(CStringMapper::map(fullyQualifiedModuleName)),
819 _Manifest(moduleManifest),
820 _SecurityData(NULL)
824 TModuleId CModuleProxy::getModuleProxyId() const
826 return _ModuleProxyId;
829 TModuleId CModuleProxy::getForeignModuleId() const
831 return _ForeignModuleId;
834 uint32 CModuleProxy::getModuleDistance() const
836 return _Distance;
839 IModule *CModuleProxy::getLocalModule() const
841 return _LocalModule;
844 CGatewayRoute *CModuleProxy::getGatewayRoute() const
846 return _Route;
849 const std::string &CModuleProxy::getModuleName() const
851 return CStringMapper::unmap(_FullyQualifiedModuleName);
853 const std::string &CModuleProxy::getModuleClassName() const
855 return CStringMapper::unmap(_ModuleClassName);
858 const std::string &CModuleProxy::getModuleManifest() const
860 return _Manifest;
864 IModuleGateway *CModuleProxy::getModuleGateway() const
866 return _Gateway;
869 void CModuleProxy::sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message)
871 H_AUTO(CModuleProxy_sendModuleMessage);
873 if (_Gateway == NULL )
875 throw EModuleNotReachable();
878 // We need to find the proxy for the sender using the addressee gateway
879 IModuleProxy *senderProx = _Gateway->getPluggedModuleProxy(senderModule);
880 if (senderProx == NULL )
882 throw EModuleNotReachable();
885 _Gateway->sendModuleProxyMessage(senderProx, this, message);
888 const TSecurityData *CModuleProxy::findSecurityData(uint8 dataTag) const
890 const TSecurityData *ms = _SecurityData;
892 while (ms != NULL)
894 if (ms->DataTag == dataTag)
896 // this block match !
897 return ms;
900 // try the next one
901 ms = ms->NextItem;
904 // not found
905 return NULL;
909 } // namespace NLNET