mirror of
https://github.com/RetroShare/libretroshare.git
synced 2026-09-14 11:05:45 +05:00
Merge f482b3e204 into 2f093fd7b3
This commit is contained in:
commit
9d5dc36d45
@ -155,6 +155,7 @@ bool RsJsonApi::parseToken(
|
||||
}
|
||||
|
||||
JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
||||
mResourceProvidersMutex("JsonApiServer resource providers"),
|
||||
mService(nullptr),
|
||||
mListeningPort(RsJsonApi::DEFAULT_PORT),
|
||||
mBindingAddress(RsJsonApi::DEFAULT_BINDING_ADDRESS),
|
||||
@ -836,7 +837,10 @@ void JsonApiServer::handleCorsOptions(
|
||||
|
||||
void JsonApiServer::registerResourceProvider(const JsonApiResourceProvider& rp)
|
||||
{
|
||||
mResourceProviders.insert(rp);
|
||||
{
|
||||
RS_STACK_MUTEX(mResourceProvidersMutex);
|
||||
mResourceProviders.insert(rp);
|
||||
}
|
||||
|
||||
if(rsEvents)
|
||||
{
|
||||
@ -847,7 +851,10 @@ void JsonApiServer::registerResourceProvider(const JsonApiResourceProvider& rp)
|
||||
}
|
||||
void JsonApiServer::unregisterResourceProvider(const JsonApiResourceProvider& rp)
|
||||
{
|
||||
mResourceProviders.erase(rp);
|
||||
{
|
||||
RS_STACK_MUTEX(mResourceProvidersMutex);
|
||||
mResourceProviders.erase(rp);
|
||||
}
|
||||
|
||||
if(rsEvents)
|
||||
{
|
||||
@ -857,10 +864,14 @@ void JsonApiServer::unregisterResourceProvider(const JsonApiResourceProvider& rp
|
||||
}
|
||||
}
|
||||
bool JsonApiServer::hasResourceProvider(const JsonApiResourceProvider& rp)
|
||||
{ return mResourceProviders.find(rp) != mResourceProviders.end(); }
|
||||
|
||||
const std::set<std::reference_wrapper<const JsonApiResourceProvider>,std::less<const JsonApiResourceProvider> >& JsonApiServer::getResourceProviders() const
|
||||
{
|
||||
RS_STACK_MUTEX(mResourceProvidersMutex);
|
||||
return mResourceProviders.find(rp) != mResourceProviders.end();
|
||||
}
|
||||
|
||||
RsJsonApi::ResourceProviderSet JsonApiServer::getResourceProviders() const
|
||||
{
|
||||
RS_STACK_MUTEX(mResourceProvidersMutex);
|
||||
return mResourceProviders;
|
||||
}
|
||||
|
||||
@ -868,7 +879,7 @@ std::vector<std::shared_ptr<rb::Resource> > JsonApiServer::getResources() const
|
||||
{
|
||||
auto tab = mResources;
|
||||
|
||||
for(auto& rp: mResourceProviders)
|
||||
for(auto& rp: getResourceProviders())
|
||||
for(auto r: rp.get().getResources()) tab.push_back(r);
|
||||
|
||||
return tab;
|
||||
|
||||
@ -64,8 +64,8 @@ public:
|
||||
|
||||
std::vector<std::shared_ptr<rb::Resource>> getResources() const;
|
||||
|
||||
/// @see RsJsonApi
|
||||
const std::set<std::reference_wrapper<const JsonApiResourceProvider>,std::less<const JsonApiResourceProvider> >& getResourceProviders() const override;
|
||||
/// @see RsJsonApi
|
||||
ResourceProviderSet getResourceProviders() const override;
|
||||
|
||||
/// @see RsJsonApi
|
||||
void fullstop() override { RsThread::fullstop(); }
|
||||
@ -180,6 +180,7 @@ private:
|
||||
/// Encrypted persistent storage for authorized JSON API tokens
|
||||
JsonApiServerAuthTokenStorage mAuthTokenStorage;
|
||||
RsMutex configMutex;
|
||||
mutable RsMutex mResourceProvidersMutex;
|
||||
|
||||
static const std::multimap<std::string, std::string> corsHeaders;
|
||||
static const std::multimap<std::string, std::string> corsOptionsHeaders;
|
||||
|
||||
@ -371,7 +371,17 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time)
|
||||
pinfo.info_string = "" ;
|
||||
dlclose(handle);
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
if(pinfo.API_version != RS_PLUGIN_API_VERSION)
|
||||
{
|
||||
std::cerr << " -> Incompatible plugin API version "
|
||||
<< std::hex << pinfo.API_version << "; expected "
|
||||
<< RS_PLUGIN_API_VERSION << std::dec << std::endl;
|
||||
pinfo.status = PLUGIN_STATUS_WRONG_API;
|
||||
pinfo.info_string = "Incompatible plugin API version";
|
||||
dlclose(handle);
|
||||
return false;
|
||||
}
|
||||
#ifdef TO_REMOVE
|
||||
if(pinfo.svn_revision == 0)
|
||||
{
|
||||
|
||||
@ -37,6 +37,11 @@ class RsJsonApi;
|
||||
/**
|
||||
* Pointer to global instance of RsJsonApi service implementation
|
||||
* @jsonapi{development}
|
||||
*
|
||||
* Beware that non-null does not imply configured: RsServer::StartupRetroShare()
|
||||
* creates the server early so plugins can register resource providers, while
|
||||
* the config manager, the authorized tokens, the listening port and the binding
|
||||
* address are only applied later by RsInit::startupWebServices().
|
||||
*/
|
||||
extern RsJsonApi* rsJsonApi;
|
||||
|
||||
@ -203,15 +208,21 @@ public:
|
||||
*/
|
||||
virtual void connectToConfigManager(p3ConfigMgr& cfgmgr) = 0;
|
||||
|
||||
using ResourceProviderSet = std::set<
|
||||
std::reference_wrapper<const JsonApiResourceProvider>,
|
||||
std::less<const JsonApiResourceProvider> >;
|
||||
|
||||
/**
|
||||
* This is used to add/remove new web services to JsonAPI. The client
|
||||
* should take care of not using a path range already used by the jsonAPI
|
||||
* server
|
||||
* server.
|
||||
* @see getResourceProviders() returns a snapshot by value, so it stays
|
||||
* valid while another thread registers or unregisters a provider.
|
||||
*/
|
||||
virtual void registerResourceProvider(const JsonApiResourceProvider&) = 0;
|
||||
virtual void unregisterResourceProvider(const JsonApiResourceProvider&) = 0;
|
||||
virtual bool hasResourceProvider(const JsonApiResourceProvider&) = 0;
|
||||
virtual const std::set<std::reference_wrapper<const JsonApiResourceProvider>,std::less<const JsonApiResourceProvider> >& getResourceProviders() const =0;
|
||||
virtual ResourceProviderSet getResourceProviders() const = 0;
|
||||
|
||||
/**
|
||||
* @brief This function should be used by JSON API clients that aren't
|
||||
|
||||
@ -38,6 +38,7 @@ extern RsPluginHandler *rsPlugins ;
|
||||
class p3Service ;
|
||||
class RsServiceControl ;
|
||||
class RsReputations ;
|
||||
class RsJsonApi;
|
||||
class RsTurtle ;
|
||||
class RsGxsTunnelService ;
|
||||
class RsDht ;
|
||||
@ -87,10 +88,10 @@ namespace resource_api
|
||||
class StateTokenServer;
|
||||
}
|
||||
|
||||
// Plugin API version. Not used yet, but will be in the future the
|
||||
// main value that decides for compatibility.
|
||||
// Plugin API version. RsPluginManager rejects plugins built against a
|
||||
// different version before calling into their ABI.
|
||||
//
|
||||
#define RS_PLUGIN_API_VERSION 0x000101
|
||||
#define RS_PLUGIN_API_VERSION 0x000103
|
||||
|
||||
// Used for the status of plugins.
|
||||
//
|
||||
@ -141,6 +142,9 @@ public:
|
||||
#ifdef RS_USE_WIRE
|
||||
RsUtil::inited_ptr<RsWire> mWire;
|
||||
#endif
|
||||
|
||||
// Keep new members appended so offsets used by older plugins do not move.
|
||||
RsUtil::inited_ptr<RsJsonApi> mJsonApi;
|
||||
};
|
||||
|
||||
class RsPlugin
|
||||
|
||||
@ -445,7 +445,24 @@ void RsInit::startupWebServices(const RsConfigOptions& conf,bool force_start_jso
|
||||
std::cerr << std::endl;
|
||||
RsInfo() << "Configuring web services" ;
|
||||
|
||||
JsonApiServer* jas = new JsonApiServer();
|
||||
// Plugins receive RsPlugInInterfaces during core startup, before the GUI
|
||||
// calls startupWebServices(). Reuse the server created for that handoff so
|
||||
// resource providers registered by plugins are not lost here.
|
||||
JsonApiServer* jas = dynamic_cast<JsonApiServer*>(rsJsonApi);
|
||||
if(!jas)
|
||||
{
|
||||
/* Not reachable today -- rsJsonApi is only ever set to a JsonApiServer,
|
||||
* here and in the plugin handoff of StartupRetroShare(). Should that
|
||||
* change, replacing it silently would leave every plugin holding the
|
||||
* pointer it received in setInterfaces() talking to an abandoned
|
||||
* object, with no trace of why. */
|
||||
if(rsJsonApi)
|
||||
RsErr() << "rsJsonApi is set but is not a JsonApiServer. Replacing "
|
||||
<< "it: plugins still hold the previous pointer.";
|
||||
|
||||
jas = new JsonApiServer();
|
||||
rsJsonApi = jas;
|
||||
}
|
||||
bool jsonapi_needed = force_start_jsonapi;
|
||||
|
||||
// add jsonapi server to config manager so that it can save/load its tokens
|
||||
@ -529,8 +546,6 @@ void RsInit::startupWebServices(const RsConfigOptions& conf,bool force_start_jso
|
||||
}
|
||||
else
|
||||
RsInfo() << " Not starting JSON API, since it is currently not required by any service." ;
|
||||
|
||||
rsJsonApi = jas;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1675,6 +1690,22 @@ int RsServer::StartupRetroShare()
|
||||
#endif
|
||||
interfaces.mServiceControl = serviceCtrl;
|
||||
interfaces.mPluginHandler = mPluginsManager;
|
||||
#ifdef RS_JSONAPI
|
||||
// The GUI configures web services after plugins are initialized. Create
|
||||
// the server now so plugins can register providers in setInterfaces().
|
||||
// startupWebServices() will configure and reuse this same instance later.
|
||||
//
|
||||
// This has to stay *after* the "if (rsJsonApi) connectToConfigManager()"
|
||||
// block above: that block exists for retroshare-service and Android, where
|
||||
// startupWebServices() already ran before login. Creating the server before
|
||||
// it would make the GUI connect the config manager here and again in
|
||||
// startupWebServices(), reloading jsonapi.cfg twice.
|
||||
if(!rsJsonApi)
|
||||
rsJsonApi = new JsonApiServer();
|
||||
interfaces.mJsonApi = rsJsonApi;
|
||||
#else
|
||||
interfaces.mJsonApi = nullptr;
|
||||
#endif
|
||||
// gxs
|
||||
interfaces.mGxsDir = currGxsDir;
|
||||
interfaces.mIdentity = mGxsIdService;
|
||||
@ -1690,8 +1721,42 @@ int RsServer::StartupRetroShare()
|
||||
interfaces.mGxsTunnels = mGxsTunnels;
|
||||
interfaces.mReputations = mReputations;
|
||||
interfaces.mPosted = mPosted;
|
||||
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
// Service and Android start JSON API before plugins are initialized. Take
|
||||
// one snapshot here so all newly registered providers are published with
|
||||
// at most one core-owned restart after every plugin received interfaces.
|
||||
const bool jsonApiWasRunning = rsJsonApi && rsJsonApi->isRunning();
|
||||
const std::size_t jsonApiProviderCount = jsonApiWasRunning ?
|
||||
rsJsonApi->getResourceProviders().size() : 0;
|
||||
#endif
|
||||
mPluginsManager->setInterfaces(interfaces);
|
||||
#ifdef RS_JSONAPI
|
||||
if( jsonApiWasRunning && jsonApiProviderCount !=
|
||||
rsJsonApi->getResourceProviders().size() )
|
||||
{
|
||||
RsInfo() << "Restarting JSON API once to publish plugin resources.";
|
||||
|
||||
/* The restart must not run on the JSON API server thread.
|
||||
* StartupRetroShare() is reached from RsLoginHelper::attemptLogin() and
|
||||
* createLocationV2(), both exposed through the JSON API, and restbed
|
||||
* serves its handlers on the thread that called Service::start(), which
|
||||
* is JsonApiServer::run() itself. restart() calls RsThread::fullstop(),
|
||||
* and joining our own thread makes waitWhileStopping() bail out with an
|
||||
* error instead of waiting; the subsequent RsThread::start() then fails
|
||||
* with "attempt to start already running thread" and the server stays
|
||||
* down for good. The /rsJsonApi/restart handler takes the same care.
|
||||
* Dispatching also keeps the RESTART_BURST_PROTECTION wait, which is
|
||||
* meant to throttle API clients, off the startup path. */
|
||||
RsThread::async([]()
|
||||
{
|
||||
const std::error_condition restartError = rsJsonApi->restart(true);
|
||||
if(restartError)
|
||||
RsErr() << "Failed restarting JSON API after plugin "
|
||||
<< "initialization: " << restartError.message();
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
// now add plugin objects inside the loop:
|
||||
// - client services provided by plugins.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user