mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 16:39:29 -05:00
changed layout of restbed/json/webui so that JsonApi is the only server (with thread functionality in a separate class) and webui is a resource provider
This commit is contained in:
parent
997501a24d
commit
009ed54ce2
@ -376,33 +376,6 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config")
|
||||
#include "jsonapi-wrappers.inl"
|
||||
}
|
||||
|
||||
void JsonApiServer::run()
|
||||
{
|
||||
std::shared_ptr<rb::Settings> settings(new rb::Settings);
|
||||
settings->set_port(mPort);
|
||||
settings->set_bind_address(mBindAddress);
|
||||
settings->set_default_header("Cache-Control", "no-cache");
|
||||
|
||||
{
|
||||
sockaddr_storage tmp;
|
||||
sockaddr_storage_inet_pton(tmp, mBindAddress);
|
||||
sockaddr_storage_setport(tmp, mPort);
|
||||
sockaddr_storage_ipv6_to_ipv4(tmp);
|
||||
RsUrl tmpUrl(sockaddr_storage_tostring(tmp));
|
||||
tmpUrl.setScheme("http");
|
||||
|
||||
std::cerr << "JSON API listening on " << tmpUrl.toString()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
mService.start(settings);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<restbed::Resource> > JsonApiServer::getResources() const
|
||||
{
|
||||
return _resources;
|
||||
}
|
||||
|
||||
void JsonApiServer::registerHandler(
|
||||
const std::string& path,
|
||||
const std::function<void (const std::shared_ptr<restbed::Session>)>& handler,
|
||||
@ -630,8 +603,32 @@ void JsonApiServer::handleCorsOptions(
|
||||
|
||||
int JsonApiServer::status() const
|
||||
{
|
||||
if(isRunning())
|
||||
if(RestbedService::isRunning() && RestbedService::isClient(this))
|
||||
return JSONAPI_STATUS_RUNNING;
|
||||
else
|
||||
return JSONAPI_STATUS_NOT_RUNNING;
|
||||
}
|
||||
|
||||
void JsonApiServer::registerResourceProvider(const JsonApiResourceProvider *rp)
|
||||
{
|
||||
_resource_providers.insert(rp);
|
||||
}
|
||||
void JsonApiServer::unregisterResourceProvider(const JsonApiResourceProvider *rp)
|
||||
{
|
||||
_resource_providers.erase(rp);
|
||||
}
|
||||
bool JsonApiServer::hasResourceProvider(const JsonApiResourceProvider *rp)
|
||||
{
|
||||
return _resource_providers.find(rp) != _resource_providers.end();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<rb::Resource> > JsonApiServer::getResources() const
|
||||
{
|
||||
auto tab = _resources;
|
||||
|
||||
for(auto& rp: _resource_providers)
|
||||
for(auto r: rp->getResources())
|
||||
tab.push_back(r);
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <restbed>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
#include "pqi/p3cfgmgr.h"
|
||||
@ -35,6 +36,16 @@
|
||||
|
||||
namespace rb = restbed;
|
||||
|
||||
class JsonApiResourceProvider
|
||||
{
|
||||
public:
|
||||
JsonApiResourceProvider() {}
|
||||
virtual ~JsonApiResourceProvider() = default;
|
||||
|
||||
virtual std::string getName() const =0;
|
||||
virtual std::vector<std::shared_ptr<rb::Resource> > getResources() const =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple usage
|
||||
* \code{.cpp}
|
||||
@ -50,13 +61,18 @@ public:
|
||||
JsonApiServer() ;
|
||||
virtual ~JsonApiServer() = default;
|
||||
|
||||
// public API
|
||||
// implements RestbedService
|
||||
|
||||
virtual bool restart() override { return RestbedService::restart();}
|
||||
virtual bool stop() override { return RestbedService::stop();}
|
||||
virtual void setListeningPort(uint16_t port) override { RestbedService::setListeningPort(port) ;}
|
||||
virtual void setBindingAddress(const std::string& address) override { RestbedService::setBindAddress(address); }
|
||||
virtual int status() const override;
|
||||
virtual std::vector<std::shared_ptr<rb::Resource> > getResources() const override ;
|
||||
|
||||
// RsJsonAPI public API
|
||||
|
||||
bool restart() override { return RestbedService::restart(); }
|
||||
bool stop() override { return RestbedService::stop();}
|
||||
int status() const override;
|
||||
|
||||
void setListeningPort(uint16_t port) override { return RestbedService::setListeningPort(port); }
|
||||
void setBindingAddress(const std::string& bind_address) override { return RestbedService::setBindAddress(bind_address); }
|
||||
|
||||
virtual void connectToConfigManager(p3ConfigMgr *cfgmgr);
|
||||
|
||||
@ -66,6 +82,10 @@ public:
|
||||
bool isAuthTokenValid(const std::string& token) override;
|
||||
bool requestNewTokenAutorization(const std::string& user) override;
|
||||
|
||||
void registerResourceProvider(const JsonApiResourceProvider *);
|
||||
void unregisterResourceProvider(const JsonApiResourceProvider *);
|
||||
bool hasResourceProvider(const JsonApiResourceProvider *);
|
||||
|
||||
// private API. These methods may be moved to RsJsonAPI so as to be visible in http mode, if needed.
|
||||
|
||||
/**
|
||||
@ -123,7 +143,6 @@ public:
|
||||
protected:
|
||||
/// @see RsSingleJobThread
|
||||
virtual void run();
|
||||
virtual std::vector<std::shared_ptr<rb::Resource> > getResources() const;
|
||||
|
||||
private:
|
||||
|
||||
@ -141,7 +160,6 @@ private:
|
||||
|
||||
uint16_t mPort;
|
||||
std::string mBindAddress;
|
||||
rb::Service mService;
|
||||
|
||||
/// Called when new JSON API auth token is requested to be authorized
|
||||
/// The callback supplies the password to be used to make the token
|
||||
@ -167,10 +185,10 @@ private:
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
const std::shared_ptr<rb::Session> session )
|
||||
{
|
||||
return checkRsServicePtrReady(
|
||||
serviceInstance.get(), serviceName, ctx, session );
|
||||
return checkRsServicePtrReady( serviceInstance.get(), serviceName, ctx, session );
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<rb::Resource> > _resources;
|
||||
std::set<JsonApiResourceProvider *> _resource_providers;
|
||||
};
|
||||
|
||||
|
@ -24,127 +24,63 @@
|
||||
#include "util/rsdebug.h"
|
||||
#include "restbedservice.h"
|
||||
|
||||
class RestbedThread: public RsThread
|
||||
{
|
||||
public:
|
||||
RestbedThread()
|
||||
{
|
||||
_service = std::make_shared<restbed::Service>(); // this is a place holder, in case we request some internal values.
|
||||
_listening_port = 1984;
|
||||
_binding_address = "127.0.0.1";
|
||||
}
|
||||
|
||||
void runloop() override
|
||||
{
|
||||
if(_resources.empty())
|
||||
{
|
||||
RsErr() << "(EE) please call RestbedService::setResources() before launching the service!" << std::endl;
|
||||
return;
|
||||
}
|
||||
auto settings = std::make_shared< restbed::Settings >( );
|
||||
settings->set_port( _listening_port );
|
||||
settings->set_bind_address( _binding_address );
|
||||
settings->set_default_header( "Connection", "close" );
|
||||
|
||||
if(_service->is_up())
|
||||
{
|
||||
std::cerr << "(II) WebUI is already running. Killing it." << std::endl;
|
||||
_service->stop();
|
||||
}
|
||||
|
||||
_service = std::make_shared<restbed::Service>();
|
||||
|
||||
for(auto& r:_resources)
|
||||
_service->publish( r );
|
||||
|
||||
try
|
||||
{
|
||||
std::cerr << "(II) Starting restbed service on port " << std::dec << _listening_port << " and binding address \"" << _binding_address << "\"" << std::endl;
|
||||
_service->start( settings );
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
RsErr() << "Could not start web interface: " << e.what() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << "(II) restbed service stopped." << std::endl;
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
_service->stop();
|
||||
|
||||
RsThread::ask_for_stop();
|
||||
|
||||
while(isRunning())
|
||||
{
|
||||
std::cerr << "(II) shutting down restbed service." << std::endl;
|
||||
rstime::rs_usleep(1000*1000);
|
||||
}
|
||||
}
|
||||
|
||||
void setListeningPort(uint16_t p) { _listening_port = p ; }
|
||||
void setBindAddress(const std::string& bindAddress) { _binding_address = bindAddress ; }
|
||||
void setResources(const std::vector<std::shared_ptr<restbed::Resource> >& r) { _resources = r ; }
|
||||
uint16_t listeningPort() const { return _listening_port;}
|
||||
|
||||
private:
|
||||
std::shared_ptr<restbed::Service> _service;
|
||||
std::vector<std::shared_ptr<restbed::Resource> > _resources;
|
||||
|
||||
uint16_t _listening_port;
|
||||
std::string _binding_address;
|
||||
};
|
||||
|
||||
RestbedService::RestbedService()
|
||||
{
|
||||
_restbed_thread = new RestbedThread();
|
||||
mService = std::make_shared<restbed::Service>(); // this is a place holder, in case we request some internal values.
|
||||
mListeningPort = 9092;
|
||||
mBindingAddress = "127.0.0.1";
|
||||
}
|
||||
RestbedService::~RestbedService()
|
||||
|
||||
void RestbedService::stop()
|
||||
{
|
||||
while(_restbed_thread->isRunning())
|
||||
{
|
||||
stop();
|
||||
std::cerr << "Deleting webUI object while webUI thread is still running. Trying shutdown...." << std::endl;
|
||||
mService->stop();
|
||||
|
||||
RsThread::ask_for_stop();
|
||||
|
||||
while(isRunning())
|
||||
{
|
||||
std::cerr << "(II) shutting down restbed service." << std::endl;
|
||||
rstime::rs_usleep(1000*1000);
|
||||
}
|
||||
delete _restbed_thread;
|
||||
}
|
||||
}
|
||||
|
||||
bool RestbedService::restart()
|
||||
void RestbedService::setListeningPort(uint16_t p) { mListeningPort = p ; }
|
||||
void RestbedService::setBindAddress(const std::string& bindAddress) { mBindingAddress = bindAddress ; }
|
||||
uint16_t RestbedService::listeningPort() const { return mListeningPort;}
|
||||
|
||||
void RestbedService::runloop() override
|
||||
{
|
||||
RsDbg() << "Restarting restbed service listening on port " << _restbed_thread->listeningPort() << std::endl;
|
||||
if(_resources.empty())
|
||||
{
|
||||
RsErr() << "(EE) please call RestbedService::setResources() before launching the service!" << std::endl;
|
||||
return;
|
||||
}
|
||||
auto settings = std::make_shared< restbed::Settings >( );
|
||||
settings->set_port( mListeningPort );
|
||||
settings->set_bind_address( mBindingAddress );
|
||||
settings->set_default_header( "Connection", "close" );
|
||||
|
||||
if(_restbed_thread->isRunning())
|
||||
_restbed_thread->stop();
|
||||
if(mService->is_up())
|
||||
{
|
||||
std::cerr << "(II) WebUI is already running. Killing it." << std::endl;
|
||||
mService->stop();
|
||||
}
|
||||
|
||||
_restbed_thread->setResources(getResources());
|
||||
_restbed_thread->start();
|
||||
return true;
|
||||
mService = std::make_shared<restbed::Service>(); // re-allocating mService is important because it deletes the existing service and therefore leaves the listening port open
|
||||
|
||||
for(auto& r:getResources())
|
||||
mService->publish(r);
|
||||
|
||||
try
|
||||
{
|
||||
std::cerr << "(II) Starting restbed service on port " << std::dec << mListeningPort << " and binding address \"" << mBindingAddress << "\"" << std::endl;
|
||||
mService->start( settings );
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
RsErr() << "Could not start web interface: " << e.what() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << "(II) restbed service stopped." << std::endl;
|
||||
}
|
||||
|
||||
bool RestbedService::stop()
|
||||
{
|
||||
_restbed_thread->stop();
|
||||
return true;
|
||||
}
|
||||
bool RestbedService::isRunning() const
|
||||
{
|
||||
return _restbed_thread->isRunning();
|
||||
}
|
||||
void RestbedService::setListeningPort(uint16_t port)
|
||||
{
|
||||
_restbed_thread->setListeningPort(port);
|
||||
|
||||
if(_restbed_thread->isRunning())
|
||||
restart();
|
||||
}
|
||||
|
||||
void RestbedService::setBindAddress(const std::string& bind_address)
|
||||
{
|
||||
_restbed_thread->setBindAddress(bind_address);
|
||||
|
||||
if(_restbed_thread->isRunning())
|
||||
restart();
|
||||
}
|
||||
|
||||
|
@ -23,26 +23,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <restbed>
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
class RestbedThread;
|
||||
|
||||
class RestbedService
|
||||
class RestbedService: public RsThread
|
||||
{
|
||||
public:
|
||||
RestbedService() ;
|
||||
virtual ~RestbedService();
|
||||
|
||||
bool isRunning() const ;
|
||||
bool restart();
|
||||
bool stop();
|
||||
bool isRunning();
|
||||
|
||||
virtual bool restart();
|
||||
virtual bool stop();
|
||||
void setListeningPort(uint16_t port) ;
|
||||
void setBindAddress(const std::string& bind_address);
|
||||
|
||||
virtual void setListeningPort(uint16_t port) ;
|
||||
virtual void setBindAddress(const std::string& bind_address);
|
||||
// should be overloaded by sub-class in order to provide resources to the restbed Service.
|
||||
|
||||
virtual std::vector<std::shared_ptr<restbed::Resource> > getResources()const =0;
|
||||
virtual std::vector<std::shared_ptr<restbed::Resource> > getResources() const = 0;
|
||||
|
||||
protected:
|
||||
void runloop() override;
|
||||
|
||||
private:
|
||||
RestbedThread *_restbed_thread;
|
||||
std::shared_ptr<restbed::Service> mService; // managed by RestbedService because it needs to be properly deleted when restarted.
|
||||
|
||||
uint16_t mListeningPort;
|
||||
std::string mBindingAddress;
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <string>
|
||||
|
||||
class p3ConfigMgr;
|
||||
class JsonApiResourceProvider;
|
||||
|
||||
class RsJsonAPI
|
||||
{
|
||||
@ -44,6 +45,10 @@ public:
|
||||
|
||||
virtual void connectToConfigManager(p3ConfigMgr *cfgmgr)=0;
|
||||
|
||||
virtual void registerResourceProvider(const JsonApiResourceProvider *)=0;
|
||||
virtual void unregisterResourceProvider(const JsonApiResourceProvider *)=0;
|
||||
virtual bool hasResourceProvider(const JsonApiResourceProvider *)=0;
|
||||
|
||||
/**
|
||||
* @brief Get status of the json api server
|
||||
* @jsonapi{development}
|
||||
|
@ -136,7 +136,7 @@ void p3WebUI::setHtmlFilesDirectory(const std::string& html_dir)
|
||||
|
||||
int p3WebUI::status() const
|
||||
{
|
||||
if(isRunning())
|
||||
if(rsJsonAPI->status()==RsJsonAPI::JSONAPI_STATUS_RUNNING && rsJsonAPI->hasResourceProvider(this))
|
||||
return WEBUI_STATUS_RUNNING;
|
||||
else
|
||||
return WEBUI_STATUS_NOT_RUNNING;
|
||||
@ -153,3 +153,22 @@ void p3WebUI::setUserPassword(const std::string& passwd)
|
||||
std::cerr << "(EE) JsonAPI is not available in this buildof Retroshare! Cannot register a user password for the WebUI" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool p3WebUI::restart()
|
||||
{
|
||||
rsJsonAPI->registerResourceProvider(this);
|
||||
|
||||
return rsJsonAPI->restart();
|
||||
}
|
||||
|
||||
bool p3WebUI::stop()
|
||||
{
|
||||
rsJsonAPI->unregisterResourceProvider(this);
|
||||
|
||||
if(rsJsonAPI->status()==RsJsonAPI::JSONAPI_STATUS_RUNNING)
|
||||
return rsJsonAPI->restart();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,23 +24,26 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "retroshare/rswebui.h"
|
||||
#include "jsonapi/restbedservice.h"
|
||||
#include "jsonapi/jsonapi.h"
|
||||
|
||||
class p3WebUI: public RsWebUI, public RestbedService
|
||||
class p3WebUI: public RsWebUI, public JsonApiResourceProvider
|
||||
{
|
||||
public:
|
||||
p3WebUI(){}
|
||||
virtual ~p3WebUI(){}
|
||||
|
||||
virtual void setHtmlFilesDirectory(const std::string& html_dir) override;
|
||||
// implements RsWebUI
|
||||
|
||||
virtual bool restart() override { return RestbedService::restart();}
|
||||
virtual bool stop() override { return RestbedService::stop();}
|
||||
virtual void setListeningPort(uint16_t port) override { RestbedService::setListeningPort(port) ;}
|
||||
virtual void setBindingAddress(const std::string& address) override { RestbedService::setBindAddress(address) ;}
|
||||
virtual void setHtmlFilesDirectory(const std::string& html_dir) override;
|
||||
virtual void setUserPassword(const std::string& passwd) override;
|
||||
|
||||
virtual int status() const override;
|
||||
virtual bool restart() override ;
|
||||
virtual bool stop() override ;
|
||||
virtual int status() const override;
|
||||
|
||||
// implements JsonApiResourceProvider
|
||||
|
||||
virtual std::string getName() const override { return "Web Interface" ;}
|
||||
virtual std::vector<std::shared_ptr<restbed::Resource> > getResources() const override;
|
||||
};
|
||||
|
||||
|
@ -398,9 +398,9 @@ int RsInit::InitRetroShare(const RsConfigOptions& conf)
|
||||
RsInfo() << "Allocating jsonAPI server (not launched yet) " << std::endl;
|
||||
JsonApiServer *jas = new JsonApiServer();
|
||||
jas->setListeningPort(conf.jsonApiPort);
|
||||
jas->setBindingAddress(conf.jsonApiBindAddress);
|
||||
jas->setBindAddress(conf.jsonApiBindAddress);
|
||||
|
||||
if(conf.jsonApiPort != NULL)
|
||||
if(conf.jsonApiPort != 0)
|
||||
{
|
||||
RsInfo() << "Launching jsonAPI server on port " << conf.jsonApiPort << std::endl;
|
||||
jas->restart();
|
||||
|
Loading…
Reference in New Issue
Block a user