// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
# 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"
# include "nel/net/callback_client.h"
# include "nel/net/callback_server.h"
using namespace std ;
using namespace NLMISC ;
namespace NLNET
{
struct TSecurityDataDesc
{
TSecurityData * SecurityData ;
TSecurityDataDesc ( )
: SecurityData ( NULL )
{
}
void serial ( CMemStream & s )
{
if ( ! s . isReading ( ) )
{
// write mode
TSecurityData * sd = SecurityData ;
uint32 nbSecBlock = 0 ;
sint32 tagCountPos = s . reserve ( 4 ) ;
while ( sd ! = NULL )
{
if ( sd - > DataTag = = 0xff )
{
TUnknownSecurityData * usd = safe_cast < TUnknownSecurityData * > ( sd ) ;
s . serial ( usd - > RealDataTag ) ;
}
else
{
s . serial ( sd - > DataTag ) ;
}
// reserve a place to store the size of the next element
sint32 pos = s . reserve ( 4 ) ;
s . serial ( * sd ) ;
// store the size
uint32 size = s . getPos ( ) - pos - 4 ;
s . poke ( size , pos ) ;
nbSecBlock + + ;
sd = sd - > NextItem ;
}
// store the number of item
s . poke ( nbSecBlock , tagCountPos ) ;
}
else
{
nlassert ( SecurityData = = NULL ) ;
TSecurityData * * pLastSd = & SecurityData ;
// read mode
uint32 nbSecBlock ;
s . serial ( nbSecBlock ) ;
if ( nbSecBlock = = 0 )
SecurityData = NULL ;
for ( uint i = 0 ; i < nbSecBlock ; + + i )
{
uint8 dataTag ;
s . serial ( dataTag ) ;
uint32 blockSize ;
s . serial ( blockSize ) ;
sint32 pos = s . getPos ( ) ;
TSecurityData * sd ;
try
{
TSecurityData : : TCtorParam param ( dataTag ) ;
sd = NLMISC_GET_FACTORY ( TSecurityData , uint8 ) . createObject ( dataTag , param ) ;
if ( sd = = NULL )
{
// we don't know this type, create an unknow security block
sd = new TUnknownSecurityData ( dataTag , blockSize ) ;
sd - > serial ( s ) ;
}
else
{
sd - > serial ( s ) ;
}
}
catch ( const EStreamOverflow & )
{
// FAILED to read the security block, rewind to old pos and serial as unknow
nlwarning ( " Error while reading stream for security data type %u " , dataTag ) ;
s . seek ( pos , NLMISC : : IStream : : begin ) ;
sd = new TUnknownSecurityData ( dataTag , blockSize ) ;
sd - > serial ( s ) ;
}
* pLastSd = sd ;
pLastSd = & ( sd - > NextItem ) ;
}
}
}
} ;
/// Sub message for module description
struct TModuleDescCodec
{
TModuleId ModuleProxyId ;
uint32 ModuleDistance ;
string ModuleFullName ;
string ModuleClass ;
string ModuleManifest ;
TSecurityDataDesc SecDesc ;
TModuleDescCodec ( )
{
}
TModuleDescCodec ( IModuleProxy * proxy )
{
ModuleProxyId = proxy - > getModuleProxyId ( ) ;
ModuleDistance = proxy - > getModuleDistance ( ) + 1 ;
ModuleFullName = proxy - > getModuleName ( ) ;
ModuleClass = proxy - > getModuleClassName ( ) ;
ModuleManifest = proxy - > getModuleManifest ( ) ;
SecDesc . SecurityData = const_cast < TSecurityData * > ( proxy - > getFirstSecurityData ( ) ) ;
}
void serial ( NLMISC : : CMemStream & s )
{
s . serial ( ModuleProxyId ) ;
s . serial ( ModuleDistance ) ;
s . serial ( ModuleFullName ) ;
s . serial ( ModuleManifest ) ;
s . serial ( ModuleClass ) ;
s . serial ( SecDesc ) ;
}
} ;
/// message for module distance update
struct TModuleDistanceChangeMsg
{
TModuleId ModuleId ;
uint32 NewDistance ;
void serial ( NLMISC : : IStream & s )
{
s . serial ( ModuleId ) ;
s . serial ( NewDistance ) ;
}
} ;
/// message for module security update
struct TModuleSecurityChangeMsg
{
TModuleId ModuleId ;
TSecurityDataDesc SecDesc ;
void serial ( NLMISC : : CMemStream & s )
{
s . serial ( ModuleId ) ;
s . serial ( SecDesc ) ;
}
} ;
/// Message for module removing
struct TModuleRemMsg
{
vector < TModuleId > RemovedModules ;
void serial ( NLMISC : : IStream & s )
{
s . serialCont ( RemovedModules ) ;
}
} ;
/// Message for module operation
struct TModuleOperationMsg
{
TModuleId ModuleId ;
string OperationName ;
CMessage MessageBody ;
void serial ( NLMISC : : IStream & s )
{
s . serial ( ModuleId ) ;
s . serial ( OperationName ) ;
s . serial ( MessageBody ) ;
}
} ;
/// message waiting next update for local dispatching
struct TLocalMessage
{
TModuleId SenderProxyId ;
TModuleId AddresseProxyId ;
CMessage Message ;
} ;
/** Register the gateway in the module manager gateway registry
*/
void CModuleGateway : : registerGateway ( )
{
IModuleManager : : getInstance ( ) . registerModuleGateway ( this ) ;
}
/** Unregister the gateway in the module manager gateway registry
*/
void CModuleGateway : : unregisterGateway ( )
{
IModuleManager : : getInstance ( ) . unregisterModuleGateway ( this ) ;
}
/** The standard gateway that interconnect module
* across process .
*/
class CStandardGateway :
public CModuleBase ,
public CModuleGateway ,
public CModuleSocket
{
typedef map < TModuleId , TModuleProxyPtr > TModuleProxies ;
/// Module proxies managed by this gateway. The map key is the module proxy id
TModuleProxies _ModuleProxies ;
typedef CTwinMap < TStringId , TModuleProxyPtr > TNamedProxyIdx ;
/// Index of name to proxy id
TNamedProxyIdx _NameToProxyIdx ;
/// A structure to hold foreign proxy information
struct TKnownModuleInfo
{
TModuleId ForeignProxyId ;
CGatewayRoute * Route ;
uint32 ModuleDistance ;
TStringId ModuleClassId ;
} ;
typedef multimap < TStringId , TKnownModuleInfo > TKnownModuleInfos ;
/** List of known foreign module info.
*/
TKnownModuleInfos _KnownModules ;
typedef map < TModuleId , TModuleId > TLocalModuleIndex ;
/// Translation table to find module proxies for locally plugged module
/// The map key is the local module id, the data is the associated proxy id
TLocalModuleIndex _LocalModuleIndex ;
typedef map < std : : string , IGatewayTransport * > TTransportList ;
/// the list of active transport
TTransportList _Transports ;
typedef set < CGatewayRoute * > TRouteList ;
// the list of available routes
TRouteList _Routes ;
/// The security plug-in (if any)
CGatewaySecurity * _SecurityPlugin ;
/// Ping counter for debug purpose
uint32 _PingCounter ;
typedef std : : list < TLocalMessage > TLocalMessageList ;
/// List of local message waiting dispatching at next update
TLocalMessageList _LocalMessages ;
public :
CStandardGateway ( )
: _SecurityPlugin ( NULL ) ,
_PingCounter ( 0 )
{
}
~ CStandardGateway ( )
{
// we need to unplug any plugged module
while ( ! _PluggedModules . getAToBMap ( ) . empty ( ) )
{
_PluggedModules . getAToBMap ( ) . begin ( ) - > second - > unplugModule ( this ) ;
}
// delete all transport
while ( ! _Transports . empty ( ) )
{
deleteTransport ( _Transports . begin ( ) - > first ) ;
}
// delete security plug-in
if ( _SecurityPlugin ! = NULL )
removeSecurityPlugin ( ) ;
// must be done before the other destructors are called
unregisterSocket ( ) ;
unregisterGateway ( ) ;
}
CModuleProxy * getModuleProxy ( TModuleId proxyId )
{
TModuleProxies : : iterator it ( _ModuleProxies . find ( proxyId ) ) ;
if ( it = = _ModuleProxies . end ( ) )
return NULL ;
return static_cast < CModuleProxy * > ( it - > second . getPtr ( ) ) ;
}
/***********************************************************
* * Gateway methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
virtual const std : : string & getGatewayName ( ) const
{
return getModuleName ( ) ;
}
virtual const std : : string & getFullyQualifiedGatewayName ( ) const
{
return getModuleFullyQualifiedName ( ) ;
}
/// Create and bind to this gateway a new transport
virtual void createTransport ( const std : : string & transportClass , const std : : string & instanceName )
{
if ( _Transports . find ( instanceName ) ! = _Transports . end ( ) )
{
nlwarning ( " A transport with the name '%s' already exist in this gateway " , instanceName . c_str ( ) ) ;
return ;
}
IGatewayTransport : : TCtorParam param ;
param . Gateway = this ;
IGatewayTransport * transport = NLMISC_GET_FACTORY ( IGatewayTransport , std : : string ) . createObject ( transportClass , param ) ;
if ( transport = = NULL )
{
nlwarning ( " Failed to create a transport with the class '%s' " , transportClass . c_str ( ) ) ;
return ;
}
// Store the transport
// TTransportInfo *ti = new TTransportInfo(transport);
_Transports . insert ( make_pair ( instanceName , transport ) ) ;
// _TransportPtrIdx.insert(make_pair(transport, ti));
nldebug ( " NETL6: Gateway transport %s (%s) created " , instanceName . c_str ( ) , transportClass . c_str ( ) ) ;
}
/// Delete a transport (this will close any open route)
virtual void deleteTransport ( const std : : string & instanceName )
{
TTransportList : : iterator it ( _Transports . find ( instanceName ) ) ;
if ( it = = _Transports . end ( ) )
{
nlwarning ( " Unknown transport named '%s' " , instanceName . c_str ( ) ) ;
return ;
}
nldebug ( " NETL6: Gateway transport '%s' deleted " , instanceName . c_str ( ) ) ;
// delete the transport
IGatewayTransport * transport = it - > second ;
// nlassert(_TransportPtrIdx.find(transport) != _TransportPtrIdx.end());
// _TransportPtrIdx.erase(transport);
delete transport ;
// delete it->second;
_Transports . erase ( it ) ;
}
/// Activate/stop peer invisible mode on a transport
virtual void setTransportPeerInvisible ( const std : : string & transportInstanceName , bool peerInvisible )
{
TTransportList : : iterator it ( _Transports . find ( transportInstanceName ) ) ;
if ( it = = _Transports . end ( ) )
{
nlwarning ( " Unknown transport named '%s' " , transportInstanceName . c_str ( ) ) ;
return ;
}
IGatewayTransport * transport = it - > second ;
if ( peerInvisible = = transport - > PeerInvisible )
// nothing more to do
return ;
// set the mode
transport - > PeerInvisible = peerInvisible ;
nldebug ( " NETL6: Gateway transport %s peer invisible mode %s " , transportInstanceName . c_str ( ) , peerInvisible ? " ON " : " OFF " ) ;
// For each route of this transport, we need to disclose/undisclose peer modules
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
if ( route - > getTransport ( ) = = transport )
{
// this route need to be filtered
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModuleProxy * proxy = first - > second ;
if ( proxy - > getGatewayRoute ( ) ! = NULL
& & proxy - > getGatewayRoute ( ) ! = route
& & proxy - > getGatewayRoute ( ) - > getTransport ( ) = = transport )
{
// this module is on the same transport, but another route, remove/add it from the
// route
if ( peerInvisible )
undiscloseModuleToRoute ( route , proxy ) ;
else
{
// check firewall rules
if ( ! route - > getTransport ( ) - > Firewalled )
discloseModuleToRoute ( route , proxy ) ;
}
}
}
}
}
}
/// Activate/stop firewalling mode on a transport
virtual void setTransportFirewallMode ( const std : : string & transportInstanceName , bool firewalled )
throw ( EGatewayFirewallBreak )
{
TTransportList : : iterator it ( _Transports . find ( transportInstanceName ) ) ;
if ( it = = _Transports . end ( ) )
{
nlwarning ( " Unknown transport named '%s' " , transportInstanceName . c_str ( ) ) ;
return ;
}
IGatewayTransport * transport = it - > second ;
if ( firewalled = = transport - > Firewalled )
// nothing to do
return ;
if ( firewalled & & transport - > getRouteCount ( ) ! = 0 )
throw EGatewayFirewallBreak ( ) ;
/// set the firewall mode
transport - > Firewalled = firewalled ;
nldebug ( " NETL6: Gateway transport %s firewall mode %s " , transportInstanceName . c_str ( ) , firewalled ? " ON " : " OFF " ) ;
if ( firewalled = = false )
{
// we need to disclose all module not disclosed yet
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
if ( route - > getTransport ( ) = = transport )
{
// this route need to be unfiltered
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModuleProxy * proxy = first - > second ;
if ( proxy - > getGatewayRoute ( ) = = NULL | | ( proxy - > getGatewayRoute ( ) ! = route ) )
{
// this module is on another route, disclose it if needed
if ( route - > FirewallDisclosed . find ( proxy - > getModuleProxyId ( ) ) = = route - > FirewallDisclosed . end ( ) )
discloseModuleToRoute ( route , proxy ) ;
}
}
}
// clear the firewall disclosed table
route - > FirewallDisclosed . clear ( ) ;
}
}
}
/// Send a command to a transport
virtual void transportCommand ( const TParsedCommandLine & commandLine )
{
for ( uint i = 1 ; i < commandLine . SubParams . size ( ) ; + + i )
{
const TParsedCommandLine * subParam = commandLine . SubParams [ i ] ;
std : : string transportName = subParam - > ParamName ;
TTransportList : : const_iterator it ( _Transports . find ( transportName ) ) ;
if ( it = = _Transports . end ( ) )
{
nlwarning ( " Unknown transport named '%s', ignoring command. " , transportName . c_str ( ) ) ;
}
else if ( subParam - > SubParams . empty ( ) )
{
nlwarning ( " Can't find sub param list for transport '%s' command " , transportName . c_str ( ) ) ;
}
else
{
nldebug ( " NETL6: Gateway transport %s, sending command '%s' " , transportName . c_str ( ) , commandLine . toString ( ) . c_str ( ) ) ;
// ok, we have a valid transport, send the command
IGatewayTransport * transport = it - > second ;
if ( ! transport - > onCommand ( * subParam ) )
return ;
}
}
}
virtual IGatewayTransport * getGatewayTransport ( const std : : string & transportName ) const
{
TTransportList : : const_iterator it ( _Transports . find ( transportName ) ) ;
if ( it = = _Transports . end ( ) )
return NULL ;
else
return it - > second ;
}
virtual uint32 getTransportCount ( ) const
{
return ( uint32 ) _Transports . size ( ) ;
}
virtual uint32 getRouteCount ( ) const
{
return ( uint32 ) _Routes . size ( ) ;
}
virtual uint32 getReceivedPingCount ( ) const
{
return _PingCounter ;
}
virtual void onRouteAdded ( CGatewayRoute * route )
{
nlassert ( route ! = NULL ) ;
// Remember the new route
nlassert ( _Routes . find ( route ) = = _Routes . end ( ) ) ;
_Routes . insert ( route ) ;
// a new route is available, disclose known modules
{
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModuleProxy * modProx = first - > second ;
// only transmit module desc coming from other routes
// and other transport if peer invisible
if ( isModuleProxyVisible ( modProx , route ) )
{
discloseModuleToRoute ( route , modProx ) ;
}
}
}
}
/// A route is removed by a transport
virtual void onRouteRemoved ( CGatewayRoute * route )
{
nlassert ( route ! = NULL ) ;
nlassert ( _Routes . find ( route ) ! = _Routes . end ( ) ) ;
// we need to remove all the proxy that come from this route
// CGatewayRoute::TForeignToLocalIdx::TAToBMap::const_iterator first(route->ForeignToLocalIdx.getAToBMap().begin()), last(route->ForeignToLocalIdx.getAToBMap().end());
// for (; first != last; ++first)
while ( ! route - > ForeignToLocalIdx . getAToBMap ( ) . empty ( ) )
{
removeForeignModule ( route , route - > ForeignToLocalIdx . getAToBMap ( ) . begin ( ) - > first ) ;
// TModuleId localProxyId = first->second;
// TModuleProxies::iterator it(_ModuleProxies.find(localProxyId));
// nlassert(it != _ModuleProxies.end());
//
// IModuleProxy *modProx = it->second;
//
// // trigger an event in the gateway
// onRemoveModuleProxy(modProx);
//
// // remove proxy record from the proxy list
// _ModuleProxies.erase(it);
// _NameToProxyIdx.removeWithB(modProx);
//
// // Release the proxy object
// IModuleManager::getInstance().releaseModuleProxy(modProx->getModuleProxyId());
}
// cleanup the translation table
// route->ForeignToLocalIdx.clear();
// clear the route tracker
_Routes . erase ( route ) ;
// cleanup route state
route - > ForeignToLocalIdx . clear ( ) ;
route - > PendingEvents . clear ( ) ;
route - > FirewallDisclosed . clear ( ) ;
route - > NextMessageType = CModuleMessageHeaderCodec : : mt_invalid ;
route - > NextSenderProxyId = 0 ;
route - > NextAddresseeProxyId = 0 ;
}
/// A transport have received a message
virtual void onReceiveMessage ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveMessage ) ;
// dispatch the message
if ( from - > NextMessageType ! = CModuleMessageHeaderCodec : : mt_invalid )
{
// this message must be dispatched to a module
onReceiveModuleMessage ( from , msgin ) ;
}
// Not a module message, dispatch the gateway message
else if ( msgin . getName ( ) = = " MOD_OP " )
{
onReceiveModuleMessageHeader ( from , msgin ) ;
}
else if ( msgin . getName ( ) = = " MOD_UPD " )
{
onReceiveModuleUpdate ( from , msgin ) ;
}
// else if (msgin.getName() == "MOD_ADD")
// {
// onReceiveModuleAdd(from, msgin);
// }
// else if (msgin.getName() == "MOD_REM")
// {
// onReceiveModuleRemove(from, msgin);
// }
// else if (msgin.getName() == "MOD_DST_UPD")
// {
// onReceiveModuleDistanceUpdate(from, msgin);
// }
}
/***********************************/
/* security plug-in management*/
/***********************************/
/** create a security plug-in.
* There must be no security plug - in currently created .
*/
virtual void createSecurityPlugin ( const std : : string & className )
{
if ( _SecurityPlugin ! = NULL )
{
nlwarning ( " NLNETL5 : CStandardGateway::createSecurityPlugin : plug-in already created " ) ;
return ;
}
CGatewaySecurity : : TCtorParam params ;
params . Gateway = this ;
CGatewaySecurity * gs = NLMISC_GET_FACTORY ( CGatewaySecurity , std : : string ) . createObject ( className , params ) ;
if ( gs = = NULL )
{
nlwarning ( " NLNETL5 : CStandardGateway::createSecurityPlugin : can't create a security plug-in for class '%s' " , className . c_str ( ) ) ;
return ;
}
// store the security plug-in
_SecurityPlugin = gs ;
// update security for all existing proxies
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModuleProxy * proxy = first - > second ;
_SecurityPlugin - > onNewProxy ( proxy ) ;
}
}
/** Send a command to the security plug-in */
virtual void sendSecurityCommand ( const TParsedCommandLine & command )
{
if ( _SecurityPlugin ! = NULL )
{
nlwarning ( " NLNETL5 : CStandardGateway::sendSecurityCommand : plug-in NOT created " ) ;
return ;
}
_SecurityPlugin - > onCommand ( command ) ;
}
/** Remove the security plug-in.
*/
virtual void removeSecurityPlugin ( )
{
if ( _SecurityPlugin = = NULL )
{
nlwarning ( " NLNETL5 : CStandardGateway::removeSecurityPlugin : plug-in not created " ) ;
return ;
}
// delete the plug-in (this can remove some security data)
_SecurityPlugin - > onDelete ( ) ;
delete _SecurityPlugin ;
_SecurityPlugin = NULL ;
}
/** Set a security data block. If a bloc of the same type
* already exist in the list , the new one will replace the
* existing one .
*/
void setSecurityData ( IModuleProxy * proxy , TSecurityData * securityData )
{
nlassert ( proxy - > getModuleGateway ( ) = = this ) ;
nlassert ( securityData - > NextItem = = NULL ) ;
CModuleProxy * modProx = dynamic_cast < CModuleProxy * > ( proxy ) ;
nlassert ( modProx ! = NULL ) ;
// look in the existing security for a matching type and remove it
removeSecurityData ( proxy , securityData - > DataTag ) ;
// now, store the security data
securityData - > NextItem = modProx - > _SecurityData ;
modProx - > _SecurityData = securityData ;
}
/** Clear a block of security data
* The block is identified by the data tag
*/
bool removeSecurityData ( IModuleProxy * proxy , uint8 dataTag )
{
nlassert ( proxy - > getModuleGateway ( ) = = this ) ;
CModuleProxy * modProx = dynamic_cast < CModuleProxy * > ( proxy ) ;
nlassert ( modProx ! = NULL ) ;
bool ret = false ;
TSecurityData * prevSec = NULL ;
TSecurityData * currentSec = modProx - > _SecurityData ;
while ( currentSec ! = NULL )
{
if ( currentSec - > DataTag = = dataTag )
{
if ( prevSec ! = NULL )
prevSec - > NextItem = currentSec - > NextItem ;
else
modProx - > _SecurityData = currentSec - > NextItem ;
TSecurityData * toDelete = currentSec ;
currentSec = currentSec - > NextItem ;
toDelete - > NextItem = NULL ;
delete toDelete ;
ret = true ;
}
else
{
prevSec = currentSec ;
currentSec = currentSec - > NextItem ;
}
}
return ret ;
}
void replaceAllSecurityDatas ( IModuleProxy * proxy , TSecurityData * securityData )
{
nlassert ( proxy - > getModuleGateway ( ) = = this ) ;
CModuleProxy * modProx = dynamic_cast < CModuleProxy * > ( proxy ) ;
nlassert ( modProx ! = NULL ) ;
nlassert ( modProx - > _SecurityData ! = securityData ) ;
if ( modProx - > _SecurityData ! = NULL )
delete modProx - > _SecurityData ;
modProx - > _SecurityData = securityData ;
}
/** Ask the gateway to resend the security data.
* The plug - in call this method after having changed
* the security info for a plug - in outside of the
* onNewProxy call .
*/
void forceSecurityUpdate ( IModuleProxy * proxy )
{
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
if ( isModuleProxyVisible ( proxy , route ) )
{
updateModuleSecurityDataToRoute ( route , proxy ) ;
}
}
}
/***********************************/
/* Inter gateway message reception */
/***********************************/
/** A gateway receive module operation */
void onReceiveModuleMessage ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveModuleMessage ) ;
// clean the message type now, any return path will be safe
from - > NextMessageType = CModuleMessageHeaderCodec : : mt_invalid ;
// Retrieve sender and destination proxy and recall gateway send method
IModuleProxy * senderProxy ;
IModuleProxy * addresseeProxy ;
TModuleProxies : : iterator it ;
// sender proxy
it = _ModuleProxies . find ( from - > NextSenderProxyId ) ;
if ( it = = _ModuleProxies . end ( ) )
{
nlwarning ( " Can't dispatch the module message, sender proxy %u is not in this gateway " , from - > NextSenderProxyId ) ;
return ;
}
senderProxy = it - > second ;
// addressee proxy
it = _ModuleProxies . find ( from - > NextAddresseeProxyId ) ;
if ( it = = _ModuleProxies . end ( ) )
{
nlwarning ( " Can't dispatch the module message '%s', sender proxy %u is not in this gateway " , msgin . getName ( ) . c_str ( ) , from - > NextAddresseeProxyId ) ;
return ;
}
addresseeProxy = it - > second ;
// give the message to the gateway (either for local dispatch or for forwarding)
sendModuleMessage ( senderProxy , addresseeProxy , msgin ) ;
}
// A gateway receive a module message header
void onReceiveModuleMessageHeader ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveModuleMessageHeader ) ;
if ( from - > NextMessageType ! = CModuleMessageHeaderCodec : : mt_invalid )
{
// juste warn (but that is VERY BAD)
nlwarning ( " Receiving a new module message header without having received the previous module message ! " ) ;
}
// store the message information in the route
CModuleMessageHeaderCodec : : decode (
msgin ,
from - > NextMessageType ,
from - > NextSenderProxyId ,
from - > NextAddresseeProxyId ) ;
// translate sender id
const TModuleId * pmoduleId = from - > ForeignToLocalIdx . getB ( from - > NextSenderProxyId ) ;
if ( pmoduleId = = NULL )
{
nlwarning ( " The sender proxy %u is unknown in the translation table, can't dispatch the message ! " , from - > NextSenderProxyId ) ;
from - > NextMessageType = CModuleMessageHeaderCodec : : mt_invalid ;
return ;
}
from - > NextSenderProxyId = * pmoduleId ;
// now, wait the message body
}
/** A gateway receive a general update message */
void onReceiveModuleUpdate ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveModuleUpdate ) ;
while ( uint32 ( msgin . getPos ( ) ) ! = msgin . length ( ) )
{
CGatewayRoute : : TPendingEventType type = CGatewayRoute : : pet_disclose_module ;
// msgin.serialShortEnum(type);
nlRead ( msgin , serialShortEnum , type ) ;
switch ( type )
{
case CGatewayRoute : : pet_disclose_module :
onReceiveModuleAdd ( from , msgin ) ;
break ;
case CGatewayRoute : : pet_undisclose_module :
onReceiveModuleRemove ( from , msgin ) ;
break ;
case CGatewayRoute : : pet_update_distance :
onReceiveModuleDistanceUpdate ( from , msgin ) ;
break ;
case CGatewayRoute : : pet_update_security :
onReceiveModuleSecurityUpdate ( from , msgin ) ;
break ;
default :
// should not append
nlstop ;
}
}
}
/** A gateway send new modules information */
void onReceiveModuleAdd ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveModuleAdd ) ;
TModuleDescCodec modDesc ;
nlRead ( msgin , serial , modDesc ) ;
// for each received module info
TStringId modNameId = CStringMapper : : map ( modDesc . ModuleFullName ) ;
/// store the module information
TKnownModuleInfo modInfo ;
modInfo . ForeignProxyId = modDesc . ModuleProxyId ;
modInfo . ModuleClassId = CStringMapper : : map ( modDesc . ModuleClass ) ;
modInfo . ModuleDistance = modDesc . ModuleDistance ;
modInfo . Route = from ;
nldebug ( " Gateway '%s' : store module info for '%s' (foreign ID %u) @ %u hop " ,
getGatewayName ( ) . c_str ( ) ,
modDesc . ModuleFullName . c_str ( ) ,
modDesc . ModuleProxyId ,
modDesc . ModuleDistance ) ;
// Store module information
_KnownModules . insert ( make_pair ( modNameId , modInfo ) ) ;
if ( _NameToProxyIdx . getB ( modNameId ) ! = NULL )
{
// a proxy for this module already exist,
IModuleProxy * modProx = * ( _NameToProxyIdx . getB ( modNameId ) ) ;
// fill the id translation table
// from->ForeignToLocalIdx.insert(make_pair(modDesc.ModuleProxyId, modProx->getModuleProxyId()));
from - > ForeignToLocalIdx . add ( modDesc . ModuleProxyId , modProx - > getModuleProxyId ( ) ) ;
// check if this route is better
if ( modProx - > getModuleDistance ( ) > modInfo . ModuleDistance )
{
// update module distance and swap route
CModuleProxy * proxy = static_cast < CModuleProxy * > ( modProx ) ;
nldebug ( " Gateway '%s' : Use a shorter path for '%s' from %u to %u hops " ,
getGatewayName ( ) . c_str ( ) ,
modDesc . ModuleFullName . c_str ( ) ,
proxy - > _Distance ,
modInfo . ModuleDistance ) ;
proxy - > _Distance = modInfo . ModuleDistance ;
proxy - > _Route = modInfo . Route ;
sendModuleDistanceUpdate ( proxy ) ;
}
// update the security if needed
if ( modDesc . SecDesc . SecurityData ! = NULL )
{
CModuleProxy * proxy = static_cast < CModuleProxy * > ( modProx ) ;
if ( _SecurityPlugin ! = NULL )
{
_SecurityPlugin - > onNewSecurityData ( from , proxy , modDesc . SecDesc . SecurityData ) ;
}
else
{
if ( proxy - > _SecurityData ! = NULL )
delete proxy - > _SecurityData ;
proxy - > _SecurityData = modDesc . SecDesc . SecurityData ;
}
}
}
else
{
// we need to create a new proxy
// create a module proxy
IModuleProxy * modProx = IModuleManager : : getInstance ( ) . createModuleProxy (
this ,
from ,
modDesc . ModuleDistance ,
NULL ,
modDesc . ModuleClass ,
modDesc . ModuleFullName ,
modDesc . ModuleManifest ,
modDesc . ModuleProxyId ) ;
// set the module security
CModuleProxy * proxy = static_cast < CModuleProxy * > ( modProx ) ;
proxy - > _SecurityData = modDesc . SecDesc . SecurityData ;
// let the security plug-in add/remove security data
if ( _SecurityPlugin ! = NULL )
_SecurityPlugin - > onNewProxy ( proxy ) ;
// store the proxy in the proxy list
_ModuleProxies . insert ( make_pair ( modProx - > getModuleProxyId ( ) , modProx ) ) ;
_NameToProxyIdx . add ( modNameId , modProx ) ;
// Fill the proxy id translation table for this route
// from->ForeignToLocalIdx.insert(make_pair(modDesc.ModuleProxyId, modProx->getModuleProxyId()));
from - > ForeignToLocalIdx . add ( modDesc . ModuleProxyId , modProx - > getModuleProxyId ( ) ) ;
// trigger an event in the gateway
onAddModuleProxy ( modProx ) ;
}
}
void onReceiveModuleRemove ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveModuleRemove ) ;
TModuleId moduleId ;
nlRead ( msgin , serial , moduleId ) ;
removeForeignModule ( from , moduleId ) ;
}
void onReceiveModuleDistanceUpdate ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveModuleDistanceUpdate ) ;
TModuleId moduleId ;
uint32 newDistance ;
nlRead ( msgin , serial , moduleId ) ;
nlRead ( msgin , serial , newDistance ) ;
// translate the module id
const TModuleId * pModuleId = from - > ForeignToLocalIdx . getB ( moduleId ) ;
if ( pModuleId = = NULL )
{
nlwarning ( " Receive a module distance update for foreign module %u, but no translation available " , moduleId ) ;
return ;
}
TModuleId localId = * pModuleId ;
// now, retrieve the module info and update
TModuleProxies : : iterator it2 ( _ModuleProxies . find ( localId ) ) ;
nlassert ( it2 ! = _ModuleProxies . end ( ) ) ;
CModuleProxy * proxy = static_cast < CModuleProxy * > ( it2 - > second . getPtr ( ) ) ;
pair < TKnownModuleInfos : : iterator , TKnownModuleInfos : : iterator > range ;
range = _KnownModules . equal_range ( proxy - > _FullyQualifiedModuleName ) ;
for ( ; range . first ! = range . second ; + + range . first )
{
TKnownModuleInfo & kmi = range . first - > second ;
if ( kmi . Route = = from )
{
// we found the module info, update the data
nldebug ( " Gateway '%s' : updating distance from %u to %u hop for module '%s' " ,
getGatewayName ( ) . c_str ( ) ,
kmi . ModuleDistance ,
newDistance ,
CStringMapper : : unmap ( range . first - > first ) . c_str ( ) ) ;
kmi . ModuleDistance = newDistance ;
break ;
}
}
nlassert ( range . first ! = range . second ) ;
// check if the changed module is the one currently in use
if ( proxy - > _Route = = from )
{
// two task : first, if the new distance is greater, look
// in available route for a shorter path,
// second, send a module distance update for this module.
if ( proxy - > _Distance < newDistance )
{
// look for a shorter path
range = _KnownModules . equal_range ( proxy - > _FullyQualifiedModuleName ) ;
for ( ; range . first ! = range . second ; + + range . first )
{
TKnownModuleInfo & kmi = range . first - > second ;
if ( kmi . ModuleDistance < proxy - > _Distance )
{
nldebug ( " Gateway '%s' : proxy '%s' use a new path from %u to %u hop " ,
getGatewayName ( ) . c_str ( ) ,
proxy - > getModuleName ( ) . c_str ( ) ,
proxy - > _Distance ,
kmi . ModuleDistance ) ;
// this path is shorter, use it now
proxy - > _Route = kmi . Route ;
proxy - > _ForeignModuleId = kmi . ForeignProxyId ;
proxy - > _Distance = kmi . ModuleDistance ;
break ;
}
}
if ( range . first = = range . second )
{
// no shorter path found, update the proxy
nldebug ( " Gateway '%s' : proxy '%s' path distance changed from %u to %u hop " ,
getGatewayName ( ) . c_str ( ) ,
proxy - > getModuleName ( ) . c_str ( ) ,
proxy - > _Distance ,
newDistance ) ;
proxy - > _Distance = newDistance ;
}
}
else
{
// the new distance is shorter, just update
nldebug ( " Gateway '%s' : proxy '%s' path distance reduced from %u to %u hop " ,
getGatewayName ( ) . c_str ( ) ,
proxy - > getModuleName ( ) . c_str ( ) ,
proxy - > _Distance ,
newDistance ) ;
proxy - > _Distance = newDistance ;
}
// send the distance update
sendModuleDistanceUpdate ( proxy ) ;
}
}
void onReceiveModuleSecurityUpdate ( CGatewayRoute * from , const CMessage & msgin )
{
H_AUTO ( CModuleGetaway_onReceiveModuleSecurityUpdate ) ;
// TModuleId foreignModuleId;
// TSecurityData *modSec;
TModuleSecurityChangeMsg secChg ;
nlRead ( msgin , serial , secChg ) ;
// msgin.serial(foreignModuleId);
// msgin.serialPolyPtr(modSec);
const TModuleId * pModuleId = from - > ForeignToLocalIdx . getB ( secChg . ModuleId ) ;
if ( pModuleId = = NULL )
{
nlwarning ( " LNETL6 : receive module security update for unknown module foreign proxy %u " , secChg . ModuleId ) ;
return ;
}
TModuleId moduleId = * pModuleId ;
CModuleProxy * modProx = getModuleProxy ( moduleId ) ;
if ( modProx = = NULL )
{
nlwarning ( " LNETL6 : receive module security update for unknown module proxy %u, foreign %u " , moduleId , secChg . ModuleId ) ;
return ;
}
// allow the security plug-in to affect the data
if ( _SecurityPlugin ! = NULL )
{
// let the plug-in update the security data
_SecurityPlugin - > onNewSecurityData ( from , modProx , secChg . SecDesc . SecurityData ) ;
}
else
{
// update the security data in the proxy
replaceAllSecurityDatas ( modProx , secChg . SecDesc . SecurityData ) ;
}
// warn local module about new security data
{
TPluggedModules : : TAToBMap : : const_iterator first ( _PluggedModules . getAToBMap ( ) . begin ( ) ) , last ( _PluggedModules . getAToBMap ( ) . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModule * module = first - > second ;
module - > onModuleSecurityChange ( modProx ) ;
}
}
// update the security to peers
{
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
if ( isModuleProxyVisible ( modProx , route ) )
{
updateModuleSecurityDataToRoute ( route , modProx ) ;
}
}
}
}
virtual void onAddModuleProxy ( IModuleProxy * addedModule )
{
H_AUTO ( CModuleGetaway_onAddmoduleProxy ) ;
// disclose module to local modules
discloseModule ( addedModule ) ;
// and send module info to any route
// for each route
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
// only send info to other routes
if ( isModuleProxyVisible ( addedModule , route ) )
{
discloseModuleToRoute ( route , addedModule ) ;
}
}
}
virtual void onRemoveModuleProxy ( IModuleProxy * removedModule )
{
H_AUTO ( CModuleGetaway_onRemoveModuleProxy ) ;
// for each route
{
// for each route
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
// only send info to other routes
if ( isModuleProxyVisible ( removedModule , route ) )
{
undiscloseModuleToRoute ( route , removedModule ) ;
}
}
}
// warn any locally plugged module
{
TPluggedModules : : TAToBMap : : const_iterator first ( _PluggedModules . getAToBMap ( ) . begin ( ) ) , last ( _PluggedModules . getAToBMap ( ) . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModule * module = first - > second ;
if ( removedModule - > getGatewayRoute ( ) ! = NULL
| | module - > getModuleId ( ) ! = removedModule - > getForeignModuleId ( ) )
{
module - > _onModuleDown ( removedModule ) ;
}
}
}
}
virtual void discloseModule ( IModuleProxy * moduleProxy )
throw ( EGatewayNotConnected )
{
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 ( moduleProxy - > getGatewayRoute ( ) ! = NULL
| | module - > getModuleId ( ) ! = moduleProxy - > getForeignModuleId ( ) )
{
module - > _onModuleUp ( moduleProxy ) ;
}
}
}
virtual IModuleProxy * getPluggedModuleProxy ( IModule * pluggedModule )
{
TLocalModuleIndex : : iterator it ( _LocalModuleIndex . find ( pluggedModule - > getModuleId ( ) ) ) ;
if ( it = = _LocalModuleIndex . end ( ) )
return NULL ;
else
{
TModuleProxies : : iterator it2 ( _ModuleProxies . find ( it - > second ) ) ;
nlassert ( it2 ! = _ModuleProxies . end ( ) ) ;
return it2 - > second ;
}
}
virtual uint32 getProxyCount ( ) const
{
return ( uint32 ) _ModuleProxies . 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 < IModuleProxy * > & resultList ) const
{
TModuleProxies : : const_iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
resultList . push_back ( first - > second ) ;
}
}
virtual void sendModuleMessage ( IModuleProxy * senderProxy , IModuleProxy * addresseeProxy , const NLNET : : CMessage & message )
{
H_AUTO ( CModuleGetaway_sendModuleMessage ) ;
// manage firewall
if ( addresseeProxy - > getGatewayRoute ( )
& & addresseeProxy - > getGatewayRoute ( ) - > getTransport ( ) - > Firewalled )
{
CGatewayRoute * route = addresseeProxy - > getGatewayRoute ( ) ;
// the destination route is firewalled, we need to
// disclose the sender module if it's not already done
if ( route - > FirewallDisclosed . find ( senderProxy - > getModuleProxyId ( ) ) = = route - > FirewallDisclosed . end ( ) )
{
discloseModuleToRoute ( route , senderProxy ) ;
route - > FirewallDisclosed . insert ( senderProxy - > getModuleProxyId ( ) ) ;
}
}
// check for visibility rules
if ( ! isModuleProxyVisible ( addresseeProxy , senderProxy - > getGatewayRoute ( ) ) )
{
nlwarning ( " Module %u '%s' try to send message to %u '%s' but addressee is not visible, message discarded " ,
senderProxy - > getModuleProxyId ( ) ,
senderProxy - > getModuleName ( ) . c_str ( ) ,
addresseeProxy - > getModuleProxyId ( ) ,
addresseeProxy - > getModuleName ( ) . c_str ( ) ) ;
return ;
}
if ( addresseeProxy - > getGatewayRoute ( ) = = NULL )
{
// the module is local, just forward the call to the dispatcher
nlassert ( senderProxy ! = NULL ) ;
nlassert ( _ModuleProxies . find ( senderProxy - > getModuleProxyId ( ) ) ! = _ModuleProxies . end ( ) ) ;
// invert the message for immediate dispatching if needed
if ( ! message . isReading ( ) )
const_cast < CMessage & > ( message ) . invert ( ) ;
// check if the module support immediate dispatching
TModuleId addresseeModId = addresseeProxy - > getForeignModuleId ( ) ;
const TModulePtr * adrcp = _PluggedModules . getB ( addresseeModId ) ;
if ( adrcp = = NULL )
{
nlwarning ( " sendModuleMessage : can't find addressee module %u that is not plugged here ! " , addresseeModId ) ;
return ;
}
IModule * addreseeMod = * adrcp ;
if ( ! addreseeMod - > isImmediateDispatchingSupported ( ) )
{
// dispatch the message at next gateway update
// this provide a coherent behavior between local and distant module message exchange
_LocalMessages . push_back ( TLocalMessage ( ) ) ;
TLocalMessage & lm = _LocalMessages . back ( ) ;
lm . SenderProxyId = senderProxy - > getModuleProxyId ( ) ;
lm . AddresseProxyId = addresseeProxy - > getModuleProxyId ( ) ;
nldebug ( " NETL6 : gateway '%s' : queuing local message '%s' from proxy %u to proxy %u " ,
getModuleName ( ) . c_str ( ) ,
message . getName ( ) . c_str ( ) ,
lm . SenderProxyId ,
lm . AddresseProxyId ) ;
if ( message . hasLockedSubMessage ( ) )
{
lm . Message . assignFromSubMessage ( message ) ;
}
else
{
lm . Message = message ;
}
}
else
{
// immediate dispatching
dispatchModuleMessage ( senderProxy , addresseeProxy , message ) ;
}
}
else
{
// the module is distant, send the message via the route
// create a message for sending
CMessage msgHeader ( " MOD_OP " ) ;
CModuleMessageHeaderCodec : : encode (
msgHeader ,
CModuleMessageHeaderCodec : : mt_oneway ,
senderProxy - > getModuleProxyId ( ) ,
addresseeProxy - > getForeignModuleId ( ) ) ;
// send any pending module info
sendPendingModuleUpdate ( addresseeProxy - > getGatewayRoute ( ) ) ;
// send the header
addresseeProxy - > getGatewayRoute ( ) - > sendMessage ( msgHeader ) ;
// send the message
addresseeProxy - > getGatewayRoute ( ) - > sendMessage ( message ) ;
}
}
virtual void dispatchModuleMessage ( IModuleProxy * senderProxy , IModuleProxy * addresseeProxy , const CMessage & message )
{
H_AUTO ( CModuleGetaway_dispatchModuleMessage ) ;
CMessage : : TMessageType msgType = message . getType ( ) ;
// retrieve the address module from the proxy
nlassert ( addresseeProxy - > getGatewayRoute ( ) = = NULL ) ;
// As the addressee is local, the foreign proxy id is the local module id (a bit triky...)
TModuleId addresseeModId = addresseeProxy - > getForeignModuleId ( ) ;
const TModulePtr * adrcp = _PluggedModules . getB ( addresseeModId ) ;
if ( adrcp = = NULL )
{
nlwarning ( " dispatchModuleMessage : dispatching a message to module %u that is not plugged here ! " , addresseeModId ) ;
return ;
}
IModule * addreseeMod = * adrcp ;
// finally, transmit the message to the module
// addreseeMod->onProcessModuleMessage(senderProxy, message);
try
{
addreseeMod - > onReceiveModuleMessage ( senderProxy , message ) ;
}
catch ( . . . )
{
nlwarning ( " An exception was thrown while dispatching message '%s' from '%s' to '%s' " ,
message . getName ( ) . c_str ( ) ,
senderProxy - > getModuleName ( ) . c_str ( ) ,
addresseeProxy - > getModuleName ( ) . c_str ( ) ) ;
if ( msgType = = CMessage : : Request )
{
// send back an exception message
CMessage except ;
except . setType ( " EXCEPT " , CMessage : : Except ) ;
senderProxy - > sendModuleMessage ( addreseeMod , except ) ;
}
}
}
/***********************************************************
* * Module methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool initModule ( const TParsedCommandLine & initInfo )
{
bool ret = CModuleBase : : initModule ( initInfo ) ;
// no options for now
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 ( )
{
H_AUTO ( CModuleGetaway_onModuleUpdate ) ;
// send waiting local messages
while ( ! _LocalMessages . empty ( ) )
{
TLocalMessage & lm = _LocalMessages . front ( ) ;
IModuleProxy * senderProx = getModuleProxy ( lm . SenderProxyId ) ;
IModuleProxy * addresseeProx = getModuleProxy ( lm . AddresseProxyId ) ;
if ( senderProx = = NULL )
{
nlwarning ( " CStandardGateway : local message dispatching : Failed to retrieve proxy for sender module %u while dispatching message '%s' to %u " ,
lm . SenderProxyId ,
lm . Message . getName ( ) . c_str ( ) ,
lm . AddresseProxyId ) ;
}
else if ( addresseeProx = = NULL )
{
nlwarning ( " CStandardGateway : local message dispatching : Failed to retrieve proxy for addressee module %u while dispatching message '%s' from %u " ,
lm . AddresseProxyId ,
lm . Message . getName ( ) . c_str ( ) ,
lm . SenderProxyId ) ;
}
else
{
// we can dispatch the message
dispatchModuleMessage ( senderProx , addresseeProx , lm . Message ) ;
}
_LocalMessages . pop_front ( ) ;
}
// send pending module un/disclosure
{
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
sendPendingModuleUpdate ( route ) ;
}
}
// update the transports
{
TTransportList : : iterator first ( _Transports . begin ( ) ) , last ( _Transports . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IGatewayTransport * transport = first - > second ;
transport - > update ( ) ;
}
}
}
void onApplicationExit ( )
{
// delete all transport
while ( ! _Transports . empty ( ) )
{
deleteTransport ( _Transports . begin ( ) - > first ) ;
}
}
void onModuleUp ( IModuleProxy * /* moduleProxy */ )
{
}
void onModuleDown ( IModuleProxy * /* moduleProxy */ )
{
}
bool onProcessModuleMessage ( IModuleProxy * /* senderModuleProxy */ , const CMessage & message )
{
// simple message for debug and unit testing
if ( message . getName ( ) = = " DEBUG_MOD_PING " )
{
_PingCounter + + ;
return true ;
}
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 )
{
// the socket implementation already checked that the module is plugged here
// just check that the destination module effectively from here
TLocalModuleIndex : : iterator it ( _LocalModuleIndex . find ( senderModule - > getModuleId ( ) ) ) ;
nlassert ( it ! = _LocalModuleIndex . end ( ) ) ;
// get the sender proxy
TModuleProxies : : iterator it2 ( _ModuleProxies . find ( it - > second ) ) ;
nlassert ( it2 ! = _ModuleProxies . end ( ) ) ;
IModuleProxy * senderProx = it2 - > second ;
// get the addressee proxy
it2 = _ModuleProxies . find ( destModuleProxyId ) ;
nlassert ( it2 ! = _ModuleProxies . end ( ) ) ;
IModuleProxy * destProx = it2 - > second ;
sendModuleMessage ( senderProx , destProx , message ) ;
}
virtual void _broadcastModuleMessage ( IModule * senderModule , const NLNET : : CMessage & message )
throw ( EModuleNotPluggedHere )
{
H_AUTO ( CModuleGetaway__broadcastModuleMessage ) ;
// send the message to all proxies (except the sender module)
TLocalModuleIndex : : iterator it ( _LocalModuleIndex . find ( senderModule - > getModuleId ( ) ) ) ;
nlassert ( it ! = _LocalModuleIndex . end ( ) ) ;
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModuleProxy * proxy = first - > second ;
proxy - > sendModuleMessage ( senderModule , message ) ;
}
}
void onModulePlugged ( IModule * pluggedModule )
{
nldebug ( " NETL6: Gateway %s : plugging module '%s' id=%u " ,
getModuleName ( ) . c_str ( ) ,
pluggedModule - > getModuleName ( ) . c_str ( ) ,
pluggedModule - > getModuleId ( ) ) ;
// A module has just been plugged here, we need to disclose it to 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 ( ) ,
pluggedModule - > getModuleFullyQualifiedName ( ) ,
pluggedModule - > getModuleManifest ( ) ,
pluggedModule - > getModuleId ( ) // the module is local, foreign id is the module id
) ;
// and store it in the proxies container
_ModuleProxies . insert ( make_pair ( modProx - > getModuleProxyId ( ) , modProx ) ) ;
_NameToProxyIdx . add ( CStringMapper : : map ( modProx - > getModuleName ( ) ) , modProx ) ;
// and also in the local module index
_LocalModuleIndex . insert ( make_pair ( pluggedModule - > getModuleId ( ) , modProx - > getModuleProxyId ( ) ) ) ;
// trigger the new module proxy event
onAddModuleProxy ( modProx ) ;
// // disclose the new module to other modules
// discloseModule(modProx);
//
// second, disclose already known proxies in the gateway to the plugged module
{
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModuleProxy * modProx = first - > second ;
// do not send a moduleUp on the module himself !
// either the gateway is non null (distant module), or the
// foreign module id is different of the local module (for local proxy,
// the foreign module id store the local module id).
if ( modProx - > getGatewayRoute ( ) ! = NULL | | modProx - > getForeignModuleId ( ) ! = pluggedModule - > getModuleId ( ) )
{
pluggedModule - > _onModuleUp ( modProx ) ;
}
}
}
}
/// Called just after a module as been effectively unplugged from a socket
void onModuleUnplugged ( IModule * unpluggedModule )
{
nldebug ( " NETL6: Gateway %s : unplugging module '%s' id=%u " ,
getModuleName ( ) . c_str ( ) ,
unpluggedModule - > getModuleName ( ) . c_str ( ) ,
unpluggedModule - > getModuleId ( ) ) ;
// remove the proxy info
TLocalModuleIndex : : iterator it ( _LocalModuleIndex . find ( unpluggedModule - > getModuleId ( ) ) ) ;
nlassert ( it ! = _LocalModuleIndex . end ( ) ) ;
TModuleProxies : : iterator it2 ( _ModuleProxies . find ( it - > second ) ) ;
nlassert ( it2 ! = _ModuleProxies . end ( ) ) ;
IModuleProxy * modProx = it2 - > second ;
// warn the unplugged module that all proxies in this gateway become unavailable
{
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModuleProxy * modProx = first - > second ;
if ( modProx - > getGatewayRoute ( ) ! = NULL
| | modProx - > getForeignModuleId ( ) ! = unpluggedModule - > getModuleId ( ) )
{
unpluggedModule - > _onModuleDown ( modProx ) ;
}
}
}
/// the gateway do the rest of the job
onRemoveModuleProxy ( modProx ) ;
TModuleId localProxyId = modProx - > getModuleProxyId ( ) ;
// remove reference to the proxy
_ModuleProxies . erase ( it2 ) ;
_NameToProxyIdx . removeWithB ( modProx ) ;
_LocalModuleIndex . erase ( it ) ;
// check in the local message queue if some message are to/from
// this module
TLocalMessageList : : iterator first ( _LocalMessages . begin ( ) ) , last ( _LocalMessages . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
TLocalMessage & lm = * first ;
if ( lm . AddresseProxyId = = localProxyId
| | lm . SenderProxyId = = localProxyId )
{
// erase this message !
nlwarning ( " CStandardGateway : while unplugging module %u from the gateway, locale message '%s' from proxy %u to proxy %u is lost " ,
unpluggedModule - > getModuleId ( ) ,
lm . Message . getName ( ) . c_str ( ) ,
lm . SenderProxyId ,
lm . AddresseProxyId ) ;
TLocalMessageList : : iterator next = first ;
+ + next ;
if ( next = = last )
{
_LocalMessages . erase ( first ) ;
break ;
}
else
{
_LocalMessages . erase ( first ) ;
first = next ;
}
}
}
// release the module proxy
IModuleManager : : getInstance ( ) . releaseModuleProxy ( localProxyId ) ;
}
////////////////////////////////////////////////////
// Gateway internal methods
////////////////////////////////////////////////////
void removeForeignModule ( CGatewayRoute * route , TModuleId foreignModuleId )
{
// translate the module id
const TModuleId * pModuleId = route - > ForeignToLocalIdx . getB ( foreignModuleId ) ;
if ( pModuleId = = NULL )
{
// oups !
nlwarning ( " removeForeignModule : unknown foreign module id %u " , foreignModuleId ) ;
return ;
}
TModuleId proxyId = * pModuleId ;
// retrieve the module proxy
TModuleProxies : : iterator it2 ( _ModuleProxies . find ( proxyId ) ) ;
if ( it2 = = _ModuleProxies . end ( ) )
{
// oups !
nlwarning ( " Gateway '%s' : removeForeignModule : can't find proxy for id %u coming from foreign id %u " ,
getGatewayName ( ) . c_str ( ) ,
proxyId ,
foreignModuleId ) ;
// still remove the idx
route - > ForeignToLocalIdx . removeWithA ( foreignModuleId ) ;
return ;
}
CModuleProxy * modProx = static_cast < CModuleProxy * > ( it2 - > second . getPtr ( ) ) ;
// remove module information
pair < TKnownModuleInfos : : iterator , TKnownModuleInfos : : iterator > range ;
range = _KnownModules . equal_range ( modProx - > _FullyQualifiedModuleName ) ;
nlassert ( range . first ! = range . second ) ;
bool found = false ;
for ( ; range . first ! = range . second ; + + range . first )
{
TKnownModuleInfo & kmi = range . first - > second ;
if ( kmi . Route = = route )
{
nldebug ( " Gateway '%s' : removing foreign module info for '%s' " ,
getGatewayName ( ) . c_str ( ) ,
CStringMapper : : unmap ( range . first - > first ) . c_str ( ) ) ;
// we have found the info relative to this module
_KnownModules . erase ( range . first ) ;
found = true ;
break ;
}
}
nlassert ( found = = true ) ;
// NB : stl debug mode don't allow to test with range.first when range;first is erased.
// nlassert(range.first != range.second);
// check if there is another view of this module
// if so, we keep the proxy and, eventually, we update the distance
range = _KnownModules . equal_range ( modProx - > _FullyQualifiedModuleName ) ;
if ( range . first ! = range . second )
{
// clean the translation table
route - > ForeignToLocalIdx . removeWithA ( foreignModuleId ) ;
// we keep the proxy, choose the best route
TKnownModuleInfos : : iterator best ( _KnownModules . end ( ) ) ;
for ( ; range . first ! = range . second ; + + range . first )
{
if ( best = = _KnownModules . end ( )
| | best - > second . ModuleDistance > range . first - > second . ModuleDistance )
best = range . first ;
}
nlassert ( best ! = _KnownModules . end ( ) ) ;
TKnownModuleInfo & kmi = best - > second ;
if ( modProx - > _Route ! = kmi . Route )
{
// the best route has changed, update the proxy
nldebug ( " Gateway '%s' : use a new route for module '%s' from %u to %u hop " ,
getGatewayName ( ) . c_str ( ) ,
modProx - > getModuleName ( ) . c_str ( ) ,
modProx - > _Distance ,
kmi . ModuleDistance ) ;
// update the proxy data
modProx - > _Route = kmi . Route ;
modProx - > _ForeignModuleId = kmi . ForeignProxyId ;
if ( modProx - > _Distance ! = kmi . ModuleDistance )
{
// the distance has changed, update and send the new distance to other gateway
modProx - > _Distance = kmi . ModuleDistance ;
sendModuleDistanceUpdate ( modProx ) ;
}
}
}
else
{
// do not remove proxy for local module from her !
if ( modProx - > _Route ! = NULL )
{
// this module is no longer reachable, remove the proxy
// trigger an event in the gateway
onRemoveModuleProxy ( modProx ) ;
// remove from the proxy list
_NameToProxyIdx . removeWithB ( modProx ) ;
_ModuleProxies . erase ( it2 ) ;
// release the proxy
IModuleManager : : getInstance ( ) . releaseModuleProxy ( proxyId ) ;
}
// clean the translation table
route - > ForeignToLocalIdx . removeWithA ( foreignModuleId ) ;
}
}
void sendModuleDistanceUpdate ( IModuleProxy * proxy )
{
// in fact, don't send immediately, store update in each
// route and wait the next update or module message sending
// to effectively send the update
// for each route
TRouteList : : iterator first ( _Routes . begin ( ) ) , last ( _Routes . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
CGatewayRoute * route = * first ;
if ( isModuleProxyVisible ( proxy , route ) )
{
updateModuleDistanceToRoute ( route , proxy ) ;
// // TODO : optimize by batch sending
// TModuleDistanceChangeMsg mdu;
//
// mdu.ModuleId = proxy->getModuleProxyId();
// mdu.NewDistance = proxy->getModuleDistance()+1;
//
// CMessage msg("MOD_DST_UPD");
// msg.serial(mdu);
//
// sendPendingModuleUpdate(route);
// route->sendMessage(msg);
}
}
}
/// Check if a module can be seen by a route
bool isModuleProxyVisible ( IModuleProxy * proxy , CGatewayRoute * route )
{
if ( route = = NULL )
{
// no route, we can see the proxy
return true ;
}
// check firewall rules
if ( route - > getTransport ( ) - > Firewalled )
{
if ( route - > FirewallDisclosed . find ( proxy - > getModuleProxyId ( ) ) = = route - > FirewallDisclosed . end ( ) )
return false ;
}
// if the module is local, then, it can be seen
if ( proxy - > getGatewayRoute ( ) = = NULL )
return true ;
// if the module is on the same route, it can't be seen (it is seen by the route outbound)
if ( proxy - > getGatewayRoute ( ) = = route )
return false ;
IGatewayTransport * transport = route - > getTransport ( ) ;
// if the module is on a different transport, it can be seen
if ( proxy - > getGatewayRoute ( ) - > getTransport ( ) ! = transport )
{
// we also need to check if this module is known in this route
// CGatewayRoute::TForeignToLocalIdx::iterator it(route->ForeignToLocalIdx.find(proxy->getForeignModuleId()));
if ( route - > ForeignToLocalIdx . getA ( proxy - > getModuleProxyId ( ) ) ! = NULL )
// this module is known in this route, so not invisible
return false ;
// ok, we can see
return true ;
}
// if the transport in not in peer invisible, it can be seen
if ( ! transport - > PeerInvisible )
return true ;
// not visible
return false ;
}
/// Disclose module information to a gateway route
void discloseModuleToRoute ( CGatewayRoute * route , IModuleProxy * proxy )
{
// route->PendingUndisclosure.erase(proxy->getModuleProxyId());
CGatewayRoute : : TPendingEvent pe ;
pe . EventType = CGatewayRoute : : pet_disclose_module ;
pe . ModuleId = proxy - > getModuleProxyId ( ) ;
route - > PendingEvents . push_back ( pe ) ;
// route->PendingDisclosure.insert(proxy);
}
/// Undisclose module information to a gateway route
void undiscloseModuleToRoute ( CGatewayRoute * route , IModuleProxy * proxy )
{
// route->PendingDisclosure.erase(proxy);
// route->PendingUndisclosure.insert(proxy->getModuleProxyId());
// route->FirewallDisclosed.erase(proxy->getModuleProxyId());
CGatewayRoute : : TPendingEvent pe ;
pe . EventType = CGatewayRoute : : pet_undisclose_module ;
pe . ModuleId = proxy - > getModuleProxyId ( ) ;
route - > PendingEvents . push_back ( pe ) ;
route - > FirewallDisclosed . erase ( proxy - > getModuleProxyId ( ) ) ;
}
/// the distance of a module need to be update to peers
void updateModuleDistanceToRoute ( CGatewayRoute * route , IModuleProxy * proxy )
{
CGatewayRoute : : TPendingEvent pe ;
pe . EventType = CGatewayRoute : : pet_update_distance ;
pe . ModuleId = proxy - > getModuleProxyId ( ) ;
route - > PendingEvents . push_back ( pe ) ;
}
/// The security data need to be updated to peers
void updateModuleSecurityDataToRoute ( CGatewayRoute * route , IModuleProxy * proxy )
{
CGatewayRoute : : TPendingEvent pe ;
pe . EventType = CGatewayRoute : : pet_update_security ;
pe . ModuleId = proxy - > getModuleProxyId ( ) ;
route - > PendingEvents . push_back ( pe ) ;
}
void sendPendingModuleUpdate ( CGatewayRoute * route )
{
if ( route - > PendingEvents . empty ( ) )
return ;
CMessage updateMsg ( " MOD_UPD " ) ;
// compil all update in a single message
while ( ! route - > PendingEvents . empty ( ) )
{
CGatewayRoute : : TPendingEvent & pe = route - > PendingEvents . front ( ) ;
switch ( pe . EventType )
{
case CGatewayRoute : : pet_disclose_module :
{
IModuleProxy * proxy = getModuleProxy ( pe . ModuleId ) ;
if ( proxy = = NULL )
break ;
// store the update type
updateMsg . serialShortEnum ( pe . EventType ) ;
// encode the message data
TModuleDescCodec modDesc ( proxy ) ;
updateMsg . serial ( modDesc ) ;
// modDesc.encode(proxy, updateMsg);
}
break ;
case CGatewayRoute : : pet_undisclose_module :
{
// store the update type
updateMsg . serialShortEnum ( pe . EventType ) ;
// store the module id
updateMsg . serial ( pe . ModuleId ) ;
}
break ;
case CGatewayRoute : : pet_update_distance :
{
IModuleProxy * proxy = getModuleProxy ( pe . ModuleId ) ;
if ( proxy = = NULL )
break ;
// store the update type
updateMsg . serialShortEnum ( pe . EventType ) ;
// store module ID and distance
updateMsg . serial ( pe . ModuleId ) ;
uint32 distance = proxy - > getModuleDistance ( ) + 1 ;
updateMsg . serial ( distance ) ;
}
break ;
case CGatewayRoute : : pet_update_security :
{
IModuleProxy * proxy = getModuleProxy ( pe . ModuleId ) ;
if ( proxy = = NULL )
break ;
// store the update type
updateMsg . serialShortEnum ( pe . EventType ) ;
// store module ID and security data
TModuleSecurityChangeMsg secChg ;
secChg . ModuleId = pe . ModuleId ;
secChg . SecDesc . SecurityData = const_cast < TSecurityData * > ( proxy - > getFirstSecurityData ( ) ) ;
updateMsg . serial ( secChg ) ;
// updateMsg.serial(pe.ModuleId);
// TSecurityData *modSec = const_cast<TSecurityData*>(proxy->getFirstSecurityData());
// updateMsg.serialPolyPtr(modSec);
}
break ;
default :
// should not append
nlstop ;
}
route - > PendingEvents . pop_front ( ) ;
}
// now send the message
route - > sendMessage ( updateMsg ) ;
// // send pending module proxy un/disclosure
// if (!route->PendingDisclosure.empty())
// {
// // disclose new module
// TModuleAddMsg message;
// message.Modules.resize(route->PendingDisclosure.size());
//
// std::set<IModuleProxy*>::iterator first(route->PendingDisclosure.begin()), last(route->PendingDisclosure.end());
// for (uint i=0; first != last; ++i, ++first)
// {
// TModuleDescMsg &modDesc = message.Modules[i];
// IModuleProxy *addedModule = *first;
//
// modDesc.ModuleProxyId = addedModule->getModuleProxyId();
// modDesc.ModuleClass = addedModule->getModuleClassName();
// modDesc.ModuleFullName = addedModule->getModuleName();
// modDesc.ModuleDistance = addedModule->getModuleDistance()+1;
// }
// route->PendingDisclosure.clear();
//
// CMessage buffer("MOD_ADD");
// buffer.serial(message);
//
// route->sendMessage(buffer);
// }
// if (!route->PendingUndisclosure.empty())
// {
// // disclose new module
// TModuleRemMsg message;
// std::copy(route->PendingUndisclosure.begin(), route->PendingUndisclosure.end(), back_insert_iterator<vector<TModuleId> >(message.RemovedModules));
// route->PendingUndisclosure.clear();
//
// CMessage buffer("MOD_REM");
// buffer.serial(message);
//
// route->sendMessage(buffer);
// }
}
void getModuleList ( std : : vector < IModuleProxy * > & resultList )
{
TModuleProxies : : iterator first ( _ModuleProxies . begin ( ) ) , last ( _ModuleProxies . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
resultList . push_back ( first - > second ) ;
}
}
NLMISC_COMMAND_HANDLER_TABLE_EXTEND_BEGIN ( CStandardGateway , CModuleBase )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , dump , " dump various information about the gateway statue " , " " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , transportListAvailableClass , " list the available transport class " , " no param " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , transportAdd , " add a new transport to this gateway " , " <transportClass> <instanceName> " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , transportOptions , " set a gateway level option on a transport " , " <transportClass> ( [PeerInvisible] [Firewalled] ) " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , transportCmd , " send a command to a transport " , " [<transportName> ( <cmd specific to transport> )]* " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , transportRemove , " remove an existing transport instance " , " <transportName> " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , securityListAvailableClass , " list the available security class " , " no param " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , securityCreate , " create a security plug-in " , " <securityClassName> " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , securityCommand , " send a command to the security plug-in " , " <cmd specific to plug-in> " )
NLMISC_COMMAND_HANDLER_ADD ( CStandardGateway , securityRemove , " remove the security plug-in " , " no parameter " )
NLMISC_COMMAND_HANDLER_TABLE_END
NLMISC_CLASS_COMMAND_DECL ( securityRemove )
{
nlunreferenced ( rawCommandString ) ;
nlunreferenced ( args ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
if ( _SecurityPlugin = = NULL )
{
log . displayNL ( " No security plug-in ! " ) ;
return true ;
}
removeSecurityPlugin ( ) ;
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( securityCommand )
{
nlunreferenced ( args ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
TParsedCommandLine command ;
if ( ! command . parseParamList ( rawCommandString ) )
{
log . displayNL ( " Invalid command line " ) ;
return false ;
}
if ( command . SubParams . size ( ) < 2 )
{
log . displayNL ( " Invalid command line " ) ;
return false ;
}
if ( _SecurityPlugin = = NULL )
{
log . displayNL ( " No security plug-in ! " ) ;
return true ;
}
sendSecurityCommand ( * command . SubParams [ 1 ] ) ;
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( securityCreate )
{
nlunreferenced ( rawCommandString ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
if ( args . size ( ) ! = 1 )
return false ;
if ( _SecurityPlugin ! = NULL )
{
log . displayNL ( " The gateway already have a security plug-in ! Remove it first " ) ;
return true ;
}
log . displayNL ( " Creating a security plug-in '%s' in gateway '%s' " ,
args [ 0 ] . c_str ( ) ,
getModuleName ( ) . c_str ( ) ) ;
createSecurityPlugin ( args [ 0 ] ) ;
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( securityListAvailableClass )
{
nlunreferenced ( rawCommandString ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
if ( args . size ( ) ! = 0 )
return false ;
vector < string > list ;
NLMISC_GET_FACTORY ( CGatewaySecurity , std : : string ) . fillFactoryList ( list ) ;
log . displayNL ( " List of %u available security class : " , list . size ( ) ) ;
for ( uint i = 0 ; i < list . size ( ) ; + + i )
{
log . displayNL ( " '%s' " , list [ i ] . c_str ( ) ) ;
}
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( transportRemove )
{
nlunreferenced ( rawCommandString ) ;
nlunreferenced ( log ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
if ( args . size ( ) ! = 1 )
return false ;
deleteTransport ( args [ 0 ] ) ;
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( transportCmd )
{
nlunreferenced ( args ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
TParsedCommandLine pcl ;
if ( ! pcl . parseParamList ( rawCommandString ) )
{
log . displayNL ( " Invalid parameter string, parse error " ) ;
return false ;
}
transportCommand ( pcl ) ;
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( transportOptions )
{
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
if ( args . size ( ) < 1 )
return false ;
// parse the params
TParsedCommandLine cl ;
if ( ! cl . parseParamList ( rawCommandString ) )
return false ;
if ( cl . SubParams . size ( ) ! = 2 )
return false ;
string transName = cl . SubParams [ 1 ] - > ParamName ;
if ( _Transports . find ( transName ) = = _Transports . end ( ) )
{
log . displayNL ( " unknown transport '%s' " , transName . c_str ( ) ) ;
return false ;
}
// IGatewayTransport *transport = _Transports.find(transName)->second;
// check for peer invisible
if ( cl . SubParams [ 1 ] - > getParam ( " PeerInvisible " ) )
setTransportPeerInvisible ( transName , true ) ;
else
setTransportPeerInvisible ( transName , false ) ;
// check for firewall mode
if ( cl . SubParams [ 1 ] - > getParam ( " Firewalled " ) )
setTransportFirewallMode ( transName , true ) ;
else
setTransportFirewallMode ( transName , false ) ;
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( transportAdd )
{
nlunreferenced ( rawCommandString ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
if ( args . size ( ) ! = 2 )
return false ;
if ( _Transports . find ( args [ 1 ] ) ! = _Transports . end ( ) )
{
log . displayNL ( " A transport with that name already exist ! " ) ;
return true ;
}
createTransport ( args [ 0 ] , args [ 1 ] ) ;
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( transportListAvailableClass )
{
nlunreferenced ( rawCommandString ) ;
nlunreferenced ( quiet ) ;
nlunreferenced ( human ) ;
if ( args . size ( ) ! = 0 )
return false ;
vector < string > list ;
NLMISC_GET_FACTORY ( IGatewayTransport , std : : string ) . fillFactoryList ( list ) ;
log . displayNL ( " List of %u available transport class : " , list . size ( ) ) ;
for ( uint i = 0 ; i < list . size ( ) ; + + i )
{
log . displayNL ( " '%s' " , list [ i ] . c_str ( ) ) ;
}
return true ;
}
NLMISC_CLASS_COMMAND_DECL ( dump )
{
if ( ! args . empty ( ) )
return false ;
// recall the dump for the module class
NLMISC_CLASS_COMMAND_CALL_BASE ( CModuleBase , dump ) ;
log . displayNL ( " ----------------------------- " ) ;
log . displayNL ( " Dumping gateway information : " ) ;
log . displayNL ( " ----------------------------- " ) ;
log . displayNL ( " The gateway has %u locally plugged module : " , _PluggedModules . getAToBMap ( ) . size ( ) ) ;
{
TPluggedModules : : TAToBMap : : const_iterator first ( _PluggedModules . getAToBMap ( ) . begin ( ) ) , last ( _PluggedModules . getAToBMap ( ) . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
IModule * module = first - > second ;
log . displayNL ( " ID:%5u : \t Name = '%s' \t class = '%s' " ,
module - > getModuleId ( ) ,
module - > getModuleName ( ) . c_str ( ) ,
module - > getModuleClassName ( ) . c_str ( ) ) ;
}
}
log . displayNL ( " The gateway as %u transport activated : " , _Transports . size ( ) ) ;
{
TTransportList : : iterator first ( _Transports . begin ( ) ) , last ( _Transports . end ( ) ) ;
for ( ; first ! = last ; + + first )
{
const string & name = first - > first ;
IGatewayTransport * transport = first - > second ;
log . displayNL ( " Transport '%s' (transport class is '%s') : " ,
name . c_str ( ) ,
transport - > getClassName ( ) . c_str ( ) ) ;
log . displayNL ( " * %s " , transport - > PeerInvisible ? " Peer module are NON visible " : " Peer modules are visible " ) ;
log . displayNL ( " * %s " , transport - > Firewalled ? " Firewall ON " : " Firewall OFF " ) ;
transport - > dump ( log ) ;
}
}
log . displayNL ( " ------------------------------ " ) ;
log . displayNL ( " ------- End of dump ---------- " ) ;
log . displayNL ( " ------------------------------ " ) ;
return true ;
}
} ;
// register the module factory
NLNET_REGISTER_MODULE_FACTORY ( CStandardGateway , " StandardGateway " ) ;
/** Set a security data block. If a bloc of the same type
* already exist in the list , the new one will replace the
* existing one .
*/
void CGatewaySecurity : : setSecurityData ( IModuleProxy * proxy , TSecurityData * securityData )
{
// forward the call to standard gateway
CStandardGateway * sg = static_cast < CStandardGateway * > ( _Gateway ) ;
sg - > setSecurityData ( proxy , securityData ) ;
}
/** Clear a block of security data
* The block is identified by the data tag
*/
bool CGatewaySecurity : : removeSecurityData ( IModuleProxy * proxy , uint8 dataTag )
{
// forward the call to standard gateway
CStandardGateway * sg = static_cast < CStandardGateway * > ( _Gateway ) ;
return sg - > removeSecurityData ( proxy , dataTag ) ;
}
/** Replace the complete set of security data with the new one.
* Security data allocated on the proxy are freed ,
*/
void CGatewaySecurity : : replaceAllSecurityDatas ( IModuleProxy * proxy , TSecurityData * securityData )
{
// forward the call to standard gateway
CStandardGateway * sg = static_cast < CStandardGateway * > ( _Gateway ) ;
sg - > replaceAllSecurityDatas ( proxy , securityData ) ;
}
/** Ask the gateway to resend the security data.
* The plug - in call this method after having changed
* the security info for a plug - in outside of the
* onNewProxy call .
*/
void CGatewaySecurity : : forceSecurityUpdate ( IModuleProxy * proxy )
{
// forward the call to standard gateway
CStandardGateway * sg = static_cast < CStandardGateway * > ( _Gateway ) ;
sg - > forceSecurityUpdate ( proxy ) ;
}
void forceGatewayLink ( )
{
}
} // namespace NLNET