module.h

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 
00025 #ifndef NL_FILE_MODULE_H
00026 #define NL_FILE_MODULE_H
00027 
00028 #include "nel/misc/factory.h"
00029 #include "nel/misc/command.h"
00030 #include "nel/misc/string_mapper.h"
00031 #include "nel/misc/co_task.h"
00032 #include "nel/misc/algo.h"
00033 #include "nel/net/message.h"
00034 #include "nel/net/unified_network.h"
00035 #include "module_common.h"
00036 
00037 namespace NLNET
00038 {
00039     class CGatewayRoute;
00040     class IModuleInterceptable;
00041 
00042     class IInterceptorRegistrar
00043     {
00044     public:
00045         virtual ~IInterceptorRegistrar() { }
00046         virtual void registerInterceptor(IModuleInterceptable *interceptor) =0;
00047         virtual void unregisterInterceptor(IModuleInterceptable *interceptor) =0;
00048     };
00049 
00055     class IModuleInterceptable
00056     {
00057     public:
00058         IModuleInterceptable();
00059         virtual ~IModuleInterceptable();
00060 
00061         void registerInterceptor(IInterceptorRegistrar *registrar);
00062 
00063         void interceptorUnregistered(IInterceptorRegistrar *registrar);
00064 
00065         IInterceptorRegistrar *getRegistrar();
00066 
00072         virtual std::string         buildModuleManifest() const { return std::string(); }
00073 
00074         //@name Callback from module sockets
00076 
00080         virtual void                onModuleUp(IModuleProxy *moduleProxy) = 0;
00085         virtual void                onModuleDown(IModuleProxy *moduleProxy) =0;
00090         virtual bool                onProcessModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message) =0;
00094         virtual void                onModuleSecurityChange(IModuleProxy *moduleProxy) =0;
00095 
00096     private:
00097         IInterceptorRegistrar       *_Registrar;
00098     };
00099 
00104     class IModule :
00105         public NLMISC::CRefCount,
00106         public IInterceptorRegistrar,
00107         public IModuleInterceptable
00108     {
00109         friend class IModuleFactory;
00110 
00111         virtual void setFactory(IModuleFactory *factory) =0;
00112 
00113     public:
00115         class EModuleAlreadyPluggedHere : public NLMISC::Exception
00116         {
00117         };
00118 
00120         class EInvokeFailed : public NLMISC::Exception
00121         {
00122         };
00123 
00125         class EInvokeBadReturn : public NLMISC::Exception
00126         {
00127         };
00128 
00129         // Module management =====================
00130 
00131         virtual ~IModule() {}
00132 
00137         virtual bool            initModule(const TParsedCommandLine &initInfo) =0;
00138 
00139         //@name Basic module information
00141 
00147         virtual TModuleId           getModuleId() const =0;
00153         virtual const std::string   &getModuleName() const =0;
00155         virtual const std::string   &getModuleClassName() const =0;
00165         virtual const std::string   &getModuleFullyQualifiedName() const =0;
00166 
00179         virtual std::string getModuleManifest() const =0;
00180 
00193         virtual bool isImmediateDispatchingSupported() const { return true; }
00195 
00196         //@name Callback from the module manager
00198 
00199         virtual void                onServiceUp(const std::string &serviceName, NLNET::TServiceId serviceId) =0;
00201         virtual void                onServiceDown(const std::string &serviceName, NLNET::TServiceId serviceId) = 0;
00208         virtual void                onModuleUpdate() =0;
00212         virtual void                onApplicationExit() = 0;
00214 
00215         // socket management =====================
00216 
00217         //@name module sockets operation
00219 
00223         virtual void                plugModule(IModuleSocket *moduleSocket)
00224             throw (EModuleAlreadyPluggedHere)
00225             =0;
00232         virtual void                unplugModule(IModuleSocket *moduleSocket)
00233             throw (EModuleNotPluggedHere)
00234             =0;
00239         virtual void                getPluggedSocketList(std::vector<IModuleSocket*> &resultList) =0;
00241 
00242 
00243         //@name Callback from module sockets
00245 
00249 //      virtual void                onModuleUp(IModuleProxy *moduleProxy) = 0;
00254 //      virtual void                onModuleDown(IModuleProxy *moduleProxy) =0;
00260         virtual void                onReceiveModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message) =0;
00264 //      virtual void                onProcessModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message) =0;
00268 //      virtual void                onModuleSecurityChange(IModuleProxy *moduleProxy) =0;
00269 
00275         virtual void        invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg)
00276             throw (EInvokeFailed)
00277             =0;
00278 
00280 
00281         //@name Callback from module sockets management
00283         enum TModuleSocketEvent
00284         {
00285             mse_plugged,
00286             mse_before_unplug,
00287             mse_unplugged,
00288         };
00289         virtual void    onModuleSocketEvent(IModuleSocket *moduleSocket, TModuleSocketEvent eventType) =0;
00291 
00292 
00294         //@name internal method, should not be used by client code
00295         virtual void _onModuleUp(IModuleProxy *removedProxy) =0;
00296         virtual void _onModuleDown(IModuleProxy *removedProxy) =0;
00297 
00299 
00300     };
00301 
00302     const TModulePtr        NullModule;
00303 
00304 
00305 
00312     struct TSecurityData
00313     {
00314         // for factory system
00315         struct TCtorParam
00316         {
00317             uint8   DataTag;
00318 
00319             TCtorParam(uint8 dataTag)
00320                 :   DataTag(dataTag)
00321             {
00322             }
00323         };
00325         uint8           DataTag;
00326 
00328         TSecurityData   *NextItem;
00329 
00330         TSecurityData(const TCtorParam &params)
00331             : DataTag(params.DataTag),
00332             NextItem(NULL)
00333 
00334         {
00335         }
00336 
00337         virtual ~TSecurityData()
00338         {
00339             if (NextItem != NULL)
00340                 delete NextItem;
00341         }
00342 
00343         virtual void serial(NLMISC::CMemStream &s) =0;
00344 
00345     };
00346 
00347     struct TUnknownSecurityData : public TSecurityData
00348     {
00349         uint8               RealDataTag;
00350         std::vector<uint8>  Data;
00351 
00352         TUnknownSecurityData(uint8 realDataTag, uint32 size)
00353             : TSecurityData(TSecurityData::TCtorParam(0xff)),
00354             RealDataTag(realDataTag),
00355             Data(size)
00356         {
00357         }
00358 
00359         void serial(NLMISC::CMemStream &s)
00360         {
00361             for (uint i=0; i<Data.size(); ++i)
00362             {
00363                 s.serial(Data[i]);
00364             }
00365         }
00366     };
00367 
00368 //  NLMISC_REGISTER_OBJECT(TSecurityData, TUnknownSecurityData, uint8, 0xff);
00369 
00379     class IModuleProxy : public NLMISC::CRefCount
00380     {
00381     public:
00382         virtual ~IModuleProxy() {}
00383 
00390         virtual TModuleId       getModuleProxyId() const =0;
00391 
00403         virtual TModuleId       getForeignModuleId() const =0;
00404 
00411         virtual uint32              getModuleDistance() const =0;
00412 
00420         virtual IModule             *getLocalModule() const =0;
00421 
00426         virtual CGatewayRoute       *getGatewayRoute() const =0;
00427 
00435         virtual const std::string &getModuleName() const =0;
00439         virtual const std::string &getModuleClassName() const =0;
00446         virtual const std::string &getModuleManifest() const =0;
00447 
00452         virtual IModuleGateway *getModuleGateway() const =0;
00453 
00458         virtual void        sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message)
00459             throw (EModuleNotReachable)
00460             =0;
00461 
00466         virtual const TSecurityData *getFirstSecurityData() const = 0;
00467 
00473         virtual const TSecurityData *findSecurityData(uint8 dataTag) const =0;
00474     };
00475 
00476     const TModuleProxyPtr   NullModuleProxy;
00477 
00479     class CModuleTask : public NLMISC::CCoTask
00480     {
00481         bool    _FailInvoke;
00482     protected:
00484         CModuleTask (class CModuleBase *module);
00485 
00486         void initMessageQueue(class CModuleBase *module);
00487 
00488         // A module having a module task always running MUST call this evenly to
00489         // process message received by the module.
00490         void flushMessageQueue(class CModuleBase *module);
00491 
00492     public:
00493         // for task blocked in 'invoke' to fail with an exception
00494         void failInvoke()
00495         {
00496             _FailInvoke = true;
00497         }
00498 
00499         bool mustFailInvoke()
00500         {
00501             return _FailInvoke;
00502         }
00503 
00504         void resetFailInvoke()
00505         {
00506             _FailInvoke = false;
00507         }
00508 
00509         void processPendingMessage(class CModuleBase *module);
00510     };
00511 
00513     template <class T>
00514     class TModuleTask : public CModuleTask
00515     {
00516     public:
00517 
00518         typedef void (T::*TMethodPtr)();
00519 
00520     private:
00521         T           *_Module;
00522         TMethodPtr  _TaskMethod;
00523 
00524         // override CTask::run
00525         void run()
00526         {
00527             initMessageQueue(_Module);
00528 
00529             try
00530             {
00531                 // run the module task command control to module task method
00532                 (_Module->*_TaskMethod)();
00533             }
00534             catch (NLMISC::Exception e)
00535             {
00536                 nlwarning("In module task '%s', exception '%e' thrown", typeid(this).name(), e.what());
00537             }
00538             catch (...)
00539             {
00540                 nlwarning("In module task '%s', unknown exception thrown", typeid(this).name());
00541             }
00542 
00543             // finish the dispatch
00544             flushMessageQueue(_Module);
00545         }
00546     public:
00547 
00548         TModuleTask(T *module,  void (T::*taskMethod)())
00549             :   CModuleTask(module),
00550                 _Module(module),
00551                 _TaskMethod(taskMethod)
00552         {
00553         }
00554     };
00555 
00556     // a special macro for easy module task startup
00557 #define NLNET_START_MODULE_TASK(className, methodName) \
00558     { \
00559         TModuleTask<className> *task = new TModuleTask<className>(this, &className::methodName); \
00560         queueModuleTask(task); \
00561     } \
00562 
00563 
00568     class IModuleFactory : public NLMISC::CRefCount
00569     {
00570     protected:
00572         std::string             _ModuleClassName;
00574         std::set<TModulePtr>    _ModuleInstances;
00575     public:
00576 
00577 
00579         IModuleFactory(const std::string &moduleClassName);
00580 
00582         virtual const std::string &getModuleClassName() const;
00584         virtual const std::string &getInitStringHelp() const =0;
00585 
00590         virtual IModule *createModule() =0;
00591 
00593         virtual void    deleteModule(IModule *module);
00594 
00600         virtual ~IModuleFactory();
00601 
00603         void registerModuleInFactory(TModulePtr module);
00604     };
00605 
00606 //  const TModuleFactoryPtr NullModuleFactory;
00607 
00608     template <class moduleClass>
00609     class CModuleFactory : public IModuleFactory
00610     {
00611     public:
00612         CModuleFactory(const std::string &moduleClassName)
00613             : IModuleFactory(moduleClassName)
00614         {}
00615 
00616         virtual IModule *createModule()
00617         {
00618             IModule *module = new moduleClass;
00619             registerModuleInFactory(module);
00620             return module;
00621         }
00622 
00623         virtual const std::string &getInitStringHelp() const
00624         {
00625             return moduleClass::getInitStringHelp();
00626         }
00627 
00628     };
00629 
00630 #define NLNET_REGISTER_MODULE_FACTORY(moduleClassName, registrationName) \
00631     class moduleClassName##Factory : public NLNET::CModuleFactory<moduleClassName> \
00632     { \
00633     public: \
00634         static const std::string &theModuleClassName() \
00635         { \
00636             static const std::string name(registrationName); \
00637             return name; \
00638         } \
00639         \
00640         moduleClassName##Factory() \
00641             : NLNET::CModuleFactory<moduleClassName>(theModuleClassName()) \
00642         {} \
00643     };\
00644     NLMISC_REGISTER_OBJECT_INDIRECT(NLNET::IModuleFactory, moduleClassName##Factory, std::string, registrationName)
00645 
00646 
00647 //#define NLNET_MAKE_MODULE_FACTORY_TYPENAME(moduleClassName) moduleClassName##Factory
00648 
00649 #define NLNET_GET_MODULE_FACTORY(moduleClassName)   moduleClassName##Factory
00650 
00651     class CModuleSocket;
00652 
00661     class CModuleBase : public IModule, public NLMISC::ICommandsHandler
00662     {
00663         // Module manager is our friend coz it need to feed some field here
00664         friend class CModuleManager;
00665         friend class CModuleTask;
00666 
00667         typedef std::set<IModuleSocket *>   TModuleSockets;
00669         TModuleSockets          _ModuleSockets;
00670 
00671         typedef std::list<IModuleInterceptable*>    TInterceptors;
00673         TInterceptors           _ModuleInterceptors;
00674 
00676         //@name Synchronous messaging
00677         typedef std::list<std::pair<IModuleProxy *, CMessage> > TMessageList;
00679         TMessageList            _SyncMessages;
00680         typedef std::list<CModuleTask*> TModuleTasks;
00682         TModuleTasks            _ModuleTasks;
00683 
00684         typedef std::vector<IModuleProxy*>  TInvokeStack;
00686         TInvokeStack            _InvokeStack;
00687 
00689         IModuleProxy            *_CurrentSender;
00691         const NLNET::CMessage   *_CurrentMessage;
00693         bool                    _CurrentMessageFailed;
00694 
00696         CModuleTask             *_MessageDispatchTask;
00698 
00699         virtual void setFactory(IModuleFactory *factory);
00700         virtual IModuleFactory *getFactory();
00701     protected:
00703         IModuleFactory      *_ModuleFactory;
00705         TModuleId           _ModuleId;
00707         std::string         _ModuleName;
00709         mutable std::string _FullyQualifedModuleName;
00710 
00711 
00712         CModuleBase();
00713         ~CModuleBase();
00714 
00715         virtual void registerInterceptor(IModuleInterceptable *interceptor);
00716         virtual void unregisterInterceptor(IModuleInterceptable *interceptor);
00717 
00718         const std::string   &getCommandHandlerName() const;
00719         TModuleId           getModuleId() const;
00720         const std::string   &getModuleName() const;
00721 
00722         const std::string   &getModuleClassName() const;
00723 
00724         const std::string   &getModuleFullyQualifiedName() const;
00725 
00726         std::string         getModuleManifest() const;
00727 
00733         virtual void        onReceiveModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message);
00734 
00736         void _receiveModuleMessageTask();
00737 
00738         void queueModuleTask(CModuleTask *task);
00739 
00740         CModuleTask *getActiveModuleTask();
00741 
00742     public:
00744         static const std::string &getInitStringHelp();
00745 
00755         template <class T>
00756         T *getInterceptor(T *dummy, IModuleInterceptable *previous = NULL)
00757         {
00758             TInterceptors::iterator it(_ModuleInterceptors.begin());
00759             if (previous != NULL)
00760             {
00761                 // advance up to next the previous
00762                 while (it != _ModuleInterceptors.end() && *it != previous)
00763                     ++it;
00764                 if (it != _ModuleInterceptors.end())
00765                     ++it;
00766             }
00767 
00768             while (it != _ModuleInterceptors.end())
00769             {
00770                 IModuleInterceptable *mi = *it;
00771                 T *inter = dynamic_cast<T*>(mi);
00772 
00773                 if (inter != NULL)
00774                 {
00775                     dummy = inter;
00776                     return inter;
00777                 }
00778 
00779                 ++it;
00780             }
00781 
00782             dummy = NULL;
00783             return NULL;
00784         }
00785     protected:
00786         // Init base module, init module name
00787         bool                initModule(const TParsedCommandLine &initInfo);
00788 
00789         void                plugModule(IModuleSocket *moduleSocket) throw (EModuleAlreadyPluggedHere);
00790         void                unplugModule(IModuleSocket *moduleSocket)  throw (EModuleNotPluggedHere);
00791         void                getPluggedSocketList(std::vector<IModuleSocket*> &resultList);
00792         void                invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg) throw (EInvokeFailed);
00793         void                _onModuleUp(IModuleProxy *removedProxy);
00794         void                _onModuleDown(IModuleProxy *removedProxy);
00795 
00796         bool                _onProcessModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message);
00797 
00798 
00799 
00800 
00802         NLMISC_COMMAND_HANDLER_TABLE_BEGIN(CModuleBase)
00803             NLMISC_COMMAND_HANDLER_ADD(CModuleBase, dump, "display informations about module instance status", "no args")
00804             NLMISC_COMMAND_HANDLER_ADD(CModuleBase, plug, "plug the module in a module socket", "<socket_name>")
00805             NLMISC_COMMAND_HANDLER_ADD(CModuleBase, unplug, "unplug the module out of a module socket", "<socket_name>")
00806             NLMISC_COMMAND_HANDLER_ADD(CModuleBase, sendPing, "send a ping message to another module using the first available route", "<addresseeModuleName>")
00807         NLMISC_COMMAND_HANDLER_TABLE_END
00808 
00809         NLMISC_CLASS_COMMAND_DECL(dump);
00810         NLMISC_CLASS_COMMAND_DECL(plug);
00811         NLMISC_CLASS_COMMAND_DECL(unplug);
00812         NLMISC_CLASS_COMMAND_DECL(sendPing);
00813     };
00814 
00815     class CGatewayRoute;
00816 
00817     class CModuleProxy : public IModuleProxy
00818     {
00819         friend class CModuleManager;
00820         friend class CStandardGateway;
00821 
00823         IModuleGateway      *_Gateway;
00825         CGatewayRoute       *_Route;
00827         uint32              _Distance;
00829         TModuleId           _ModuleProxyId;
00831         TModuleId           _ForeignModuleId;
00832 
00834         TModulePtr          _LocalModule;
00836         NLMISC::TStringId   _ModuleClassName;
00838         NLMISC::TStringId   _FullyQualifiedModuleName;
00840         std::string         _Manifest;
00842         TSecurityData       *_SecurityData;
00843 
00845         CModuleProxy(TModulePtr localModule, TModuleId localModuleId, const std::string &moduleClassName, const std::string &fullyQualifiedModuleName, const std::string &moduleManifest);
00846     public:
00847 
00848         const CGatewayRoute * getRoute() const
00849         {
00850             return _Route;
00851         }
00852 
00859         virtual TModuleId   getModuleProxyId() const;
00860 
00861         virtual TModuleId   getForeignModuleId() const;
00862 
00863 
00864         uint32              getModuleDistance() const;
00865 
00866         IModule             *getLocalModule() const;
00867 
00868         CGatewayRoute       *getGatewayRoute() const;
00869 
00877         virtual const std::string &getModuleName() const;
00879         virtual const std::string &getModuleClassName() const;
00881         virtual const std::string &getModuleManifest() const;
00882 
00885         virtual IModuleGateway *getModuleGateway() const;
00886 
00889         virtual void        sendModuleMessage(IModule *senderModule, const NLNET::CMessage &message)
00890             throw (EModuleNotReachable);
00891 
00892         virtual const TSecurityData *getFirstSecurityData() const
00893         {
00894             return _SecurityData;
00895         }
00896 
00897         virtual const TSecurityData *findSecurityData(uint8 dataTag) const;
00898     };
00899 
00900 
00901 
00904     template <class PtrContainer>
00905     class TBroadcastModuleMessage
00906     {
00907 
00908         void sendMessage(IModule *sender, const PtrContainer &addresseeProxies, const NLNET::CMessage &message)
00909         {
00910             typename PtrContainer::iterator first(addresseeProxies.begin()), last(addresseeProxies.end());
00911             for (; first != last; ++first)
00912             {
00913                 IModuleProxy *proxy = static_cast<IModuleProxy*>(*first);
00914 
00915                 proxy->sendModuleMessage(sender, message);
00916             }
00917         }
00918     };
00919 
00920 
00921 } // namespace NLNET
00922 
00923 #endif // NL_FILE_MODULE_H

Generated on Thu Jan 7 08:26:23 2010 for NeL by  doxygen 1.6.1