2011-06-16 17:59:26 -04:00
# include <string.h>
# include "pluginmanager.h"
# include <dirent.h>
2011-07-05 16:29:07 -04:00
# include <serialiser/rsserial.h>
# include <serialiser/rstlvbase.h>
# include <serialiser/rstlvtypes.h>
# include <serialiser/rspluginitems.h>
# include <util/rsdir.h>
2011-06-16 17:59:26 -04:00
# include <util/folderiterator.h>
# include <ft/ftserver.h>
# include <dbase/cachestrapper.h>
# include <retroshare/rsplugin.h>
# include <retroshare/rsfiles.h>
# include <pqi/pqiservice.h>
2012-02-02 19:15:49 -05:00
# include <plugins/rscacheservice.h>
# include <plugins/rspqiservice.h>
2011-06-16 17:59:26 -04:00
// lets disable the plugin system for now, as it's unfinished.
2011-06-17 14:51:22 -04:00
# ifdef WINDOWS_SYS
# include "dlfcn_win32.h"
# else
2011-06-16 17:59:26 -04:00
# include <dlfcn.h>
# endif
std : : string RsPluginManager : : _plugin_entry_symbol ;
std : : string RsPluginManager : : _local_cache_dir ;
std : : string RsPluginManager : : _remote_cache_dir ;
2011-06-17 15:59:01 -04:00
std : : vector < std : : string > RsPluginManager : : _plugin_directories ;
2011-06-16 17:59:26 -04:00
ftServer * RsPluginManager : : _ftserver = NULL ;
2011-07-09 20:41:39 -04:00
p3LinkMgr * RsPluginManager : : _linkmgr = NULL ;
2011-06-16 17:59:26 -04:00
typedef RsPlugin * ( * RetroSharePluginEntry ) ( void ) ;
RsPluginHandler * rsPlugins ;
2011-07-05 16:29:07 -04:00
RsPluginManager : : RsPluginManager ( ) : p3Config ( CONFIG_TYPE_PLUGINS )
{
2012-02-18 09:55:50 -05:00
_allow_all_plugins = false ;
2011-07-05 16:29:07 -04:00
}
void RsPluginManager : : loadConfiguration ( )
{
std : : string dummyHash = " dummyHash " ;
p3Config : : loadConfiguration ( dummyHash ) ;
}
2011-10-08 13:47:36 -04:00
void RsPluginManager : : setInterfaces ( RsPlugInInterfaces & interfaces )
{
std : : cerr < < " RsPluginManager::setInterfaces() " < < std : : endl ;
for ( uint32_t i = 0 ; i < _plugins . size ( ) ; + + i )
2012-02-27 13:41:21 -05:00
if ( _plugins [ i ] . plugin ! = NULL )
{
std : : cerr < < " setting iterface for plugin " < < _plugins [ i ] . plugin - > getPluginName ( ) < < " , with RS_ID " < < _plugins [ i ] . plugin - > rs_service_id ( ) < < std : : endl ;
_plugins [ i ] . plugin - > setInterfaces ( interfaces ) ;
}
2011-10-08 13:47:36 -04:00
}
2011-06-16 17:59:26 -04:00
void RsPluginManager : : setCacheDirectories ( const std : : string & local_cache , const std : : string & remote_cache )
{
_local_cache_dir = local_cache ;
_remote_cache_dir = remote_cache ;
}
bool RsPluginManager : : acceptablePluginName ( const std : : string & name )
{
// Needs some windows specific code here
//
# ifdef WINDOWS_SYS
2011-06-17 20:58:09 -04:00
return name . size ( ) > 4 & & name . substr ( name . size ( ) - 4 ) = = " .dll " ;
2011-06-16 17:59:26 -04:00
# else
return name . size ( ) > 3 & & ! strcmp ( name . c_str ( ) + name . size ( ) - 3 , " .so " ) ;
# endif
}
2011-07-05 16:29:07 -04:00
void RsPluginManager : : disablePlugin ( const std : : string & hash )
{
std : : set < std : : string > : : iterator it = _accepted_hashes . find ( hash ) ;
if ( it ! = _accepted_hashes . end ( ) )
{
std : : cerr < < " RsPluginManager::disablePlugin(): removing hash " < < hash < < " from white list " < < std : : endl ;
_accepted_hashes . erase ( it ) ;
IndicateConfigChanged ( ) ;
}
}
void RsPluginManager : : enablePlugin ( const std : : string & hash )
{
if ( _accepted_hashes . find ( hash ) = = _accepted_hashes . end ( ) )
{
std : : cerr < < " RsPluginManager::enablePlugin(): inserting hash " < < hash < < " in white list " < < std : : endl ;
_accepted_hashes . insert ( hash ) ;
IndicateConfigChanged ( ) ;
}
}
2011-06-16 17:59:26 -04:00
void RsPluginManager : : loadPlugins ( const std : : vector < std : : string > & plugin_directories )
{
2011-06-17 15:59:01 -04:00
_plugin_directories = plugin_directories ;
2011-06-16 17:59:26 -04:00
_plugin_entry_symbol = " RETROSHARE_PLUGIN_provide " ;
// 0 - get the list of files to read
for ( uint32_t i = 0 ; i < plugin_directories . size ( ) ; + + i )
{
librs : : util : : FolderIterator dirIt ( plugin_directories [ i ] ) ;
if ( ! dirIt . isValid ( ) )
{
std : : cerr < < " Plugin directory : " < < plugin_directories [ i ] < < " does not exist. " < < std : : endl ;
2011-06-17 15:59:01 -04:00
continue ;
2011-06-16 17:59:26 -04:00
}
while ( dirIt . readdir ( ) )
{
std : : string fname ;
dirIt . d_name ( fname ) ;
std : : string fullname = plugin_directories [ i ] + " / " + fname ;
if ( ! acceptablePluginName ( fullname ) )
continue ;
std : : cerr < < " Found plugin " < < fullname < < std : : endl ;
std : : cerr < < " Loading plugin... " < < std : : endl ;
loadPlugin ( fullname ) ;
}
dirIt . closedir ( ) ;
}
std : : cerr < < " Loaded a total of " < < _plugins . size ( ) < < " plugins. " < < std : : endl ;
}
2011-07-05 16:29:07 -04:00
void RsPluginManager : : getPluginStatus ( int i , uint32_t & status , std : : string & file_name , std : : string & hash , std : : string & error_string ) const
2011-06-16 17:59:26 -04:00
{
2011-07-05 16:29:07 -04:00
if ( ( uint32_t ) i > = _plugins . size ( ) )
return ;
2011-06-16 17:59:26 -04:00
2011-07-05 16:29:07 -04:00
status = _plugins [ i ] . status ;
error_string = _plugins [ i ] . info_string ;
hash = _plugins [ i ] . file_hash ;
file_name = _plugins [ i ] . file_name ;
}
2011-06-16 17:59:26 -04:00
2012-02-18 09:55:50 -05:00
bool RsPluginManager : : getAllowAllPlugins ( ) const
{
return _allow_all_plugins ;
}
void RsPluginManager : : allowAllPlugins ( bool b )
{
_allow_all_plugins = b ;
IndicateConfigChanged ( ) ;
}
2011-07-05 16:29:07 -04:00
RsSerialiser * RsPluginManager : : setupSerialiser ( )
{
RsSerialiser * rss = new RsSerialiser ;
2012-02-18 09:55:50 -05:00
rss - > addSerialType ( new RsPluginSerialiser ( ) ) ;
rss - > addSerialType ( new RsGeneralConfigSerialiser ( ) ) ;
2011-06-16 17:59:26 -04:00
2011-07-05 16:29:07 -04:00
return rss ;
}
2011-06-16 17:59:26 -04:00
2011-12-22 15:17:59 -05:00
void RsPluginManager : : loadPlugins ( const std : : vector < RsPlugin * > & plugins )
{
for ( uint32_t i = 0 ; i < plugins . size ( ) ; + + i )
loadPlugin ( plugins [ i ] ) ;
}
bool RsPluginManager : : loadPlugin ( RsPlugin * p )
{
std : : cerr < < " Loading programmatically inserted plugin " < < std : : endl ;
PluginInfo pinfo ;
pinfo . plugin = p ;
pinfo . file_name = " No file " ;
pinfo . file_hash = " No hash " ;
pinfo . info_string = " " ;
p - > setPlugInHandler ( this ) ; // WIN fix, cannot share global space with shared libraries
// The following choice is conservative by forcing RS to resolve all dependencies at
// the time of loading the plugin.
pinfo . status = PLUGIN_STATUS_LOADED ;
_plugins . push_back ( pinfo ) ;
return true ;
}
2011-07-05 16:29:07 -04:00
bool RsPluginManager : : loadPlugin ( const std : : string & plugin_name )
{
std : : cerr < < " Loading plugin " < < plugin_name < < std : : endl ;
PluginInfo pf ;
pf . plugin = NULL ;
pf . file_name = plugin_name ;
2012-02-18 15:29:03 -05:00
pf . info_string = " " ;
2011-07-05 16:29:07 -04:00
std : : cerr < < " -> hashing. " < < std : : endl ;
uint64_t size ;
if ( ! RsDirUtil : : getFileHash ( plugin_name , pf . file_hash , size ) )
2011-06-16 17:59:26 -04:00
{
2011-07-05 16:29:07 -04:00
std : : cerr < < " -> cannot hash file. Plugin read canceled. " < < std : : endl ;
return false ;
2011-06-16 17:59:26 -04:00
}
2011-07-05 16:29:07 -04:00
// This file can be loaded. Insert an entry into the list of detected plugins.
//
_plugins . push_back ( pf ) ;
PluginInfo & pinfo ( _plugins . back ( ) ) ;
2011-06-16 17:59:26 -04:00
2011-07-05 16:29:07 -04:00
std : : cerr < < " -> hash = " < < pinfo . file_hash < < std : : endl ;
2011-06-16 17:59:26 -04:00
2012-02-18 09:55:50 -05:00
if ( ( ! _allow_all_plugins ) & & _accepted_hashes . find ( pinfo . file_hash ) = = _accepted_hashes . end ( ) )
2011-06-16 17:59:26 -04:00
{
2011-07-05 16:29:07 -04:00
std : : cerr < < " -> hash is not in white list. Plugin is rejected. Go to config->plugins to authorise this plugin. " < < std : : endl ;
pinfo . status = PLUGIN_STATUS_UNKNOWN_HASH ;
pinfo . info_string = " " ;
2011-06-16 17:59:26 -04:00
return false ;
}
2011-07-05 16:29:07 -04:00
else
2011-06-16 17:59:26 -04:00
{
2011-07-05 16:29:07 -04:00
// The following choice is conservative by forcing RS to resolve all dependencies at
// the time of loading the plugin.
int link_mode = RTLD_NOW | RTLD_GLOBAL ;
void * handle = dlopen ( plugin_name . c_str ( ) , link_mode ) ;
if ( handle = = NULL )
{
2012-02-18 15:29:03 -05:00
const char * val = dlerror ( ) ;
std : : cerr < < " Cannot open plugin: " < < val < < std : : endl ;
2011-07-05 16:29:07 -04:00
pinfo . status = PLUGIN_STATUS_DLOPEN_ERROR ;
2012-02-18 15:29:03 -05:00
pinfo . info_string = val ;
2011-07-05 16:29:07 -04:00
return false ;
}
void * pf = dlsym ( handle , _plugin_entry_symbol . c_str ( ) ) ;
if ( pf = = NULL )
{
std : : cerr < < dlerror ( ) < < std : : endl ;
pinfo . status = PLUGIN_STATUS_MISSING_SYMBOL ;
pinfo . info_string = " Symbol " + _plugin_entry_symbol + " is missing. " ;
return false ;
}
std : : cerr < < " Added function entry for symbol " < < _plugin_entry_symbol < < std : : endl ;
RsPlugin * p = ( ( * ( RetroSharePluginEntry ) pf ) ( ) ) ;
if ( p = = NULL )
{
std : : cerr < < " Plugin entry function " < < _plugin_entry_symbol < < " returns NULL ! It should return an object of type RsPlugin* " < < std : : endl ;
pinfo . status = PLUGIN_STATUS_NULL_PLUGIN ;
pinfo . info_string = " Plugin entry " + _plugin_entry_symbol + " () return NULL " ;
return false ;
}
2011-06-16 17:59:26 -04:00
2011-07-05 16:29:07 -04:00
pinfo . status = PLUGIN_STATUS_LOADED ;
pinfo . plugin = p ;
2012-02-27 13:41:21 -05:00
p - > setPlugInHandler ( this ) ; // WIN fix, cannot share global space with shared libraries
2011-07-05 16:29:07 -04:00
pinfo . info_string = " " ;
return true ;
}
2011-06-16 17:59:26 -04:00
}
2011-07-09 20:41:39 -04:00
p3LinkMgr * RsPluginManager : : getLinkMgr ( ) const
2011-06-16 17:59:26 -04:00
{
2011-07-09 20:41:39 -04:00
assert ( _linkmgr ! = NULL ) ;
return _linkmgr ;
2011-06-16 17:59:26 -04:00
}
2011-10-08 13:47:36 -04:00
2011-06-16 17:59:26 -04:00
ftServer * RsPluginManager : : getFileServer ( ) const
{
assert ( _ftserver ! = NULL ) ;
return _ftserver ;
}
const std : : string & RsPluginManager : : getLocalCacheDir ( ) const
{
assert ( ! _local_cache_dir . empty ( ) ) ;
return _local_cache_dir ;
}
const std : : string & RsPluginManager : : getRemoteCacheDir ( ) const
{
assert ( ! _remote_cache_dir . empty ( ) ) ;
return _remote_cache_dir ;
}
void RsPluginManager : : slowTickPlugins ( time_t seconds )
{
for ( uint32_t i = 0 ; i < _plugins . size ( ) ; + + i )
2011-07-05 16:29:07 -04:00
if ( _plugins [ i ] . plugin ! = NULL & & _plugins [ i ] . plugin - > rs_cache_service ( ) ! = NULL & & ( seconds % _plugins [ i ] . plugin - > rs_cache_service ( ) - > tickDelay ( ) ) )
2011-06-16 17:59:26 -04:00
{
2011-07-05 16:29:07 -04:00
std : : cerr < < " ticking plugin " < < _plugins [ i ] . plugin - > getPluginName ( ) < < std : : endl ;
_plugins [ i ] . plugin - > rs_cache_service ( ) - > tick ( ) ;
2011-06-16 17:59:26 -04:00
}
}
void RsPluginManager : : registerCacheServices ( )
{
std : : cerr < < " Registering cache services. " < < std : : endl ;
for ( uint32_t i = 0 ; i < _plugins . size ( ) ; + + i )
2011-07-05 16:29:07 -04:00
if ( _plugins [ i ] . plugin ! = NULL & & _plugins [ i ] . plugin - > rs_cache_service ( ) ! = NULL )
2011-06-16 17:59:26 -04:00
{
2011-07-05 16:29:07 -04:00
rsFiles - > getCacheStrapper ( ) - > addCachePair ( CachePair ( _plugins [ i ] . plugin - > rs_cache_service ( ) , _plugins [ i ] . plugin - > rs_cache_service ( ) , CacheId ( _plugins [ i ] . plugin - > rs_service_id ( ) , 0 ) ) ) ;
std : : cerr < < " adding new cache pair for plugin " < < _plugins [ i ] . plugin - > getPluginName ( ) < < " , with RS_ID " < < _plugins [ i ] . plugin - > rs_service_id ( ) < < std : : endl ;
2011-06-16 17:59:26 -04:00
}
}
void RsPluginManager : : registerClientServices ( p3ServiceServer * pqih )
{
std : : cerr < < " Registering pqi services. " < < std : : endl ;
for ( uint32_t i = 0 ; i < _plugins . size ( ) ; + + i )
2011-07-05 16:29:07 -04:00
if ( _plugins [ i ] . plugin ! = NULL & & _plugins [ i ] . plugin - > rs_pqi_service ( ) ! = NULL )
2011-06-16 17:59:26 -04:00
{
2011-07-05 16:29:07 -04:00
pqih - > addService ( _plugins [ i ] . plugin - > rs_pqi_service ( ) ) ;
std : : cerr < < " Added pqi service for plugin " < < _plugins [ i ] . plugin - > getPluginName ( ) < < std : : endl ;
2011-06-16 17:59:26 -04:00
}
}
void RsPluginManager : : addConfigurations ( p3ConfigMgr * ConfigMgr )
{
std : : cerr < < " Registering configuration files. " < < std : : endl ;
for ( uint32_t i = 0 ; i < _plugins . size ( ) ; + + i )
2011-07-05 16:29:07 -04:00
if ( _plugins [ i ] . plugin ! = NULL & & _plugins [ i ] . plugin - > configurationFileName ( ) . length ( ) > 0 )
2011-06-16 17:59:26 -04:00
{
2012-02-18 15:29:03 -05:00
if ( _plugins [ i ] . plugin - > rs_cache_service ( ) ! = NULL )
ConfigMgr - > addConfiguration ( _plugins [ i ] . plugin - > configurationFileName ( ) , _plugins [ i ] . plugin - > rs_cache_service ( ) ) ;
else if ( _plugins [ i ] . plugin - > rs_pqi_service ( ) ! = NULL )
ConfigMgr - > addConfiguration ( _plugins [ i ] . plugin - > configurationFileName ( ) , _plugins [ i ] . plugin - > rs_pqi_service ( ) ) ;
else
continue ;
2011-07-05 16:29:07 -04:00
std : : cerr < < " Added configuration for plugin " < < _plugins [ i ] . plugin - > getPluginName ( ) < < " , with file " < < _plugins [ i ] . plugin - > configurationFileName ( ) < < std : : endl ;
2011-06-16 17:59:26 -04:00
}
}
2011-07-05 16:29:07 -04:00
bool RsPluginManager : : loadList ( std : : list < RsItem * > & list )
{
_accepted_hashes . clear ( ) ;
std : : cerr < < " RsPluginManager::loadList(): " < < std : : endl ;
std : : list < RsItem * > : : iterator it ;
for ( it = list . begin ( ) ; it ! = list . end ( ) ; it + + )
{
RsPluginHashSetItem * vitem = dynamic_cast < RsPluginHashSetItem * > ( * it ) ;
if ( vitem )
for ( std : : list < std : : string > : : const_iterator it ( vitem - > hashes . ids . begin ( ) ) ; it ! = vitem - > hashes . ids . end ( ) ; + + it )
{
_accepted_hashes . insert ( * it ) ;
std : : cerr < < " loaded hash " < < * it < < std : : endl ;
}
2012-02-18 09:55:50 -05:00
RsConfigKeyValueSet * witem = dynamic_cast < RsConfigKeyValueSet * > ( * it ) ;
if ( witem )
{
for ( std : : list < RsTlvKeyValue > : : const_iterator kit = witem - > tlvkvs . pairs . begin ( ) ; kit ! = witem - > tlvkvs . pairs . end ( ) ; + + kit )
if ( ( * kit ) . key = = " ALLOW_ALL_PLUGINS " )
{
std : : cerr < < " WARNING: Allowing all plugins. No hash will be checked. Be careful! " < < std : : endl ;
_allow_all_plugins = ( kit - > value = = " YES " ) ;
}
}
2011-07-05 16:29:07 -04:00
delete ( * it ) ;
}
return true ;
}
bool RsPluginManager : : saveList ( bool & cleanup , std : : list < RsItem * > & list )
{
cleanup = true ;
RsPluginHashSetItem * vitem = new RsPluginHashSetItem ( ) ;
for ( std : : set < std : : string > : : const_iterator it ( _accepted_hashes . begin ( ) ) ; it ! = _accepted_hashes . end ( ) ; + + it )
vitem - > hashes . ids . push_back ( * it ) ;
list . push_back ( vitem ) ;
2012-02-18 09:55:50 -05:00
RsConfigKeyValueSet * witem = new RsConfigKeyValueSet ;
RsTlvKeyValue kv ;
kv . key = " ALLOW_ALL_PLUGINS " ;
kv . value = _allow_all_plugins ? " YES " : " NO " ;
witem - > tlvkvs . pairs . push_back ( kv ) ;
list . push_back ( witem ) ;
2011-07-05 16:29:07 -04:00
return true ;
}
2011-10-08 13:47:36 -04:00
RsCacheService : : RsCacheService ( uint16_t service_type , uint32_t config_type , uint32_t tick_delay , RsPluginHandler * pgHandler )
: CacheSource ( service_type , true , pgHandler - > getFileServer ( ) - > getCacheStrapper ( ) , pgHandler - > getLocalCacheDir ( ) ) ,
CacheStore ( service_type , true , pgHandler - > getFileServer ( ) - > getCacheStrapper ( ) , pgHandler - > getFileServer ( ) - > getCacheTransfer ( ) , pgHandler - > getRemoteCacheDir ( ) ) ,
2011-06-16 17:59:26 -04:00
p3Config ( config_type ) , // CONFIG_TYPE_RANK_LINK
_tick_delay_in_seconds ( tick_delay )
{
}
2012-02-28 13:25:57 -05:00
RsPQIService : : RsPQIService ( uint16_t service_type , uint32_t config_type , uint32_t /*tick_delay_in_seconds*/ , RsPluginHandler * /*pgHandler*/ )
2012-02-18 15:29:03 -05:00
: p3Service ( service_type ) , p3Config ( config_type )
{
}