Prepare for merging

This commit is contained in:
Gioacchino Mazzurco 2019-11-27 18:44:10 +01:00
parent b1860d8682
commit 1d4ca64dee
No known key found for this signature in database
GPG key ID: A1FBCA3872E87051
27 changed files with 1442 additions and 992 deletions

View file

@ -4,14 +4,13 @@
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* 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. *
* it under the terms of the GNU Affero General Public License version 3 as *
* published by the Free Software Foundation. *
* *
* 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. *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser 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 <https://www.gnu.org/licenses/>. *
@ -30,7 +29,6 @@
#include "util/rsjson.h"
#include "retroshare/rsfiles.h"
#include "util/radix64.h"
#include "retroshare/rsversion.h"
#include "retroshare/rsinit.h"
#include "util/rsnet.h"
#include "retroshare/rsiface.h"
@ -42,16 +40,18 @@
// Generated at compile time
#include "jsonapi-includes.inl"
/*extern*/ RsJsonAPI* rsJsonAPI = nullptr;
/*extern*/ RsJsonApi* rsJsonApi = nullptr;
const std::string RsJsonAPI::DEFAULT_BINDING_ADDRESS = "127.0.0.1";
const std::string RsJsonApi::DEFAULT_BINDING_ADDRESS = "127.0.0.1";
/*static*/ const std::multimap<std::string, std::string>
JsonApiServer::corsHeaders =
{
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, OPTIONS"},
{ "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" },
{ "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent,"
"X-Requested-With,If-Modified-Since,"
"Cache-Control,Content-Type,Range" },
{ "Access-Control-Expose-Headers", "Content-Length,Content-Range" }
};
@ -60,7 +60,9 @@ JsonApiServer::corsOptionsHeaders =
{
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, OPTIONS"},
{ "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" },
{ "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent,"
"X-Requested-With,If-Modified-Since,"
"Cache-Control,Content-Type,Range" },
{ "Access-Control-Max-Age", "1728000" }, // 20 days
{ "Content-Type", "text/plain; charset=utf-8" },
{ "Content-Length", "0" }
@ -100,7 +102,7 @@ JsonApiServer::corsOptionsHeaders =
/*static*/ bool JsonApiServer::checkRsServicePtrReady(
const void* serviceInstance, const std::string& serviceName,
RsGenericSerializer::SerializeContext& ctx,
const std::shared_ptr<restbed::Session> session)
const std::shared_ptr<rb::Session> session )
{
if(serviceInstance) return true;
@ -117,37 +119,36 @@ JsonApiServer::corsOptionsHeaders =
return false;
}
bool RsJsonAPI::parseToken(const std::string& clear_token,std::string& user,std::string& passwd)
bool RsJsonApi::parseToken(
const std::string& clear_token, std::string& user,std::string& passwd )
{
uint32_t last_index=0;
uint32_t nb_colons=0;
uint32_t colonIndex = 0;
uint32_t colonCounter = 0;
const auto tkLen = clear_token.length();
for(uint32_t i=0;i<clear_token.length();++i)
if(clear_token[i]==':')
{
++nb_colons;
last_index = i;
}
else if(!librs::util::is_alphanumeric(clear_token[i]))
return false;
for(uint32_t i=0; i < tkLen && colonCounter < 2; ++i)
if(clear_token[i] == ':') { ++colonCounter; colonIndex = i; }
else if(!librs::util::is_alphanumeric(clear_token[i])) return false;
if(nb_colons != 1)
return false;
if(colonCounter != 1) return false;
user = clear_token.substr(0,last_index);
passwd = clear_token.substr(last_index+1,(int)clear_token.size()-(int)last_index-1);
user = clear_token.substr(0, colonIndex);
passwd = clear_token.substr(colonIndex + 1);
return true;
}
JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config")
JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
mService(std::make_shared<restbed::Service>()),
mListeningPort(RsJsonApi::DEFAULT_PORT),
mBindingAddress(RsJsonApi::DEFAULT_BINDING_ADDRESS)
{
registerHandler("/rsLoginHelper/createLocation",
[this](const std::shared_ptr<rb::Session> session)
{
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( reqSize, [this](
auto reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( static_cast<size_t>(reqSize), [this](
const std::shared_ptr<rb::Session> session,
const rb::Bytes& body )
{
@ -194,8 +195,8 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config")
registerHandler("/rsLoginHelper/attemptLogin",
[this](const std::shared_ptr<rb::Session> session)
{
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( reqSize, [this](
auto reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( static_cast<size_t>(reqSize), [this](
const std::shared_ptr<rb::Session> session,
const rb::Bytes& body )
{
@ -234,8 +235,8 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config")
registerHandler("/rsControl/rsGlobalShutDown",
[](const std::shared_ptr<rb::Session> session)
{
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( reqSize, [](
auto reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( static_cast<size_t>(reqSize), [](
const std::shared_ptr<rb::Session> session,
const rb::Bytes& body )
{
@ -248,8 +249,8 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config")
registerHandler("/rsFiles/getFileData",
[](const std::shared_ptr<rb::Session> session)
{
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( reqSize, [](
auto reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( static_cast<size_t>(reqSize), [](
const std::shared_ptr<rb::Session> session,
const rb::Bytes& body )
{
@ -415,38 +416,31 @@ void JsonApiServer::registerHandler(
else session->close(rb::UNAUTHORIZED);
} );
mResources.push_back(resource);
mResources.push_back(resource);
}
void JsonApiServer::setNewAccessRequestCallback( const std::function<bool (const std::string&,std::string&)>& callback )
{
mNewAccessRequestCallback = callback;
}
void JsonApiServer::setNewAccessRequestCallback(
const std::function<bool (const std::string&, const std::string&)>& callback )
{ mNewAccessRequestCallback = callback; }
bool JsonApiServer::requestNewTokenAutorization(const std::string& user)
bool JsonApiServer::requestNewTokenAutorization(
const std::string& user, const std::string& passwd )
{
std::string passwd;
if(rsLoginHelper->isLoggedIn() && mNewAccessRequestCallback(user,passwd))
return authorizeUser(user,passwd);
if(rsLoginHelper->isLoggedIn() && mNewAccessRequestCallback(user, passwd))
return authorizeUser(user, passwd);
return false;
}
bool JsonApiServer::isAuthTokenValid(const std::string& token)
{
RS_STACK_MUTEX(configMutex);
std::string user,passwd;
std::string user,passwd;
if(!parseToken(token,user,passwd)) return false;
if(!parseToken(token,user,passwd))
return false;
auto it = mAuthTokenStorage.mAuthorizedTokens.find(user);
if(it == mAuthTokenStorage.mAuthorizedTokens.end())
return false;
auto it = mAuthTokenStorage.mAuthorizedTokens.find(user);
if(it == mAuthTokenStorage.mAuthorizedTokens.end()) return false;
// attempt avoiding +else CRYPTO_memcmp+ being optimized away
int noOptimiz = 1;
@ -455,11 +449,12 @@ bool JsonApiServer::isAuthTokenValid(const std::string& token)
* std::string comparison is usually not constant time on content to be
* faster, so an attacker may use timings to guess authorized tokens */
if( passwd.size() == it->second.size() && ( noOptimiz = CRYPTO_memcmp( passwd.data(), it->second.data(), it->second.size() ) ) == 0 )
return true;
// Make token size guessing harder
else
noOptimiz = CRYPTO_memcmp(passwd.data(), passwd.data(), passwd.size());
if( passwd.size() == it->second.size() &&
( noOptimiz = CRYPTO_memcmp(
passwd.data(), it->second.data(), it->second.size() ) ) == 0 )
return true;
// Make token size guessing harder
else noOptimiz = CRYPTO_memcmp(passwd.data(), passwd.data(), passwd.size());
// attempt avoiding +else CRYPTO_memcmp+ being optimized away
return static_cast<uint32_t>(noOptimiz) + 1 == 0;
@ -482,29 +477,37 @@ bool JsonApiServer::revokeAuthToken(const std::string& token)
return false;
}
void JsonApiServer::connectToConfigManager(p3ConfigMgr *cfgmgr)
void JsonApiServer::connectToConfigManager(p3ConfigMgr& cfgmgr)
{
cfgmgr->addConfiguration("jsonapi.cfg",this);
cfgmgr.addConfiguration("jsonapi.cfg",this);
RsFileHash hash;
loadConfiguration(hash);
RsFileHash hash;
loadConfiguration(hash);
}
bool JsonApiServer::authorizeUser(const std::string& user,const std::string& passwd)
bool JsonApiServer::authorizeUser(
const std::string& user, const std::string& passwd )
{
if(!librs::util::is_alphanumeric(user) || !librs::util::is_alphanumeric(passwd))
{
RsErr() << "Password or username for jsonapi token is not alphanumeric." << std::endl;
return false;
}
if(!librs::util::is_alphanumeric(user))
{
RsErr() << __PRETTY_FUNCTION__ << " User name is not alphanumeric"
<< std::endl;
return false;
}
if(!librs::util::is_alphanumeric(passwd))
{
RsErr() << __PRETTY_FUNCTION__ << " Password is not alphanumeric"
<< std::endl;
return false;
}
RS_STACK_MUTEX(configMutex);
std::string& p(mAuthTokenStorage.mAuthorizedTokens[user]);
if(p != passwd)
std::string& p(mAuthTokenStorage.mAuthorizedTokens[user]);
if(p != passwd)
{
p = passwd;
p = passwd;
IndicateConfigChanged();
}
return true;
@ -519,25 +522,6 @@ bool JsonApiServer::authorizeUser(const std::string& user,const std::string& pas
return decodedToken;
}
/*static*/ std::string JsonApiServer::encodeToken(const std::string& clear_token)
{
std::string encoded;
Radix64::encode( reinterpret_cast<const uint8_t*>(clear_token.c_str()),
clear_token.length(), encoded );
return encoded;
}
/*static*/ void JsonApiServer::version(
uint32_t& major, uint32_t& minor, uint32_t& mini, std::string& extra,
std::string& human )
{
major = RS_MAJOR_VERSION;
minor = RS_MINOR_VERSION;
mini = RS_MINI_VERSION;
extra = RS_EXTRA_VERSION;
human = RS_HUMAN_READABLE_VERSION;
}
RsSerialiser* JsonApiServer::setupSerialiser()
{
RsSerialiser* rss = new RsSerialiser;
@ -575,26 +559,88 @@ void JsonApiServer::handleCorsOptions(
const std::shared_ptr<restbed::Session> session )
{ session->close(rb::NO_CONTENT, corsOptionsHeaders); }
void JsonApiServer::registerResourceProvider(const JsonApiResourceProvider *rp)
{
mResourceProviders.insert(rp);
}
void JsonApiServer::unregisterResourceProvider(const JsonApiResourceProvider *rp)
{
mResourceProviders.erase(rp);
}
bool JsonApiServer::hasResourceProvider(const JsonApiResourceProvider *rp)
{
return mResourceProviders.find(rp) != mResourceProviders.end();
}
void JsonApiServer::registerResourceProvider(const JsonApiResourceProvider& rp)
{ mResourceProviders.insert(rp); }
void JsonApiServer::unregisterResourceProvider(const JsonApiResourceProvider& rp)
{ mResourceProviders.erase(rp); }
bool JsonApiServer::hasResourceProvider(const JsonApiResourceProvider& rp)
{ return mResourceProviders.find(rp) != mResourceProviders.end(); }
std::vector<std::shared_ptr<rb::Resource> > JsonApiServer::getResources() const
{
auto tab = mResources;
auto tab = mResources;
for(auto& rp: mResourceProviders)
for(auto r: rp->getResources())
tab.push_back(r);
for(auto& rp: mResourceProviders)
for(auto r: rp.get().getResources()) tab.push_back(r);
return tab;
return tab;
}
bool JsonApiServer::restart()
{
fullstop();
RsThread::start("JSON API Server");
return true;
}
bool JsonApiServer::fullstop()
{
if(!mService->is_up()) return true;
mService->stop();
RsThread::ask_for_stop();
while(isRunning())
{
RsDbg() << __PRETTY_FUNCTION__ << " shutting down JSON API service."
<< std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
return true;
}
uint16_t JsonApiServer::listeningPort() const { return mListeningPort; }
void JsonApiServer::setListeningPort(uint16_t p) { mListeningPort = p; }
void JsonApiServer::setBindingAddress(const std::string& bindAddress)
{ mBindingAddress = bindAddress; }
std::string JsonApiServer::getBindingAddress() const { return mBindingAddress; }
void JsonApiServer::runloop()
{
auto settings = std::make_shared<restbed::Settings>();
settings->set_port(mListeningPort);
settings->set_bind_address(mBindingAddress);
settings->set_default_header("Connection", "close");
if(mService->is_up())
{
RsWarn() << __PRETTY_FUNCTION__ << " restbed is already running. "
<< " stopping it before starting again!" << std::endl;
mService->stop();
}
/* re-allocating mService is important because it deletes the existing
* service and therefore leaves the listening port open */
mService = std::make_shared<restbed::Service>();
for(auto& r: getResources()) mService->publish(r);
try
{
RsUrl apiUrl; apiUrl.setScheme("http").setHost(mBindingAddress)
.setPort(mListeningPort);
RsDbg() << __PRETTY_FUNCTION__ << " JSON API server listening on "
<< apiUrl.toString() << std::endl;
mService->start(settings);
}
catch(std::exception& e)
{
RsErr() << __PRETTY_FUNCTION__ << " Failure starting JSON API server: "
<< e.what() << std::endl;
print_stacktrace();
return;
}
RsInfo() << __PRETTY_FUNCTION__ << " finished!" << std::endl;
}

View file

@ -4,14 +4,13 @@
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* 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. *
* it under the terms of the GNU Affero General Public License version 3 as *
* published by the Free Software Foundation. *
* *
* 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. *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser 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 <https://www.gnu.org/licenses/>. *
@ -25,12 +24,13 @@
#include <cstdint>
#include <map>
#include <set>
#include <functional>
#include <vector>
#include "util/rsthreads.h"
#include "pqi/p3cfgmgr.h"
#include "rsitems/rsitem.h"
#include "jsonapi/jsonapiitems.h"
#include "jsonapi/restbedservice.h"
#include "retroshare/rsjsonapi.h"
#include "util/rsthreads.h"
@ -39,96 +39,89 @@ namespace rb = restbed;
class JsonApiResourceProvider
{
public:
JsonApiResourceProvider() {}
virtual ~JsonApiResourceProvider() = default;
virtual ~JsonApiResourceProvider() = default;
virtual std::string getName() const =0;
virtual std::vector<std::shared_ptr<rb::Resource> > getResources() const =0;
virtual std::vector<std::shared_ptr<rb::Resource>> getResources() const = 0;
inline bool operator< (const JsonApiResourceProvider& rp) const
{ return this < &rp; }
};
/**
* Simple usage
* \code{.cpp}
* JsonApiServer jas(9092);
* jsonApiServer = &jas;
* jas.start("JsonApiServer");
* \endcode
* Uses p3Config to securely store persistent JSON API authorization tokens
*/
class JsonApiServer : public p3Config, public RestbedService, public RsJsonAPI
class JsonApiServer : public p3Config, public RsThread, public RsJsonApi
{
public:
JsonApiServer() ;
virtual ~JsonApiServer() = default;
JsonApiServer();
~JsonApiServer() override = default;
// implements RestbedService
std::vector<std::shared_ptr<rb::Resource>> getResources() const;
virtual std::vector<std::shared_ptr<rb::Resource> > getResources() const override ;
/// @see RsJsonApi
bool restart() override;
// RsJsonAPI public API
/// @see RsJsonApi
bool fullstop() override;
bool restart() override { return RestbedService::restart(); }
bool stop() override { return RestbedService::fullstop();}
bool isRunning() override { return RestbedService::isRunning(); }
/// @see RsJsonApi
inline bool isRunning() override { return RsThread::isRunning(); }
void setListeningPort(uint16_t port) override { return RestbedService::setListeningPort(port); }
void setBindingAddress(const std::string& bind_address) override { return RestbedService::setBindAddress(bind_address); }
uint16_t listeningPort() const override { return RestbedService::listeningPort() ; }
/// @see RsJsonApi
void setListeningPort(uint16_t port) override;
virtual void connectToConfigManager(p3ConfigMgr *cfgmgr);
/// @see RsJsonApi
void setBindingAddress(const std::string& bindAddress) override;
virtual bool authorizeUser(const std::string& alphanumeric_user,const std::string& alphanumeric_passwd) override;
virtual std::map<std::string,std::string> getAuthorizedTokens() override;
/// @see RsJsonApi
std::string getBindingAddress() const override;
/// @see RsJsonApi
uint16_t listeningPort() const override;
/// @see RsJsonApi
void connectToConfigManager(p3ConfigMgr& cfgmgr) override;
/// @see RsJsonApi
virtual bool authorizeUser(
const std::string& alphanumeric_user,
const std::string& alphanumeric_passwd ) override;
/// @see RsJsonApi
std::map<std::string,std::string> getAuthorizedTokens() override;
/// @see RsJsonApi
bool revokeAuthToken(const std::string& user) override;
/// @see RsJsonApi
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 *);
/// @see RsJsonAPI
bool requestNewTokenAutorization(
const std::string& user, const std::string& password ) override;
// private API. These methods may be moved to RsJsonAPI so as to be visible in http mode, if needed.
/// @see RsJsonApi
void registerResourceProvider(const JsonApiResourceProvider&) override;
/// @see RsJsonApi
void unregisterResourceProvider(const JsonApiResourceProvider&) override;
/// @see RsJsonApi
bool hasResourceProvider(const JsonApiResourceProvider&) override;
/**
* @brief Get decoded version of the given encoded token
* @jsonapi{development,unauthenticated}
* @param[in] radix64_token encoded
* @return token decoded
*/
static std::string decodeToken(const std::string& radix64_token);
/**
* @brief Get encoded version of the given decoded token
* @jsonapi{development,unauthenticated}
* @param[in] clear_token decoded
* @return token encoded
*/
static std::string encodeToken(const std::string& clear_token);
/**
* @brief Write version information to given paramethers
* @jsonapi{development,unauthenticated}
* @param[out] major storage
* @param[out] minor storage
* @param[out] mini storage
* @param[out] extra storage
* @param[out] human storage
*/
static void version( uint32_t& major, uint32_t& minor, uint32_t& mini,
std::string& extra, std::string&human );
// /!\ These methods shouldn't be accessible through http!
/**
* @param[in] path Path itno which publish the API call
* Register an unique handler for a resource path
* @param[in] path Path into which publish the API call
* @param[in] handler function which will be called to handle the requested
* @param[in] requiresAutentication specify if the API call must be
* autenticated or not
* path, the function must be declared like:
* \code{.cpp}
* void functionName(const shared_ptr<restbed::Session> session)
* \endcode
* autenticated or not.
*/
void registerHandler(
const std::string& path,
@ -139,29 +132,29 @@ public:
* @brief Set new access request callback
* @param callback function to call when a new JSON API access is requested
*/
void setNewAccessRequestCallback(const std::function<bool(const std::string&,std::string&)>& callback );
void setNewAccessRequestCallback(
const std::function<bool(const std::string&, const std::string&)>&
callback );
private:
/// @see p3Config::setupSerialiser
virtual RsSerialiser* setupSerialiser();
RsSerialiser* setupSerialiser() override;
/// @see p3Config::saveList
virtual bool saveList(bool &cleanup, std::list<RsItem *>& saveItems);
bool saveList(bool &cleanup, std::list<RsItem *>& saveItems) override;
/// @see p3Config::loadList
virtual bool loadList(std::list<RsItem *>& loadList);
bool loadList(std::list<RsItem *>& loadList) override;
/// @see p3Config::saveDone
virtual void saveDone();
void saveDone() override;
uint16_t mPort;
std::string mBindAddress;
/// Called when new JSON API auth token is requested to be authorized
/// The callback supplies the password to be used to make the token
///
std::function<bool(const std::string&,std::string& passwd)> mNewAccessRequestCallback;
std::function<bool(const std::string&, const std::string& passwd)>
mNewAccessRequestCallback;
/// Encrypted persistent storage for authorized JSON API tokens
JsonApiServerAuthTokenStorage mAuthTokenStorage;
@ -182,10 +175,21 @@ 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> > mResources;
std::set<const JsonApiResourceProvider *> mResourceProviders;
std::vector<std::shared_ptr<rb::Resource>> mResources;
std::set<
std::reference_wrapper<const JsonApiResourceProvider>,
std::less<const JsonApiResourceProvider> > mResourceProviders;
/// @see RsThread
void runloop() override;
std::shared_ptr<restbed::Service> mService;
uint16_t mListeningPort;
std::string mBindingAddress;
};

View file

@ -1,94 +0,0 @@
/*******************************************************************************
* libretroshare/src/jsonapi/: restbedservice.cc *
* *
* libretroshare: retroshare core library *
* *
* Copyright 2019-2019 Cyril Soler *
* *
* 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 Lesser 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 <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include "retroshare/rsjsonapi.h"
#include "util/rsthreads.h"
#include "util/rsdebug.h"
#include "restbedservice.h"
RestbedService::RestbedService()
: mService(std::make_shared<restbed::Service>()), // this is a place holder, in case we request some internal values.
mListeningPort(RsJsonAPI::DEFAULT_PORT),
mBindingAddress(RsJsonAPI::DEFAULT_BINDING_ADDRESS)
{
}
bool RestbedService::restart()
{
fullstop();
start("Restbed Service");
return true;
}
bool RestbedService::fullstop()
{
if(!mService->is_up())
return true;
mService->stop();
RsThread::ask_for_stop();
while(isRunning())
{
std::cerr << "(II) shutting down restbed service." << std::endl;
rstime::rs_usleep(1000*1000);
}
return true;
}
uint16_t RestbedService::listeningPort() const { return mListeningPort ; }
void RestbedService::setListeningPort(uint16_t p) { mListeningPort = p ; }
void RestbedService::setBindAddress(const std::string& bindAddress) { mBindingAddress = bindAddress ; }
void RestbedService::runloop()
{
auto settings = std::make_shared< restbed::Settings >( );
settings->set_port( mListeningPort );
settings->set_bind_address( mBindingAddress );
settings->set_default_header( "Connection", "close" );
if(mService->is_up())
{
RsWarn() << "(II) WebUI is already running. Killing it." << std::endl;
mService->stop();
}
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;
}

View file

@ -172,6 +172,7 @@ HEADERS += plugins/pluginmanager.h \
HEADERS += $$PUBLIC_HEADERS
SOURCES *= services/rsversion.cxx
################################# Linux ##########################################
linux-* {
@ -902,8 +903,8 @@ rs_jsonapi {
# Force recalculation of libretroshare dependencies see https://stackoverflow.com/a/47884045
QMAKE_EXTRA_TARGETS += libretroshare
HEADERS += jsonapi/jsonapi.h jsonapi/jsonapiitems.h jsonapi/restbedservice.h retroshare/rsjsonapi.h
SOURCES += jsonapi/jsonapi.cpp jsonapi/restbedservice.cc
HEADERS += jsonapi/jsonapi.h jsonapi/jsonapiitems.h retroshare/rsjsonapi.h
SOURCES += jsonapi/jsonapi.cpp
}
rs_deep_channels_index {

View file

@ -5,9 +5,8 @@
* Copyright (C) 2019-2019 Cyril Soler <csoler@users.sourceforge.net> *
* *
* 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. *
* it under the terms of the GNU Affero General Public License version 3 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
@ -16,7 +15,7 @@
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
*
* *
*******************************************************************************/
#pragma once
@ -25,113 +24,139 @@
class p3ConfigMgr;
class JsonApiResourceProvider;
class RsJsonApi;
class RsJsonAPI
/**
* Pointer to global instance of RsJsonApi service implementation
* @jsonapi{development}
*/
extern RsJsonApi* rsJsonApi;
class RsJsonApi
{
public:
static const uint16_t DEFAULT_PORT = 9092 ;
static const std::string DEFAULT_BINDING_ADDRESS ; // 127.0.0.1
static const uint16_t DEFAULT_PORT = 9092;
static const std::string DEFAULT_BINDING_ADDRESS; // 127.0.0.1
/**
* @brief Restart RsJsonApi server
* @jsonapi{development}
*/
virtual bool restart() = 0;
/**
* @brief Request RsJsonApi to stop and wait until ti has stopped.
* Be expecially carefull to call this from JSON API because you will loose
* access to the API.
* @jsonapi{development}
*/
virtual bool fullstop() = 0;
virtual bool restart() =0;
virtual bool stop() =0;
/**
* @brief Get status of the json api server
* @jsonapi{development}
* @return Returns true if the server is running
*/
virtual bool isRunning() =0;
virtual bool isRunning() = 0;
/*!
* \brief setBindingAddress
* Sets the binding address of the jsonapi server. Will only take effect after the server is restarted
* \param address
* Address in IPv4 or IPv6 format.
*/
/**
* Sets the binding address of the JSON API server. Will only take effect
* after the server is restarted.
* @jsonapi{development}
* @param[in] address Binding address in IPv4 or IPv6 format.
*/
virtual void setBindingAddress(const std::string& address) = 0;
virtual void setBindingAddress(const std::string& address) =0;
/**
* Get the binding address of the JSON API server.
* @jsonapi{development}
* @return string representing binding address
*/
virtual std::string getBindingAddress() const = 0;
/*!
* \brief setListeningPort
* Port to use when talking to the jsonAPI server.
* \param port
* Should be a non system-reserved 16 bits port number (1024 to 65535)
*/
virtual void setListeningPort(uint16_t port) =0;
virtual uint16_t listeningPort() const =0;
/*!
* Set port on which JSON API server will listen. Will only take effect
* after the server is restarted.
* @jsonapi{development}
* @param[in] port Must be available otherwise the binding will fail
*/
virtual void setListeningPort(uint16_t port) = 0;
/*!
* \brief connectToConfigManager
* Should be called after creating the JsonAPI object so that it publishes itself with the proper config file.
* Since JsonAPI is created *before* login, the config manager does not exist at this time.
* \param cfgmgr
*/
virtual void connectToConfigManager(p3ConfigMgr *cfgmgr)=0;
/*!
* Get port on which JSON API server will listen.
* @jsonapi{development}
*/
virtual uint16_t listeningPort() const = 0;
/*!
* \brief registerResourceProvider
* 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.
*/
virtual void registerResourceProvider(const JsonApiResourceProvider *)=0;
virtual void unregisterResourceProvider(const JsonApiResourceProvider *)=0;
virtual bool hasResourceProvider(const JsonApiResourceProvider *)=0;
/*!
* Should be called after creating the JsonAPI object so that it publishes
* itself with the proper config file.
* Since JsonAPI is created *before* login, the config manager does not
* exist at that time.
* @param cfgmgr
*/
virtual void connectToConfigManager(p3ConfigMgr& cfgmgr) = 0;
/**
* 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
*/
virtual void registerResourceProvider(const JsonApiResourceProvider&) = 0;
virtual void unregisterResourceProvider(const JsonApiResourceProvider&) = 0;
virtual bool hasResourceProvider(const JsonApiResourceProvider&) = 0;
//=============================================================================================//
// API methods that are also accessible through http //
//=============================================================================================//
/**
* @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
* failure will depend on mNewAccessRequestCallback return value, and it
* will likely need human user interaction in the process.
* @jsonapi{development,unauthenticated}
* @param[in] token token to autorize
* @param[in] user user name to authorize
* @param[in] password password for the new user
* @return true if authorization succeded, false otherwise.
*/
virtual bool requestNewTokenAutorization(const std::string& token)=0;
virtual bool requestNewTokenAutorization(
const std::string& user, const std::string& password) = 0;
//=============================================================================================//
// Utility methods //
//=============================================================================================//
/** Split a token in USER:PASSWORD format into user and password */
static bool parseToken(
const std::string& clear_token,
std::string& user, std::string& passwd );
static bool parseToken(const std::string& clear_token,std::string& user,std::string& passwd);
//=============================================================================================//
// API methods that SHOULD NOT be accessible through http //
//=============================================================================================//
//////////////// @Gio: The methods below should not be accessible from the API server !
///
/**
* @brief Add new auth (user,passwd) token to the authorized set, creating the token user:passwd internally.
* @param[in] alphanumeric_user username to autorize decoded
* @param[in] alphanumeric_passwd passwd to autorize decoded
* @return true if the token has been added to authorized, false if error occurred
* Add new auth (user,passwd) token to the authorized set, creating the
* token user:passwd internally.
* @jsonapi{development}
* @param[in] user user name to autorize, must be alphanumerinc
* @param[in] password password for the user, must be alphanumerinc
* @return true if the token has been added to authorized, false if error
* occurred
*/
virtual bool authorizeUser(const std::string& alphanumeric_user,const std::string& alphanumeric_passwd)=0;
virtual bool authorizeUser(
const std::string& user, const std::string& password ) = 0;
/**
* @brief Revoke given auth token
* @param[in] user par of the decoded token
* @jsonapi{development}
* @param[in] user user name of which to revoke authorization
* @return true if the token has been revoked, false otherwise
*/
virtual bool revokeAuthToken(const std::string& user)=0;
/**
* @brief Get authorized tokens
* @jsonapi{development}
* @return the set of authorized encoded tokens
*/
virtual std::map<std::string,std::string> getAuthorizedTokens() =0;
virtual std::map<std::string,std::string> getAuthorizedTokens() = 0;
/**
* @brief Check if given JSON API auth token is authorized
* @jsonapi{development,unauthenticated}
* @param[in] token decoded
* @return tru if authorized, false otherwise
*/
virtual bool isAuthTokenValid(const std::string& token)=0;
virtual bool isAuthTokenValid(const std::string& token) = 0;
virtual ~RsJsonApi() = default;
};
extern RsJsonAPI *rsJsonAPI;

View file

@ -3,7 +3,8 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2012-2018 by Retroshare Team <retroshare.project@gmail.com> *
* Copyright (C) 2012-2018 Retroshare Team <contact@retroshare.cc> *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -21,7 +22,6 @@
*******************************************************************************/
#pragma once
/**
* @def RS_MINI_VERSION
* First number of RetroShare versioning scheme
@ -69,13 +69,45 @@
(RS_MINOR_VERSION == (B) && RS_MINI_VERSION >= (C)))))
#define __RS_PRIVATE_STRINGIFY2(X) #X
#define __RS_PRIVATE_STRINGIFY(X) __RS_PRIVATE_STRINGIFY2(X)
#define RS_PRIVATE_STRINGIFY2(X) #X
#define RS_PRIVATE_STRINGIFY(X) RS_PRIVATE_STRINGIFY2(X)
/**
* Human readable string describing RetroShare version
*/
constexpr auto RS_HUMAN_READABLE_VERSION =
__RS_PRIVATE_STRINGIFY(RS_MAJOR_VERSION) "." \
__RS_PRIVATE_STRINGIFY(RS_MINOR_VERSION) "." \
__RS_PRIVATE_STRINGIFY(RS_MINI_VERSION) RS_EXTRA_VERSION;
RS_PRIVATE_STRINGIFY(RS_MAJOR_VERSION) "." \
RS_PRIVATE_STRINGIFY(RS_MINOR_VERSION) "." \
RS_PRIVATE_STRINGIFY(RS_MINI_VERSION) RS_EXTRA_VERSION;
#include <cstdint>
#include <string>
/**
* Helper to expose version information to JSON API.
* From C++ you should use directly the macro and constants defined upstair
* @jsonapi{development}
*/
class RsVersion
{
public:
/**
* @brief Write version information to given paramethers
* @jsonapi{development,unauthenticated}
* @param[out] major storage
* @param[out] minor storage
* @param[out] mini storage
* @param[out] extra storage
* @param[out] human storage
*/
static void version( uint32_t& major, uint32_t& minor, uint32_t& mini,
std::string& extra, std::string& human );
};
/**
* Pointer to global instance of RsVersion, for the sake of JSON API, from C++
* you can use directly the macro and constants defined upstair
* @jsonapi{development}
*/
extern RsVersion* rsVersion;

View file

@ -6,39 +6,67 @@
* Copyright 2019-2019 Cyril Soler <csoler@users.sourceforge.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* it under the terms of the GNU Affero General Public License version 3 as *
* published by the Free Software Foundation. *
* *
* 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
class RsWebUI
#include <string>
class RsWebUi;
/**
* Pointer to global instance of RsWebUi service implementation
* @jsonapi{development}
*/
extern RsWebUi* rsWebUI;
class RsWebUi
{
public:
enum {
WEBUI_STATUS_UNKNOWN = 0x00,
WEBUI_STATUS_NOT_RUNNING = 0x01,
WEBUI_STATUS_RUNNING = 0x02
};
static const std::string DEFAULT_BASE_DIRECTORY ;
static const std::string DEFAULT_BASE_DIRECTORY;
virtual bool restart() =0;
virtual bool stop() =0;
/**
* @brief Restart WebUI
* @jsonapi{development}
*/
virtual bool restart() = 0;
virtual void setHtmlFilesDirectory(const std::string& html_dir) =0;
virtual void setUserPassword(const std::string& passwd) =0;
/**
* @brief Stop WebUI
* @jsonapi{development}
*/
virtual bool stop() = 0;
virtual int status() const=0;
/**
* @brief Set WebUI static files directory, need restart to apply
* @param[in] htmlDir directory path
* @jsonapi{development}
*/
virtual void setHtmlFilesDirectory(const std::string& htmlDir) = 0;
/**
* @brief Set WebUI user password
* @param[in] password new password for WebUI
* @jsonapi{development}
*/
virtual void setUserPassword(const std::string& password) =0;
/**
* @brief check if WebUI is running
* @jsonapi{development}
* @return true if running, false otherwise
*/
virtual bool isRunning() const = 0;
virtual ~RsWebUi() = default;
};
extern RsWebUI *rsWebUI;

View file

@ -91,7 +91,7 @@ void RsServer::rsGlobalShutDown()
mNetMgr->shutdown(); /* Handles UPnP */
#ifdef RS_JSONAPI
rsJsonAPI->stop();
rsJsonApi->fullstop();
#endif
rsAutoProxyMonitor::instance()->stopAllRSShutdown();

View file

@ -34,7 +34,6 @@
#include "retroshare/rsiface.h"
#include "retroshare/rstypes.h"
#include "util/rsthreads.h"
#include "jsonapi/jsonapi.h"
#include "chat/p3chatservice.h"
#include "gxstunnel/p3gxstunnel.h"
@ -141,7 +140,7 @@ public:
private:
std::string getSQLCipherVersion();
std::string getSQLCipherVersion(); // TODO: move to rsversion.h
// The real Server Parts.
@ -157,9 +156,6 @@ public:
RsPluginManager *mPluginsManager;
//sslroot *sslr;
JsonApiServer *mJsonAPIServer;
/* services */
p3heartbeat *mHeart;
p3discovery2 *mDisc;

View file

@ -6,16 +6,15 @@
* Copyright 2019-2019 Cyril Soler *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* it under the terms of the GNU Lesser General Public License version 3 as *
* published by the Free Software Foundation. *
* *
* 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
@ -28,26 +27,29 @@
#include <memory>
#include <chrono>
#include <cstdlib>
#include "util/rsthreads.h"
#include "util/rsdebug.h"
#include "retroshare/rswebui.h"
#include "rsserver/rsaccounts.h"
#include "retroshare/rsjsonapi.h"
enum {
TEXT_HTML = 0,
TEXT_CSS = 1,
TEXT_SVG = 2,
TEXT_TTF = 3,
TEXT_WOFF = 4,
APPLICATION_OCTET_STREAM = 5
};
#define DEBUG_RS_WEBUI 1
RsWebUI *rsWebUI = new p3WebUI;
RsWebUi *rsWebUI = new p3WebUI;
static const std::string mime_types[6] = {
enum MimeTypeIndex
{
TEXT_HTML,
TEXT_CSS,
TEXT_SVG,
TEXT_TTF,
TEXT_WOFF,
APPLICATION_OCTET_STREAM,
};
static const constexpr char* const mime_types[] =
{
"text/html",
"text/css",
"image/svg+xml",
@ -56,59 +58,59 @@ static const std::string mime_types[6] = {
"application/octet-stream",
};
const std::string RsWebUI::DEFAULT_BASE_DIRECTORY = RsAccountsDetail::PathDataDirectory(false); //"/usr/share/retroshare/webui/";
static std::string _base_directory = RsWebUI::DEFAULT_BASE_DIRECTORY;
const std::string RsWebUi::DEFAULT_BASE_DIRECTORY =
RsAccountsDetail::PathDataDirectory(false) + "/webui/";
static std::string _base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY;
template<int MIME_TYPE_INDEX> class handler
template<MimeTypeIndex MIME_TYPE_INDEX> class handler
{
public:
static void get_handler( const std::shared_ptr< restbed::Session > session )
public:
static void get_handler( const std::shared_ptr< restbed::Session > session )
{
const auto request = session->get_request( );
const std::string filename = request->get_path_parameter( "filename" );
std::string directory = request->get_path_parameter( "dir" );
if(!directory.empty()) directory += "/";
std::string resource_filename = _base_directory + "/" + directory + filename;
RsDbg() << "Reading file: \"" << resource_filename << "\"" << std::endl;
std::ifstream stream( resource_filename, std::ifstream::in );
if(stream.is_open())
{
const auto request = session->get_request( );
const std::string filename = request->get_path_parameter( "filename" );
std::string directory = request->get_path_parameter( "dir" );
const std::string body = std::string(
std::istreambuf_iterator<char>(stream),
std::istreambuf_iterator<char>() );
if(!directory.empty())
directory += "/";
RsDbg() << __PRETTY_FUNCTION__
<< " body length=" << body.length() << std::endl;
std::string resource_filename = _base_directory + "/" + directory + filename;
RsDbg() << "Reading file: \"" << resource_filename << "\"" << std::endl;
std::ifstream stream( resource_filename, std::ifstream::in );
if ( stream.is_open( ) )
const std::multimap<std::string, std::string> headers
{
const std::string body = std::string( std::istreambuf_iterator< char >( stream ), std::istreambuf_iterator< char >( ) );
{ "Content-Type", mime_types[MIME_TYPE_INDEX] },
{ "Content-Length", std::to_string(body.length()) }
};
RsDbg() << " body length=" << body.length() << std::endl;
const std::multimap< std::string, std::string > headers
{
{ "Content-Type", mime_types[MIME_TYPE_INDEX] },
{ "Content-Length", std::to_string( body.length( ) ) }
};
session->close( restbed::OK, body, headers );
}
else
{
RsErr() << "Could not open file " << resource_filename << std::endl;
session->close( restbed::NOT_FOUND );
}
session->close(restbed::OK, body, headers);
}
else
{
RsErr() << __PRETTY_FUNCTION__ << "Could not open file: "
<< resource_filename << std::endl;
session->close(restbed::NOT_FOUND);
}
}
};
static void service_ready_handler( restbed::Service& )
std::vector< std::shared_ptr<restbed::Resource> > p3WebUI::getResources() const
{
fprintf( stderr, "Hey! The service is up and running." );
}
static std::vector< std::shared_ptr<restbed::Resource> > rtab;
std::vector<std::shared_ptr<restbed::Resource> > p3WebUI::getResources() const
{
static std::vector<std::shared_ptr<restbed::Resource> > rtab;
if(rtab.empty())
if(rtab.empty())
{
auto resource1 = std::make_shared< restbed::Resource >( );
auto resource1 = std::make_shared< restbed::Resource >();
resource1->set_paths( {
"/{filename: index.html}",
"/{filename: app.js}",
@ -167,37 +169,29 @@ void p3WebUI::setHtmlFilesDirectory(const std::string& html_dir)
_base_directory = html_dir;
}
int p3WebUI::status() const
{
if(rsJsonAPI->isRunning() && rsJsonAPI->hasResourceProvider(this))
return WEBUI_STATUS_RUNNING;
else
return WEBUI_STATUS_NOT_RUNNING;
}
bool p3WebUI::isRunning() const
{ return rsJsonApi->isRunning() && rsJsonApi->hasResourceProvider(*this); }
void p3WebUI::setUserPassword(const std::string& passwd)
{
#ifdef RS_JSONAPI
std::cerr << "Updating webui token with new passwd \"" << passwd << "\"" << std::endl;
RsDbg() << __PRETTY_FUNCTION__ << " Updating webui token with new passwd \""
<< passwd << "\"" << std::endl;
if(!rsJsonAPI->authorizeUser("webui",passwd))
if(!rsJsonApi->authorizeUser("webui",passwd))
std::cerr << "(EE) Cannot register webui token. Some error occurred when calling authorizeUser()" << std::endl;
#else
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);
rsJsonAPI->restart();
rsJsonApi->registerResourceProvider(*this);
rsJsonApi->restart();
return true;
}
bool p3WebUI::stop()
{
rsJsonAPI->unregisterResourceProvider(this);
rsJsonAPI->restart();
rsJsonApi->unregisterResourceProvider(*this);
rsJsonApi->restart();
return true;
}

View file

@ -6,16 +6,15 @@
* Copyright 2019-2019 Cyril Soler *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* it under the terms of the GNU Lesser General Public License version 3 as *
* published by the Free Software Foundation. *
* *
* 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
@ -26,11 +25,10 @@
#include "retroshare/rswebui.h"
#include "jsonapi/jsonapi.h"
class p3WebUI: public RsWebUI, public JsonApiResourceProvider
class p3WebUI: public RsWebUi, public JsonApiResourceProvider
{
public:
p3WebUI(){}
virtual ~p3WebUI() = default;
~p3WebUI() override = default;
// implements RsWebUI
@ -39,11 +37,9 @@ public:
virtual bool restart() override ;
virtual bool stop() override ;
virtual int status() const override;
bool isRunning() const override;
// implements JsonApiResourceProvider
virtual std::string getName() const override { return "Web Interface" ;}
virtual std::vector<std::shared_ptr<restbed::Resource> > getResources() const override;
};

View file

@ -393,20 +393,16 @@ int RsInit::InitRetroShare(const RsConfigOptions& conf)
return error_code ;
#ifdef RS_JSONAPI
// We create the JsonApiServer this early, because it is needed *before* login
// We create the JsonApiServer this early, because it is needed *before* login
RsInfo() << __PRETTY_FUNCTION__
<< "Allocating jsonAPI server (not launched yet)" << std::endl;
JsonApiServer* jas = new JsonApiServer();
jas->setListeningPort(conf.jsonApiPort);
jas->setBindingAddress(conf.jsonApiBindAddress);
RsInfo() << "Allocating jsonAPI server (not launched yet) " << std::endl;
JsonApiServer *jas = new JsonApiServer();
jas->setListeningPort(conf.jsonApiPort);
jas->setBindAddress(conf.jsonApiBindAddress);
if(conf.jsonApiPort != 0) jas->restart();
if(conf.jsonApiPort != 0)
{
RsInfo() << "Launching jsonAPI server on port " << conf.jsonApiPort << std::endl;
jas->restart();
}
rsJsonAPI = jas;
rsJsonApi = jas;
#endif
#ifdef RS_AUTOLOGIN
@ -1224,10 +1220,8 @@ int RsServer::StartupRetroShare()
mPluginsManager->loadPlugins(programatically_inserted_plugins) ;
#ifdef RS_JSONAPI
// add jsonapi server to config manager so that it can save/load its tokens
if(rsJsonAPI)
rsJsonAPI->connectToConfigManager(mConfigMgr);
// add jsonapi server to config manager so that it can save/load its tokens
if(rsJsonApi) rsJsonApi->connectToConfigManager(*mConfigMgr);
#endif
/**** Reputation system ****/

View file

@ -1,56 +1,35 @@
/*******************************************************************************
* libretroshare/src/jsonapi/: restbedservice.h *
* *
* libretroshare: retroshare core library *
* *
* Copyright 2019-2019 Cyril Soler *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* it under the terms of the GNU Lesser 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. *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include "retroshare/rsversion.h"
#include <restbed>
#include "util/rsthreads.h"
/*extern*/ RsVersion* rsVersion = new RsVersion;
class RestbedThread;
class RestbedService: public RsThread
/*static*/ void RsVersion::version(
uint32_t& major, uint32_t& minor, uint32_t& mini, std::string& extra,
std::string& human )
{
public:
RestbedService() ;
virtual ~RestbedService() = default;
bool restart();
bool fullstop();
void setListeningPort(uint16_t port) ;
void setBindAddress(const std::string& bind_address);
uint16_t listeningPort() const ;
// 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;
protected:
void runloop() override;
std::shared_ptr<restbed::Service> mService; // managed by RestbedService because it needs to be properly deleted when restarted.
private:
uint16_t mListeningPort;
std::string mBindingAddress;
};
major = RS_MAJOR_VERSION;
minor = RS_MINOR_VERSION;
mini = RS_MINI_VERSION;
extra = RS_EXTRA_VERSION;
human = RS_HUMAN_READABLE_VERSION;
}

View file

@ -28,8 +28,8 @@
class Radix64
{
public:
static std::vector<uint8_t> decode(const std::string& buffer)
public:
static std::vector<uint8_t> decode(const std::string& buffer)
{
char val;
int c = 0, c2;/* init c because gcc is not clever
@ -122,13 +122,14 @@ again:
/****************
* create a radix64 encoded string.
*/
static void encode(const unsigned char *data,int len,std::string& out_string)
static void encode(
const unsigned char* data, size_t len, std::string& out_string )
{
char *buffer, *p;
radix64_init();
int size = (len + 2) / 3 * 4 +1;
size_t size = (len + 2) / 3 * 4 +1;
buffer = p = new char[size] ;
for (; len >= 3; len -= 3, data += 3)