mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
made JsonApiServer an singleton through static method instance()
This commit is contained in:
parent
3b45fc5199
commit
d19d1685de
@ -44,6 +44,9 @@
|
||||
|
||||
/*extern*/ JsonApiServer* jsonApiServer = nullptr;
|
||||
|
||||
const std::string JsonApiServer::DEFAULT_LISTENING_ADDRESS = "127.0.0.1";
|
||||
p3ConfigMgr *JsonApiServer::_config_mgr = nullptr;
|
||||
|
||||
/*static*/ const std::multimap<std::string, std::string>
|
||||
JsonApiServer::corsHeaders =
|
||||
{
|
||||
@ -115,11 +118,33 @@ JsonApiServer::corsOptionsHeaders =
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonApiServer::JsonApiServer(uint16_t port, const std::string& bindAddress,
|
||||
const std::function<bool(const std::string&)> newAccessRequestCallback ) :
|
||||
mPort(port), mBindAddress(bindAddress),
|
||||
mNewAccessRequestCallback(newAccessRequestCallback),
|
||||
configMutex("JsonApiServer config")
|
||||
JsonApiServer& JsonApiServer::instance()
|
||||
{
|
||||
static JsonApiServer *_instance = nullptr;
|
||||
|
||||
if(_instance == NULL)
|
||||
{
|
||||
_instance = new JsonApiServer();
|
||||
|
||||
if(_config_mgr == nullptr)
|
||||
RsErr() << "JsonApiServer::instance() called before JsonApiServer::setConfigManager(). This is a bug!" << std::endl;
|
||||
|
||||
_config_mgr->addConfiguration("jsonapi.cfg",_instance);
|
||||
}
|
||||
|
||||
return *_instance;
|
||||
}
|
||||
|
||||
void JsonApiServer::start(uint16_t port, const std::string& bindAddress, const std::function<bool(const std::string&)> callback)
|
||||
{
|
||||
mPort = port;
|
||||
mBindAddress = bindAddress;
|
||||
mNewAccessRequestCallback = callback;
|
||||
|
||||
RsThread::start("JsonApiServer");
|
||||
}
|
||||
|
||||
JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config")
|
||||
{
|
||||
registerHandler("/rsLoginHelper/createLocation",
|
||||
[this](const std::shared_ptr<rb::Session> session)
|
||||
@ -342,6 +367,10 @@ JsonApiServer::JsonApiServer(uint16_t port, const std::string& bindAddress,
|
||||
} );
|
||||
}, true);
|
||||
|
||||
RsFileHash dummyHash;
|
||||
setFilename("jsonapi.cfg"); // hack
|
||||
loadConfiguration(dummyHash);
|
||||
|
||||
// Generated at compile time
|
||||
#include "jsonapi-wrappers.inl"
|
||||
}
|
||||
|
@ -35,11 +35,11 @@ namespace rb = restbed;
|
||||
|
||||
struct JsonApiServer;
|
||||
|
||||
/**
|
||||
* Pointer to global instance of JsonApiServer
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
extern JsonApiServer* jsonApiServer;
|
||||
// /**
|
||||
// * Pointer to global instance of JsonApiServer
|
||||
// * @jsonapi{development}
|
||||
// */
|
||||
// extern JsonApiServer* jsonApiServer;
|
||||
|
||||
/**
|
||||
* Simple usage
|
||||
@ -53,20 +53,9 @@ extern JsonApiServer* jsonApiServer;
|
||||
struct JsonApiServer : RsSingleJobThread, p3Config
|
||||
{
|
||||
static const uint16_t DEFAULT_PORT = 9092 ;
|
||||
static const std::string DEFAULT_LISTENING_ADDRESS ;
|
||||
|
||||
/**
|
||||
* @brief construct a JsonApiServer instance with given parameters
|
||||
* @param[in] port listening port fpt the JSON API socket
|
||||
* @param[in] bindAddress binding address for the JSON API socket
|
||||
* @param newAccessRequestCallback called when a new auth token is asked to
|
||||
* be authorized via JSON API, the auth token is passed as parameter, and
|
||||
* the callback should return true if the new token get access granted and
|
||||
* false otherwise, this usually requires user interacion to confirm access
|
||||
*/
|
||||
JsonApiServer(
|
||||
uint16_t port = DEFAULT_PORT,
|
||||
const std::string& bindAddress = "127.0.0.1",
|
||||
const std::function<bool(const std::string&)> newAccessRequestCallback = [](const std::string&){return false;} );
|
||||
static JsonApiServer& instance() ;
|
||||
|
||||
/**
|
||||
* @param[in] path Path itno which publish the API call
|
||||
@ -96,6 +85,17 @@ struct JsonApiServer : RsSingleJobThread, p3Config
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* @brief start
|
||||
* Starts the json Api server.
|
||||
*
|
||||
* @param port port to listen to
|
||||
* @param listen_address bind address to listen to
|
||||
*/
|
||||
void start( uint16_t port = DEFAULT_PORT,
|
||||
const std::string& bindAddress = "127.0.0.1",
|
||||
const std::function<bool(const std::string&)> newAccessRequestCallback = [](const std::string&){return false;});
|
||||
|
||||
/**
|
||||
* @brief This function should be used by JSON API clients that aren't
|
||||
* authenticated yet, to ask their token to be authorized, the success or
|
||||
@ -175,10 +175,25 @@ struct JsonApiServer : RsSingleJobThread, p3Config
|
||||
static void version( uint32_t& major, uint32_t& minor, uint32_t& mini,
|
||||
std::string& extra, std::string&human );
|
||||
|
||||
|
||||
static void setConfigMgr(p3ConfigMgr *cfg) { _config_mgr = cfg; }
|
||||
protected:
|
||||
/// @see RsSingleJobThread
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief construct a JsonApiServer instance with given parameters
|
||||
* @param[in] port listening port fpt the JSON API socket
|
||||
* @param[in] bindAddress binding address for the JSON API socket
|
||||
* @param newAccessRequestCallback called when a new auth token is asked to
|
||||
* be authorized via JSON API, the auth token is passed as parameter, and
|
||||
* the callback should return true if the new token get access granted and
|
||||
* false otherwise, this usually requires user interacion to confirm access
|
||||
*/
|
||||
JsonApiServer( );
|
||||
|
||||
|
||||
/// @see p3Config::setupSerialiser
|
||||
virtual RsSerialiser* setupSerialiser();
|
||||
|
||||
@ -191,8 +206,8 @@ private:
|
||||
/// @see p3Config::saveDone
|
||||
virtual void saveDone();
|
||||
|
||||
const uint16_t mPort;
|
||||
const std::string mBindAddress;
|
||||
uint16_t mPort;
|
||||
std::string mBindAddress;
|
||||
rb::Service mService;
|
||||
|
||||
/// Called when new JSON API auth token is requested to be authorized
|
||||
@ -220,5 +235,7 @@ private:
|
||||
return checkRsServicePtrReady(
|
||||
serviceInstance.get(), serviceName, ctx, session );
|
||||
}
|
||||
|
||||
static p3ConfigMgr *_config_mgr;
|
||||
};
|
||||
|
||||
|
@ -173,15 +173,16 @@ void p3ConfigMgr::addConfiguration(std::string file, pqiConfig *conf)
|
||||
}
|
||||
// Also check that the filename is not already registered for another config
|
||||
|
||||
for(std::list<pqiConfig*>::const_iterator it = mConfigs.begin(); it!= mConfigs.end(); ++it)
|
||||
for(std::list<pqiConfig*>::iterator it = mConfigs.begin(); it!= mConfigs.end();)
|
||||
if((*it)->filename == filename)
|
||||
{
|
||||
std::cerr << "!!!!!!!!!! Trying to register a config for file \"" << filename << "\" that is already registered" << std::endl;
|
||||
std::cerr << "!!!!!!!!!! Please correct the code !" << std::endl;
|
||||
return;
|
||||
std::cerr << "(WW) Registering a config for file \"" << filename << "\" that is already registered. Replacing previous component." << std::endl;
|
||||
it = mConfigs.erase(it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
|
||||
conf->setFilename(filename);
|
||||
conf->setFilename(filename);// (cyril) this is quite terrible. The constructor of pqiConfig should take the filename as parameter and hold the information.
|
||||
mConfigs.push_back(conf);
|
||||
}
|
||||
|
||||
|
@ -106,13 +106,12 @@ void setHash(const RsFileHash& h);
|
||||
|
||||
RsMutex cfgMtx;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* This sets the name of the pqi configuation file
|
||||
*/
|
||||
void setFilename(const std::string& name);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @param an index for the Confind which contains list of configuarations that can be tracked
|
||||
*/
|
||||
|
@ -91,7 +91,7 @@ void RsServer::rsGlobalShutDown()
|
||||
mNetMgr->shutdown(); /* Handles UPnP */
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
if(jsonApiServer) jsonApiServer->shutdown();
|
||||
JsonApiServer::instance().shutdown();
|
||||
#endif
|
||||
|
||||
rsAutoProxyMonitor::instance()->stopAllRSShutdown();
|
||||
|
@ -410,10 +410,8 @@ int RsInit::InitRetroShare(const RsConfigOptions& conf)
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
if(rsInitConfig->jsonApiPort)
|
||||
{
|
||||
jsonApiServer = new JsonApiServer( rsInitConfig->jsonApiPort, rsInitConfig->jsonApiBindAddress );
|
||||
jsonApiServer->start("JSON API Server");
|
||||
}
|
||||
JsonApiServer::instance().start(rsInitConfig->jsonApiPort, rsInitConfig->jsonApiBindAddress);
|
||||
|
||||
#endif // ifdef RS_JSONAPI
|
||||
|
||||
return RS_INIT_OK;
|
||||
@ -1214,14 +1212,7 @@ int RsServer::StartupRetroShare()
|
||||
//
|
||||
mPluginsManager->loadPlugins(programatically_inserted_plugins) ;
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
if(jsonApiServer) // JsonApiServer may be disabled at runtime
|
||||
{
|
||||
mConfigMgr->addConfiguration("jsonApi.cfg", jsonApiServer);
|
||||
RsFileHash dummyHash;
|
||||
jsonApiServer->loadConfiguration(dummyHash);
|
||||
}
|
||||
#endif
|
||||
JsonApiServer::setConfigMgr(mConfigMgr);
|
||||
|
||||
/**** Reputation system ****/
|
||||
|
||||
@ -1230,7 +1221,7 @@ int RsServer::StartupRetroShare()
|
||||
|
||||
#ifdef RS_ENABLE_GXS
|
||||
|
||||
std::string currGxsDir = RsAccounts::AccountDirectory() + "/gxs";
|
||||
std::string currGxsDir = RsAccounts::AccountDirectory() + "/gxs";
|
||||
RsDirUtil::checkCreateDirectory(currGxsDir);
|
||||
|
||||
RsNxsNetMgr* nxsMgr = new RsNxsNetMgrImpl(serviceCtrl);
|
||||
|
@ -83,7 +83,13 @@ void JsonApiPage::load()
|
||||
whileBlocking(ui.enableCheckBox)->setChecked(Settings->getJsonApiEnabled());
|
||||
whileBlocking(ui.portSpinBox)->setValue(Settings->getJsonApiPort());
|
||||
whileBlocking(ui.listenAddressLineEdit)->setText(Settings->getJsonApiListenAddress());
|
||||
whileBlocking(ui.tokensListView)->setModel(new QStringListModel(Settings->getJsonApiAuthTokens()));
|
||||
|
||||
QStringList newTk;
|
||||
|
||||
for(const auto& it : JsonApiServer::instance().getAuthorizedTokens())
|
||||
newTk.push_back(QString::fromStdString(it.first)+":"+QString::fromStdString(it.second)) ;
|
||||
|
||||
whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk));
|
||||
}
|
||||
|
||||
QString JsonApiPage::helpText() const { return ""; }
|
||||
@ -93,52 +99,38 @@ QString JsonApiPage::helpText() const { return ""; }
|
||||
checkShutdownJsonApi();
|
||||
|
||||
if(Settings->getJsonApiEnabled())
|
||||
{
|
||||
jsonApiServer = new JsonApiServer(
|
||||
Settings->getJsonApiPort(),
|
||||
Settings->getJsonApiListenAddress().toStdString() );
|
||||
jsonApiServer->start("jsonApiServer");
|
||||
|
||||
for(const QString& token : Settings->getJsonApiAuthTokens())
|
||||
jsonApiServer->authorizeToken(token.toStdString());
|
||||
}
|
||||
JsonApiServer::instance().start( Settings->getJsonApiPort(), Settings->getJsonApiListenAddress().toStdString() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ void JsonApiPage::checkShutdownJsonApi()
|
||||
{
|
||||
if(jsonApiServer)
|
||||
{
|
||||
/* It is important to make a copy of +jsonApiServer+ pointer so the old
|
||||
JsonApiServer::instance().shutdown();
|
||||
|
||||
/* It is important to make a copy of +jsonApiServer+ pointer so the old
|
||||
* object can be deleted later, while the original pointer is
|
||||
* reassigned */
|
||||
JsonApiServer* oldJsonApiServer = jsonApiServer;
|
||||
jsonApiServer = nullptr;
|
||||
|
||||
oldJsonApiServer->shutdown();
|
||||
QProgressDialog* pd = new QProgressDialog(
|
||||
"Stopping JSON API Server", QString(), 0, 3000);
|
||||
QTimer* prtm = new QTimer;
|
||||
prtm->setInterval(16); // 60 FPS
|
||||
connect( prtm, &QTimer::timeout,
|
||||
pd, [=](){pd->setValue(pd->value()+16);} );
|
||||
pd->show();
|
||||
prtm->start();
|
||||
|
||||
QProgressDialog* pd = new QProgressDialog(
|
||||
"Stopping JSON API Server", QString(), 0, 3000);
|
||||
QTimer* prtm = new QTimer;
|
||||
prtm->setInterval(16); // 60 FPS
|
||||
connect( prtm, &QTimer::timeout,
|
||||
pd, [=](){pd->setValue(pd->value()+16);} );
|
||||
pd->show();
|
||||
prtm->start();
|
||||
|
||||
/* Must wait for deletion because stopping of the server is async.
|
||||
/* Must wait for deletion because stopping of the server is async.
|
||||
* It is important to capture a copy so it "survive" after
|
||||
* safeStopJsonApiServer returns */
|
||||
QTimer::singleShot(3*1000, [=]()
|
||||
{
|
||||
delete oldJsonApiServer;
|
||||
prtm->stop();
|
||||
pd->close();
|
||||
prtm->deleteLater();
|
||||
pd->deleteLater();
|
||||
});
|
||||
}
|
||||
QTimer::singleShot(3*1000, [=]()
|
||||
{
|
||||
prtm->stop();
|
||||
pd->close();
|
||||
prtm->deleteLater();
|
||||
pd->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
void JsonApiPage::onApplyClicked(bool)
|
||||
@ -150,23 +142,27 @@ void JsonApiPage::onApplyClicked(bool)
|
||||
void JsonApiPage::addTokenClicked(bool)
|
||||
{
|
||||
QString token(ui.tokenLineEdit->text());
|
||||
if(jsonApiServer) jsonApiServer->authorizeToken(token.toStdString());
|
||||
QStringList newTk(Settings->getJsonApiAuthTokens());
|
||||
newTk.removeAll(token);
|
||||
newTk.append(token);
|
||||
Settings->setJsonApiAuthTokens(newTk);
|
||||
JsonApiServer::instance().authorizeToken(token.toStdString());
|
||||
|
||||
QStringList newTk;
|
||||
|
||||
for(const auto& it : JsonApiServer::instance().getAuthorizedTokens())
|
||||
newTk.push_back(QString::fromStdString(it.first)+":"+QString::fromStdString(it.second)) ;
|
||||
|
||||
whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk));
|
||||
}
|
||||
|
||||
void JsonApiPage::removeTokenClicked(bool)
|
||||
{
|
||||
QString token(ui.tokenLineEdit->text());
|
||||
if(jsonApiServer) jsonApiServer->revokeAuthToken(token.toStdString());
|
||||
QStringList newTk(Settings->getJsonApiAuthTokens());
|
||||
newTk.removeAll(token);
|
||||
Settings->setJsonApiAuthTokens(newTk);
|
||||
whileBlocking(ui.tokensListView)->setModel(
|
||||
new QStringListModel(Settings->getJsonApiAuthTokens()) );
|
||||
JsonApiServer::instance().revokeAuthToken(token.toStdString());
|
||||
|
||||
QStringList newTk;
|
||||
|
||||
for(const auto& it : JsonApiServer::instance().getAuthorizedTokens())
|
||||
newTk.push_back(QString::fromStdString(it.first)+":"+QString::fromStdString(it.second)) ;
|
||||
|
||||
whileBlocking(ui.tokensListView)->setModel(new QStringListModel(Settings->getJsonApiAuthTokens()) );
|
||||
}
|
||||
|
||||
void JsonApiPage::tokenClicked(const QModelIndex& index)
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include "rsharesettings.h"
|
||||
#include "gui/MainWindow.h"
|
||||
|
||||
// for this one, we'd rather use a file in retroshare/*h list.
|
||||
#include <jsonapi/jsonapi.h>
|
||||
|
||||
#include <retroshare/rsnotify.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
|
||||
@ -1208,7 +1211,7 @@ void RshareSettings::setJsonApiEnabled(bool enabled)
|
||||
|
||||
uint16_t RshareSettings::getJsonApiPort()
|
||||
{
|
||||
return valueFromGroup("JsonApi", "port", 9092).toUInt();
|
||||
return valueFromGroup("JsonApi", "port", JsonApiServer::DEFAULT_PORT).toUInt();
|
||||
}
|
||||
|
||||
void RshareSettings::setJsonApiPort(uint16_t port)
|
||||
|
@ -233,8 +233,6 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO);
|
||||
|
||||
RsConfigOptions conf;
|
||||
|
||||
conf.jsonApiPort = 0 ; // disable JSon API at start. The JSonAPI preference UI will enable it according to saved parameters.
|
||||
|
||||
argstream as(argc,argv);
|
||||
as >> option('s',"stderr" ,conf.outStderr ,"output to stderr instead of log file." )
|
||||
>> option('u',"udp" ,conf.udpListenerOnly,"Only listen to UDP." )
|
||||
|
Loading…
Reference in New Issue
Block a user