// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdnet.h" #include "nel/net/module_gateway.h" #include "nel/net/module.h" #include "nel/net/module_manager.h" #include "nel/net/module_socket.h" #include "nel/net/module_message.h" using namespace std; using namespace NLMISC; namespace NLNET { /** A simple gateway that interconnect module locally * For testing purpose and simple case. */ class CLocalGateway : public CModuleBase, public CModuleGateway, public CModuleSocket { // the proxy that represent this gateway // TModuleGatewayProxyPtr _ThisProxy; typedef CTwinMap TModuleProxies; // The modules proxies TModuleProxies _ModuleProxies; public: CLocalGateway() { } ~CLocalGateway() { // we need to unplug any plugged module while (!_PluggedModules.getAToBMap().empty()) { _PluggedModules.getAToBMap().begin()->second->unplugModule(this); } // must be done before the other destructors are called unregisterSocket(); unregisterGateway(); } /*********************************************************** ** Gateway methods ***********************************************************/ virtual const std::string &getGatewayName() const { return getModuleName(); } virtual const std::string &getFullyQualifiedGatewayName() const { return getModuleFullyQualifiedName(); } /// Return the gateway proxy of this gateway // virtual TModuleGatewayProxyPtr &getGatewayProxy() // { // nlassert(!_ThisProxy.isNull()); // return _ThisProxy; // } /// Create and bind to this gateway a new transport virtual void createTransport(const std::string &/* transportClass */, const std::string &/* instanceName */) { } /// Delete a transport (this will close any open route) virtual void deleteTransport(const std::string &/* instanceName */) { } /// Activate/stop peer invisible mode on a transport virtual void setTransportPeerInvisible(const std::string &/* transportInstanceName */, bool /* peerInvisible */) { // unsupported nlstop; } /// Activate/stop firewalling mode on a transport virtual void setTransportFirewallMode(const std::string &/* transportInstanceName */, bool /* firewalled */) throw (EGatewayFirewallBreak) { // unsupported nlstop; } /// Send a command to a transport virtual void transportCommand(const TParsedCommandLine &/* commandLine */) { } virtual IGatewayTransport *getGatewayTransport(const std::string &/* transportName */) const { // there are no transport here return NULL; } virtual uint32 getTransportCount() const { return 0; } virtual uint32 getRouteCount() const { return 0; } virtual uint32 getReceivedPingCount() const { return 0; } virtual void onRouteAdded(CGatewayRoute * /* route */) { } /// A route is removed by a transport virtual void onRouteRemoved(CGatewayRoute * /* route */) { } /// A transport have received a message virtual void onReceiveMessage(CGatewayRoute * /* from */, const CMessage &/* msgin */) { } virtual void createSecurityPlugin(const std::string &/* className */) { } virtual void sendSecurityCommand(const TParsedCommandLine &/* command */) { } virtual void removeSecurityPlugin() { } // virtual bool isGatewayServerOpen() // { // return false; // } // // virtual CInetAddress getGatewayServerAddress() // { // CInetAddress invalid; // // return invalid; // } // virtual void getGatewayClientList(std::vector gatewayList) // { // return; // } // virtual void openGatewayServer(uint16 listeningPort) // throw (EGatewayAlreadyOpen, EGatewayPortInUse) // { // nlstop; // } // virtual void closeGatewayServer() // throw (EGatewayNotOpen) // { // nlstop; // } // virtual void shutdownGatewayServer() // { // nlstop; // } // virtual void onGatewayServerOpen() // { // } // virtual void onGatewayServerClose() // { // } // virtual TModuleGatewayConstant onClientGatewayConnect(TModuleGatewayProxyPtr &clientGateway) // { // return mgc_reject_connection; // } // virtual void onClientGatewayDisconnect(TModuleGatewayProxyPtr &clientGateway) // { // } // virtual void getGatewayServerList(std::vector serverList) // { // return; // } // virtual bool isGatewayConnected() // { // return false; // } // virtual void connectGateway(CInetAddress serverAddress) // { // nlstop; // } // virtual void disconnectGateway(TModuleGatewayProxyPtr &serverGateway) // { // nlstop; // } // virtual void onGatewayConnection(const TModuleGatewayProxyPtr &serverGateway, TModuleGatewayConstant connectionResult) // { // nlstop; // } // virtual void onGatewayDisconnection(const TModuleGatewayProxyPtr &serverGateway) // { // nlstop; // } virtual void onAddModuleProxy(IModuleProxy *addedModule) { // always disclose module to local modules discloseModule(addedModule); } virtual void onRemoveModuleProxy(IModuleProxy * /* removedModule */) { } virtual void discloseModule(IModuleProxy *moduleProxy) throw (EGatewayNotConnected) { // check that the module is plugged here nlassert(_ModuleProxies.getB(moduleProxy) != NULL); // CModuleProxy *modProx = dynamic_cast(moduleProxy); // nlassert(modProx != NULL); nlassert(moduleProxy->getModuleGateway() == this); // warn any plugged module TPluggedModules::TAToBMap::const_iterator first(_PluggedModules.getAToBMap().begin()), last(_PluggedModules.getAToBMap().end()); for (; first != last; ++first) { IModule *module = first->second; if (module->getModuleId() != moduleProxy->getForeignModuleId()) { module->_onModuleUp(moduleProxy); } } } virtual IModuleProxy *getPluggedModuleProxy(IModule * /* pluggedModule */) { return NULL; } virtual uint32 getProxyCount() const { return _ModuleProxies.getAToBMap().size(); } /// Fill a vector with the list of proxies managed here. The module are filled in ascending proxy id order. virtual void getModuleProxyList(std::vector &resultList) const { map index; { TModuleProxies::TAToBMap::const_iterator first(_ModuleProxies.getAToBMap().begin()), last(_ModuleProxies.getAToBMap().end()); for (; first != last; ++first) { index.insert(make_pair(first->first->getModuleProxyId(), first->first)); } } // now build the vector map::iterator first(index.begin()), last(index.end()); for( ; first != last; ++first) { resultList.push_back(first->second); } } // virtual void onReceiveModuleMessage(TModuleGatewayProxyPtr &senderGateway, TModuleMessagePtr &message) // { // } virtual void sendModuleMessage(IModuleProxy * /* senderProxy */, IModuleProxy * /* addresseeProxy */, const CMessage &/* message */) { } virtual void dispatchModuleMessage(IModuleProxy * /* senderProxy */, IModuleProxy * /* addresseeProxy */, const CMessage &/* message */) { nlstop; // TModuleId sourceId = message->getSenderModuleProxyId(); // TModuleProxies::TAToBMap::const_iterator firstSource(_ModuleProxies.getAToBMap().begin()), lastSource(_ModuleProxies.getAToBMap().end()); // for (; firstSource != lastSource && firstSource->first->getForeignModuleId() != sourceId; ++firstSource) {} // nlassert( firstSource != lastSource ); // // TPluggedModules::iterator first(_PluggedModules.begin()), last(_PluggedModules.end()); // TModuleId destId = message->getAddresseeModuleProxyId(); // for (; first != last && (*first)->getModuleId() != destId; ++first) {} // if (first != last) // { // (*first)->onProcessModuleMessage(firstSource->first, message); // } } /*********************************************************** ** Module methods ***********************************************************/ bool initModule(const TParsedCommandLine &initInfo) { bool ret = CModuleBase::initModule(initInfo); // in fact, this gateway is so simple, that it have no option ! registerSocket(); registerGateway(); return ret; } std::string buildModuleManifest() const { return string(); } void onServiceUp(const std::string &/* serviceName */, NLNET::TServiceId /* serviceId */) { } void onServiceDown(const std::string &/* serviceName */, NLNET::TServiceId /* serviceId */) { } void onModuleUpdate() { } void onApplicationExit() { } void onModuleUp(IModuleProxy * /* moduleProxy */) { } void onModuleDown(IModuleProxy * /* moduleProxy */) { } bool onProcessModuleMessage(IModuleProxy * /* senderModuleProxy */, const CMessage &/* message */) { return false; } void onModuleSecurityChange(IModuleProxy * /* moduleProxy */) { } void onModuleSocketEvent(IModuleSocket * /* moduleSocket */, TModuleSocketEvent /* eventType */) { } /*********************************************************** ** Socket methods ***********************************************************/ const std::string &getSocketName() { return getModuleName(); } void _sendModuleMessage(IModule *senderModule, TModuleId destModuleProxyId, const NLNET::CMessage &message ) throw (EModuleNotReachable, EModuleNotPluggedHere) { TModuleProxies::TAToBMap::const_iterator first(_ModuleProxies.getAToBMap().begin()), last(_ModuleProxies.getAToBMap().end()); for (; first != last && first->first->getModuleProxyId() != destModuleProxyId; ++first) {} if (first != last) { first->first->sendModuleMessage(senderModule, message); return;} throw EModuleNotReachable(); } virtual void _broadcastModuleMessage(IModule * /* senderModule */, const NLNET::CMessage &/* message */) throw (EModuleNotPluggedHere) { nlstop; } void onModulePlugged(IModule *pluggedModule) { // A module has just been plugged here, we need to disclose it the the // other module, and disclose other module to it. // create a proxy for this module IModuleProxy *modProx = IModuleManager::getInstance().createModuleProxy( this, NULL, // the module is local, so there is no route 0, // the module is local, distance is 0 pluggedModule, // the module is local, so store the module pointer pluggedModule->getModuleClassName(), getGatewayName()+"/"+pluggedModule->getModuleFullyQualifiedName(), pluggedModule->getModuleManifest(), // _ThisProxy, pluggedModule->getModuleId()); // and store it _ModuleProxies.add(modProx, CStringMapper::map(modProx->getModuleName())); // disclose the new module to other modules discloseModule(modProx); // second, disclose already plugged proxy to the new one { TModuleProxies::TAToBMap::const_iterator first(_ModuleProxies.getAToBMap().begin()), last(_ModuleProxies.getAToBMap().end()); for (; first != last; ++first) { if (first->first->getModuleName() != pluggedModule->getModuleFullyQualifiedName()) pluggedModule->_onModuleUp(first->first); } } } /// Called just after a module as been effectively unplugged from a socket void onModuleUnplugged(IModule *unpluggedModule) { // remove the proxy info TModuleProxies::TBToAMap::const_iterator it(_ModuleProxies.getBToAMap().find(CStringMapper::map(getGatewayName()+"/"+unpluggedModule->getModuleFullyQualifiedName()))); nlassert(it != _ModuleProxies.getBToAMap().end()); IModuleProxy *modProx = it->second; // warn all connected module that a module become unavailable { TPluggedModules::TAToBMap::const_iterator first(_PluggedModules.getAToBMap().begin()), last(_PluggedModules.getAToBMap().end()); for (; first != last; ++first) { IModule *module = first->second; if (module->getModuleFullyQualifiedName() != modProx->getModuleName()) module->_onModuleDown(it->second); } } // warn the unplugged module that all plugged modules are become unavailable { TModuleProxies::TAToBMap::const_iterator first(_ModuleProxies.getAToBMap().begin()), last(_ModuleProxies.getAToBMap().end()); for (; first != last; ++first) { if (first->first->getModuleName() != unpluggedModule->getModuleFullyQualifiedName()) unpluggedModule->_onModuleDown(first->first); } } TModuleId localProxyId = modProx->getModuleProxyId(); // remove reference to the proxy _ModuleProxies.removeWithA(modProx); // release the module proxy IModuleManager::getInstance().releaseModuleProxy(localProxyId); } void getModuleList(std::vector &resultList) { TModuleProxies::TAToBMap::const_iterator first(_ModuleProxies.getAToBMap().begin()), last(_ModuleProxies.getAToBMap().end()); for (; first != last; ++first) { resultList.push_back(first->first); } } }; // register the module factory NLNET_REGISTER_MODULE_FACTORY(CLocalGateway, "LocalGateway"); void forceLocalGatewayLink() { } } // namespace NLNET