00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
00130
00131 virtual ~IModule() {}
00132
00137 virtual bool initModule(const TParsedCommandLine &initInfo) =0;
00138
00139
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
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
00216
00217
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
00245
00249
00254
00260 virtual void onReceiveModuleMessage(IModuleProxy *senderModuleProxy, const CMessage &message) =0;
00264
00268
00269
00275 virtual void invokeModuleOperation(IModuleProxy *destModule, const NLNET::CMessage &opMsg, NLNET::CMessage &resultMsg)
00276 throw (EInvokeFailed)
00277 =0;
00278
00280
00281
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
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
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 ¶ms)
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
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
00489
00490 void flushMessageQueue(class CModuleBase *module);
00491
00492 public:
00493
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
00525 void run()
00526 {
00527 initMessageQueue(_Module);
00528
00529 try
00530 {
00531
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
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
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
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
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
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
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
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
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 }
00922
00923 #endif // NL_FILE_MODULE_H