Implement JSON API HTTP Basic authentication

jsonapi-generator is now capable of generating API for headers outside
  retroshare/ directory
jsonapi-generator do a bit of methods parameter sanity check
JsonApiServer is now integrated in the rsinit hell like other services
Add *::exportGPGKeyPairToString to a bunch of classes in cascade
RsControl is now capable of calling back a function when retroshare is almost
  completely stopped, this is useful when running retroshare toghether with
  externally managed runloop such as QCoreApplication
Expose a bunch of methods through JSON API
retroshare-nogui remove some dead code and fix stopping from the RetroShare API
This commit is contained in:
Gioacchino Mazzurco 2018-09-19 21:28:26 +02:00
parent ac9350d375
commit eb77f921ec
No known key found for this signature in database
GPG key ID: A1FBCA3872E87051
32 changed files with 816 additions and 398 deletions

View file

@ -18,6 +18,7 @@
#include "jsonapi.h"
#include <string>
#include <sstream>
#include <memory>
#include <restbed>
@ -27,10 +28,17 @@
#include "retroshare/rsfiles.h"
#include "util/radix64.h"
#include "retroshare/rsversion.h"
#include "retroshare/rsinit.h"
#include "util/rsnet.h"
#include "retroshare/rsiface.h"
#include "retroshare/rsinit.h"
#include "util/rsurl.h"
// Generated at compile time
#include "jsonapi-includes.inl"
/*extern*/ JsonApiServer* jsonApiServer = nullptr;
#define INITIALIZE_API_CALL_JSON_CONTEXT \
RsGenericSerializer::SerializeContext cReq( \
nullptr, 0, \
@ -71,10 +79,10 @@ static bool checkRsServicePtrReady(
{
if(serviceInstance) return true;
std::string jsonApiError;
std::string jsonApiError = __PRETTY_FUNCTION__;
jsonApiError += "Service: ";
jsonApiError += serviceName;
jsonApiError += " not initialized! Are you sure you logged in already?";
jsonApiError += " not initialized!";
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
RS_SERIAL_PROCESS(jsonApiError);
@ -84,13 +92,53 @@ static bool checkRsServicePtrReady(
return false;
}
JsonApiServer::JsonApiServer(
uint16_t port, const std::string& bindAddress,
const std::function<void(int)> shutdownCallback ) :
mPort(port), mBindAddress(bindAddress), mShutdownCallback(shutdownCallback)
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")
{
registerHandler("/jsonApiServer/shutdown",
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](
const std::shared_ptr<rb::Session> session,
const rb::Bytes& body )
{
INITIALIZE_API_CALL_JSON_CONTEXT;
RsPeerId account;
std::string password;
// deserialize input parameters from JSON
{
RsGenericSerializer::SerializeContext& ctx(cReq);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);
RS_SERIAL_PROCESS(account);
RS_SERIAL_PROCESS(password);
}
// call retroshare C++ API
RsInit::LoadCertificateStatus retval =
rsLoginHelper->attemptLogin(account, password);
if( retval == RsInit::OK )
authorizeToken(account.toStdString()+":"+password);
// serialize out parameters and return value to JSON
{
RsGenericSerializer::SerializeContext& ctx(cAns);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
RS_SERIAL_PROCESS(retval);
}
// return them to the API caller
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
} );
}, false);
registerHandler("/rsControl/rsGlobalShutDown",
[this](const std::shared_ptr<rb::Session> session)
{
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
@ -100,37 +148,9 @@ JsonApiServer::JsonApiServer(
{
INITIALIZE_API_CALL_JSON_CONTEXT;
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
shutdown();
rsControl->rsGlobalShutDown();
} );
});
registerHandler("/jsonApiServer/version",
[](const std::shared_ptr<rb::Session> session)
{
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( reqSize, [](
const std::shared_ptr<rb::Session> session,
const rb::Bytes& body )
{
INITIALIZE_API_CALL_JSON_CONTEXT;
uint32_t major = RS_MAJOR_VERSION;
uint32_t minor = RS_MINOR_VERSION;
uint32_t mini = RS_MINI_VERSION;
std::string extra = RS_EXTRA_VERSION;
std::string human = RS_HUMAN_READABLE_VERSION;
RsGenericSerializer::SerializeContext& ctx(cAns);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
RS_SERIAL_PROCESS(major);
RS_SERIAL_PROCESS(minor);
RS_SERIAL_PROCESS(mini);
RS_SERIAL_PROCESS(extra);
RS_SERIAL_PROCESS(human);
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
} );
});
}, true);
registerHandler("/rsFiles/getFileData",
[](const std::shared_ptr<rb::Session> session)
@ -186,7 +206,7 @@ JsonApiServer::JsonApiServer(
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
} );
});
}, true);
// Generated at compile time
#include "jsonapi-wrappers.inl"
@ -198,22 +218,173 @@ void JsonApiServer::run()
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);
}
void JsonApiServer::registerHandler(
const std::string& path,
const std::function<void (const std::shared_ptr<restbed::Session>)>& handler)
const std::function<void (const std::shared_ptr<restbed::Session>)>& handler,
bool requiresAutentication )
{
std::shared_ptr<restbed::Resource> resource(new rb::Resource);
resource->set_path(path);
resource->set_method_handler("GET", handler);
resource->set_method_handler("POST", handler);
if(requiresAutentication)
resource->set_authentication_handler(
[this](
const std::shared_ptr<rb::Session> session,
const std::function<void (const std::shared_ptr<rb::Session>)>& callback )
{
if(!rsLoginHelper->isLoggedIn())
{
session->close(rb::CONFLICT);
return;
}
std::istringstream authHeader;
authHeader.str(session->get_request()->get_header("Authorization"));
std::string authToken;
std::getline(authHeader, authToken, ' ');
if(authToken != "Basic")
{
session->close(rb::UNAUTHORIZED);
return;
}
std::getline(authHeader, authToken, ' ');
authToken = decodeToken(authToken);
if(isAuthTokenValid(authToken)) callback(session);
else session->close(rb::UNAUTHORIZED);
} );
mService.publish(resource);
}
void JsonApiServer::shutdown(int exitCode)
void JsonApiServer::setNewAccessRequestCallback(
const std::function<bool (const std::string&)>& callback )
{ mNewAccessRequestCallback = callback; }
void JsonApiServer::shutdown() { mService.stop(); }
bool JsonApiServer::requestNewTokenAutorization(const std::string& token)
{
mService.stop();
mShutdownCallback(exitCode);
if(rsLoginHelper->isLoggedIn() && mNewAccessRequestCallback(token))
return authorizeToken(token);
return false;
}
bool JsonApiServer::isAuthTokenValid(const std::string& token)
{
RS_STACK_MUTEX(configMutex);
return mAuthTokenStorage.mAuthorizedTokens.count(token);
}
std::set<std::string> JsonApiServer::getAuthorizedTokens()
{
RS_STACK_MUTEX(configMutex);
return mAuthTokenStorage.mAuthorizedTokens;
}
bool JsonApiServer::revokeAuthToken(const std::string& token)
{
RS_STACK_MUTEX(configMutex);
if(mAuthTokenStorage.mAuthorizedTokens.erase(token))
{
IndicateConfigChanged();
return true;
}
return false;
}
bool JsonApiServer::authorizeToken(const std::string& token)
{
if(token.empty()) return false;
RS_STACK_MUTEX(configMutex);
if(mAuthTokenStorage.mAuthorizedTokens.insert(token).second)
{
IndicateConfigChanged();
return true;
}
return false;
}
/*static*/ std::string JsonApiServer::decodeToken(const std::string& token)
{
std::vector<uint8_t> decodedVect(Radix64::decode(token));
std::string decodedToken(
reinterpret_cast<const char*>(&decodedVect[0]),
decodedVect.size() );
return decodedToken;
}
/*static*/ std::string JsonApiServer::encondeToken(const std::string& token)
{
std::string encoded;
Radix64::encode( reinterpret_cast<const uint8_t*>(token.c_str()),
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;
rss->addSerialType(new JsonApiConfigSerializer);
return rss;
}
bool JsonApiServer::saveList(bool& cleanup, std::list<RsItem*>& saveItems)
{
cleanup = false;
configMutex.lock();
saveItems.push_back(&mAuthTokenStorage);
return true;
}
bool JsonApiServer::loadList(std::list<RsItem*>& loadList)
{
for(RsItem* it : loadList)
switch (static_cast<JsonApiItemsType>(it->PacketSubType()))
{
case JsonApiItemsType::AuthTokenItem:
mAuthTokenStorage = *static_cast<JsonApiServerAuthTokenStorage*>(it);
delete it;
break;
default:
delete it;
break;
}
return true;
}
void JsonApiServer::saveDone() { configMutex.unlock(); }

View file

@ -15,36 +15,59 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <memory>
#include <restbed>
#include <cstdint>
#include "util/rsthreads.h"
#include "pqi/p3cfgmgr.h"
#include "rsitems/rsitem.h"
#include "jsonapi/jsonapiitems.h"
#include "util/rsthreads.h"
namespace rb = restbed;
struct JsonApiServer;
/**
* Pointer to global instance of JsonApiServer
* @jsonapi{development}
*/
extern JsonApiServer* jsonApiServer;
/**
* Simple usage
* \code{.cpp}
* JsonApiServer jas(9092);
* jsonApiServer = &jas;
* jas.start("JsonApiServer");
* \endcode
* Uses p3Config to securely store persistent JSON API authorization tokens
*/
struct JsonApiServer : RsSingleJobThread
struct JsonApiServer : RsSingleJobThread, p3Config
{
/**
* @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 = 9092,
const std::string& bindAddress = "127.0.0.1",
const std::function<void(int)> shutdownCallback = [](int){} );
/// @see RsSingleJobThread
virtual void run();
const std::function<bool(const std::string&)> newAccessRequestCallback = [](const std::string&){return false;} );
/**
* @param[in] path Path itno 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)
@ -52,24 +75,118 @@ struct JsonApiServer : RsSingleJobThread
*/
void registerHandler(
const std::string& path,
const std::function<void(const std::shared_ptr<rb::Session>)>& handler );
const std::function<void(const std::shared_ptr<rb::Session>)>& handler,
bool requiresAutentication = true );
/**
* @brief Shutdown the JSON API server and call shutdownCallback
* @jsonapi{development}
* Beware that this method shout down only the JSON API server instance not
* the whole RetroShare instance, this behaviour can be altered via
* shutdownCallback paramether of @see JsonApiServer::JsonApiServer
* This method is made available also via JSON API with path
* /jsonApiServer/shutdown
* @param exitCode just passed down to the shutdownCallback
* @brief Set new access request callback
* @param callback function to call when a new JSON API access is requested
*/
void shutdown(int exitCode = 0);
void setNewAccessRequestCallback(
const std::function<bool(const std::string&)>& callback );
/**
* @brief Shutdown the JSON API server
* Beware that this method shout down only the JSON API server instance not
*/
void shutdown();
/**
* @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
* @return true if authorization succeded, false otherwise.
*/
bool requestNewTokenAutorization(const std::string& token);
/**
* @brief Check if given JSON API auth token is authorized
* @jsonapi{development}
* @param[in] token decoded
* @return tru if authorized, false otherwise
*/
bool isAuthTokenValid(const std::string& token);
/**
* @brief Get uthorized tokens
* @jsonapi{development}
* @return the set of authorized encoded tokens
*/
std::set<std::string> getAuthorizedTokens();
/**
* @brief Revoke given auth token
* @jsonapi{development}
* @param[in] token decoded
* @return true if the token has been revoked, false otherwise
*/
bool revokeAuthToken(const std::string& token);
/**
* @brief Add new auth token to the authorized set
* @jsonapi{development}
* @param[in] token toke to autorize decoded
* @return true if the token has been added to authorized, false if error
* occurred or if the token was already authorized
*/
bool authorizeToken(const std::string& token);
/**
* @brief Get decoded version of the given encoded token
* @jsonapi{development,unauthenticated}
* @param[in] token encoded
* @return token decoded
*/
static std::string decodeToken(const std::string& token);
/**
* @brief Get encoded version of the given decoded token
* @jsonapi{development,unauthenticated}
* @param[in] token decoded
* @return token encoded
*/
static std::string encondeToken(const std::string& 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 );
/// @see RsSingleJobThread
virtual void run();
private:
/// @see p3Config::setupSerialiser
virtual RsSerialiser* setupSerialiser();
/// @see p3Config::saveList
virtual bool saveList(bool &cleanup, std::list<RsItem *>& saveItems);
/// @see p3Config::loadList
virtual bool loadList(std::list<RsItem *>& loadList);
/// @see p3Config::saveDone
virtual void saveDone();
const uint16_t mPort;
const std::string mBindAddress;
rb::Service mService;
const std::function<void(int)> mShutdownCallback;
/// Called when new JSON API auth token is requested to be authorized
std::function<bool(const std::string&)> mNewAccessRequestCallback;
/// Encrypted persistent storage for authorized JSON API tokens
JsonApiServerAuthTokenStorage mAuthTokenStorage;
RsMutex configMutex;
};

View file

@ -0,0 +1,69 @@
/*
* RetroShare JSON API
* Copyright (C) 2018 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.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <ctime>
#include <cstdint>
#include <set>
#include "rsitems/rsitem.h"
#include "rsitems/rsserviceids.h"
#include "serialiser/rsserializer.h"
#include "serialiser/rsserializable.h"
enum class JsonApiItemsType : uint8_t { AuthTokenItem = 0 };
struct JsonApiServerAuthTokenStorage : RsItem
{
JsonApiServerAuthTokenStorage() :
RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_JSONAPI,
static_cast<uint8_t>(JsonApiItemsType::AuthTokenItem) ) {}
/// @see RsSerializable
virtual void serial_process(RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx)
{
RS_SERIAL_PROCESS(mAuthorizedTokens);
}
/// @see RsItem
virtual void clear() { mAuthorizedTokens.clear(); }
std::set<std::string> mAuthorizedTokens;
};
struct JsonApiConfigSerializer : RsServiceSerializer
{
JsonApiConfigSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_JSONAPI) {}
virtual ~JsonApiConfigSerializer() {}
RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const
{
if(service_id != RS_SERVICE_TYPE_JSONAPI) return nullptr;
switch(static_cast<JsonApiItemsType>(item_sub_id))
{
case JsonApiItemsType::AuthTokenItem: return new JsonApiServerAuthTokenStorage();
default: return nullptr;
}
}
};

View file

@ -909,7 +909,7 @@ rs_jsonapi {
# Force recalculation of libretroshare dependencies see https://stackoverflow.com/a/47884045
QMAKE_EXTRA_TARGETS += libretroshare
HEADERS += jsonapi/jsonapi.h
HEADERS += jsonapi/jsonapi.h jsonapi/jsonapiitems.h
SOURCES += jsonapi/jsonapi.cpp
}

View file

@ -709,6 +709,36 @@ bool PGPHandler::exportGPGKeyPair(const std::string& filename,const RsPgpId& exp
return true ;
}
bool PGPHandler::exportGPGKeyPairToString(
std::string& data, const RsPgpId& exportedKeyId,
bool includeSignatures, std::string& errorMsg ) const
{
RS_STACK_MUTEX(pgphandlerMtx);
const ops_keydata_t *pubkey = locked_getPublicKey(exportedKeyId,false);
if(!pubkey)
{
errorMsg = "Cannot output key " + exportedKeyId.toStdString() +
": not found in public keyring.";
return false;
}
const ops_keydata_t *seckey = locked_getSecretKey(exportedKeyId);
if(!seckey)
{
errorMsg = "Cannot output key " + exportedKeyId.toStdString() +
": not found in secret keyring.";
return false;
}
data = makeRadixEncodedPGPKey(pubkey, includeSignatures);
data += "\n";
data += makeRadixEncodedPGPKey(seckey, includeSignatures);
data += "\n";
return true;
}
bool PGPHandler::getGPGDetailsFromBinaryBlock(const unsigned char *mem_block,size_t mem_size,RsPgpId& key_id, std::string& name, std::list<RsPgpId>& signers) const
{
ops_keyring_t *tmp_keyring = allocateOPSKeyring();

View file

@ -99,6 +99,9 @@ class PGPHandler
bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_id,std::string& import_error) ;
bool importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) ;
bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_id) const ;
bool exportGPGKeyPairToString(
std::string& data, const RsPgpId& exportedKeyId,
bool includeSignatures, std::string& errorMsg ) const;
bool availableGPGCertificatesWithPrivateKeys(std::list<RsPgpId>& ids);
bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) ;

View file

@ -327,6 +327,14 @@ bool AuthGPG::exportProfile(const std::string& fname,const RsPgpId& exported_id)
return PGPHandler::exportGPGKeyPair(fname,exported_id) ;
}
bool AuthGPG::exportIdentityToString(
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
std::string& errorMsg )
{
return PGPHandler::exportGPGKeyPairToString(
data, pgpId, includeSignatures, errorMsg);
}
bool AuthGPG::importProfile(const std::string& fname,RsPgpId& imported_id,std::string& import_error)
{
return PGPHandler::importGPGKeyPair(fname,imported_id,import_error) ;
@ -337,7 +345,6 @@ bool AuthGPG::importProfileFromString(const std::string &data, RsPgpId &gpg_id,
return PGPHandler::importGPGKeyPairFromString(data, gpg_id, import_error);
}
bool AuthGPG::active()
{
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/

View file

@ -158,6 +158,9 @@ public:
virtual bool importProfile(const std::string& filename,RsPgpId& gpg_id,std::string& import_error) ;
virtual bool importProfileFromString(const std::string& data,RsPgpId& gpg_id,std::string& import_error) ;
virtual bool exportProfile(const std::string& filename,const RsPgpId& gpg_id) ;
virtual bool exportIdentityToString(
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
std::string& errorMsg );
virtual bool removeKeysFromPGPKeyring(const std::set<RsPgpId> &pgp_ids,std::string& backup_file,uint32_t& error_code) ;

View file

@ -987,9 +987,9 @@ void p3ServiceControl::filterChangeAdded_locked(const RsPeerId &peerId, uint32_t
void p3ServiceControl::getPeersConnected(const uint32_t serviceId, std::set<RsPeerId> &peerSet)
void p3ServiceControl::getPeersConnected(uint32_t serviceId, std::set<RsPeerId> &peerSet)
{
RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/
RS_STACK_MUTEX(mCtrlMtx);
std::map<uint32_t, std::set<RsPeerId> >::iterator mit;
mit = mServicePeerMap.find(serviceId);
@ -1004,9 +1004,9 @@ void p3ServiceControl::getPeersConnected(const uint32_t serviceId, std::set<RsPe
}
bool p3ServiceControl::isPeerConnected(const uint32_t serviceId, const RsPeerId &peerId)
bool p3ServiceControl::isPeerConnected(uint32_t serviceId, const RsPeerId &peerId)
{
RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/
RS_STACK_MUTEX(mCtrlMtx);
std::map<uint32_t, std::set<RsPeerId> >::iterator mit;
mit = mServicePeerMap.find(serviceId);

View file

@ -95,8 +95,8 @@ virtual bool getServicePermissions(uint32_t serviceId, RsServicePermissions &per
virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions);
// Get List of Peers using this Service.
virtual void getPeersConnected(const uint32_t serviceId, std::set<RsPeerId> &peerSet);
virtual bool isPeerConnected(const uint32_t serviceId, const RsPeerId &peerId);
virtual void getPeersConnected(uint32_t serviceId, std::set<RsPeerId> &peerSet);
virtual bool isPeerConnected(uint32_t serviceId, const RsPeerId &peerId);
// Gets the list of items used by that service
virtual bool getServiceItemNames(uint32_t serviceId,std::map<uint8_t,std::string>& names) ;

View file

@ -204,7 +204,7 @@ public:
* as available or a sensible maximum. Expect a block size of around 1MiB.
* To get more data, call this function repeatedly with different offsets.
*
* jsonapi{development}
* @jsonapi{development,manualwrapper}
* note the missing @ the wrapper for this is written manually not
* autogenerated @see JsonApiServer.
*

View file

@ -200,8 +200,8 @@ public:
* @brief Share channel publishing key
* This can be used to authorize other peers to post on the channel
* @jsonapi{development}
* param[in] groupId Channel id
* param[in] peers peers to which share the key
* @param[in] groupId Channel id
* @param[in] peers peers to which share the key
* @return false on error, true otherwise
*/
virtual bool groupShareKeys(

View file

@ -19,24 +19,22 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef RETROSHARE_GUI_INTERFACE_H
#define RETROSHARE_GUI_INTERFACE_H
#pragma once
#include "retroshare/rsnotify.h"
#include "rstypes.h"
#include <map>
#include <functional>
class NotifyBase;
class RsServer;
class RsInit;
class RsPeerCryptoParams;
struct TurtleFileInfo ;
class RsControl;
/* RsInit -> Configuration Parameters for RetroShare Startup
*/
/// RsInit -> Configuration Parameters for RetroShare Startup
RsInit* InitRsConfig();
RsInit *InitRsConfig();
/* extract various options for GUI */
const char *RsConfigDirectory(RsInit *config);
bool RsConfigStartMinimised(RsInit *config);
@ -46,35 +44,50 @@ void CleanupRsConfig(RsInit *);
// Called First... (handles comandline options)
int InitRetroShare(int argc, char **argv, RsInit *config);
class RsControl /* The Main Interface Class - for controlling the server */
/**
* Pointer to global instance of RsControl needed to expose JSON API
* @jsonapi{development}
*/
extern RsControl* rsControl;
/** The Main Interface Class - for controlling the server */
class RsControl
{
public:
/// TODO: This should return a reference instead of a pointer!
static RsControl *instance();
static void earlyInitNotificationSystem() { instance(); }
static RsControl* instance();
static void earlyInitNotificationSystem() { rsControl = instance(); }
/* Real Startup Fn */
virtual int StartupRetroShare() = 0;
/** Check if core is fully ready, true only after
* StartupRetroShare() finish and before rsGlobalShutDown() begin
/**
* @brief Check if core is fully ready, true only after StartupRetroShare()
* finish and before rsGlobalShutDown() begin
* @jsonapi{development}
*/
virtual bool isReady() = 0;
/****************************************/
/* Config */
virtual void ConfigFinalSave() = 0;
virtual void ConfigFinalSave( ) = 0;
virtual void rsGlobalShutDown( ) = 0;
/**
* @brief Turn off RetroShare
* @jsonapi{development,manualwrapper}
*/
virtual void rsGlobalShutDown() = 0;
/****************************************/
virtual bool getPeerCryptoDetails(
const RsPeerId& ssl_id,RsPeerCryptoParams& params ) = 0;
virtual void getLibraries(std::list<RsLibraryInfo> &libraries) = 0;
virtual bool getPeerCryptoDetails(const RsPeerId& ssl_id,RsPeerCryptoParams& params) = 0;
virtual void getLibraries(std::list<RsLibraryInfo> &libraries) = 0;
/**
* @brief Set shutdown callback, useful if main runlop is controlled by
* another entity such as QCoreApplication
* @param callback function to call when shutdown is almost complete
*/
virtual void setShutdownCallback(const std::function<void(int)>& callback) = 0;
protected:
RsControl() {} // should not be used, hence it's private.
protected:
RsControl() {} // should not be used, hence it's private.
};
#endif

View file

@ -72,7 +72,7 @@ public:
* PreLogin
* Call before init retroshare, initialises rsinitconfig's public attributes
*/
static void InitRsConfig();
static void InitRsConfig();
/*!
* Should be called to load up ssl cert and private key, and intialises gpg
@ -166,15 +166,45 @@ public:
static std::string systemDataDirectory(bool check = true);
static std::string PGPDirectory();
// PGP Accounts.
static int GetPGPLogins(std::list<RsPgpId> &pgpIds);
/**
* @brief Get available PGP identities id list
* @jsonapi{development,unauthenticated}
* @param[out] pgpIds storage for PGP id list
* @return true on success, false otherwise
*/
static int GetPGPLogins(std::list<RsPgpId> &pgpIds);
static int GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email);
static bool GeneratePGPCertificate(const std::string&, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString);
// PGP Support Functions.
static bool ExportIdentity(const std::string& fname,const RsPgpId& pgp_id) ;
static bool ImportIdentity(const std::string& fname,RsPgpId& imported_pgp_id,std::string& import_error) ;
static bool ImportIdentityFromString(const std::string& data,RsPgpId& imported_pgp_id,std::string& import_error) ;
/**
* @brief Import full encrypted PGP identity from string
* @jsonapi{development,unauthenticated}
* @param[in] data certificate string
* @param[out] pgpId storage for the PGP fingerprint of the imported key
* @param[out] errorMsg storage for eventual human readable error message
* @return true on success, false otherwise
*/
static bool ImportIdentityFromString(
const std::string& data, RsPgpId& pgpId,
std::string& errorMsg );
/**
* @brief Export full encrypted PGP identity to string
* @jsonapi{development}
* @param[out] data storage for certificate string
* @param[in] pgpId PGP id to export
* @param[in] includeSignatures true to include signatures
* @param[out] errorMsg storage for eventual human readable error message
* @return true on success, false otherwise
*/
static bool exportIdentityToString(
std::string& data, const RsPgpId& pgpId, std::string& errorMsg,
bool includeSignatures = true );
static void GetUnsupportedKeys(std::map<std::string,std::vector<std::string> > &unsupported_keys);
static bool CopyGnuPGKeyrings() ;
@ -233,7 +263,7 @@ struct RsLoginHelper
{
/**
* @brief Normal way to attempt login
* @jsonapi{development}
* @jsonapi{development,manualwrapper}
* @param[in] account Id of the account to which attempt login
* @param[in] password Password for the given account
* @return RsInit::OK if login attempt success, error code otherwhise
@ -255,14 +285,14 @@ struct RsLoginHelper
/**
* @brief Get locations and associated information
* @jsonapi{development}
* @jsonapi{development,unauthenticated}
* @param[out] locations storage for the retrived locations
*/
void getLocations(std::vector<RsLoginHelper::Location>& locations);
/**
* @brief Creates a new RetroShare location, and log in once is created
* @jsonapi{development}
* @jsonapi{development,unauthenticated}
* @param[inout] location provide input information to generate the location
* and storage to output the data of the generated location
* @param[in] password to protect and unlock the associated PGP key
@ -280,7 +310,7 @@ struct RsLoginHelper
/**
* @brief Check if RetroShare is already logged in, this usually return true
* after a successfull attemptLogin() and before closeSession()
* @jsonapi{development}
* @jsonapi{development,unauthenticated}
* @return true if already logged in, false otherwise
*/
bool isLoggedIn();

View file

@ -36,7 +36,7 @@ class RsServiceControl;
* Pointer to global instance of RsServiceControl service implementation
* @jsonapi{development}
*/
extern RsServiceControl *rsServiceControl;
extern RsServiceControl* rsServiceControl;
struct RsServiceInfo : RsSerializable
{
@ -131,9 +131,9 @@ public:
virtual ~RsServiceControl(){}
/**
* @brief getOwnServices return a map off all services.
* @brief get a map off all services.
* @jsonapi{development}
* @param[out] info
* @param[out] info storage for service information
* @return always true
*/
virtual bool getOwnServices(RsPeerServiceInfo &info) = 0;
@ -197,7 +197,8 @@ public:
* @param[in] serviceId service to look up.
* @param[out] peerSet set of peers using this service.
*/
virtual void getPeersConnected(const uint32_t serviceId, std::set<RsPeerId> &peerSet) = 0;
virtual void getPeersConnected( uint32_t serviceId,
std::set<RsPeerId>& peerSet ) = 0;
};
#endif

View file

@ -79,6 +79,7 @@ const uint16_t RS_SERVICE_GXS_TYPE_GXSCIRCLE = 0x0218;
const uint16_t RS_SERVICE_GXS_TYPE_REPUTATION = 0x0219;
const uint16_t RS_SERVICE_TYPE_GXS_RECOGN = 0x0220;
const uint16_t RS_SERVICE_TYPE_GXS_TRANS = 0x0230;
const uint16_t RS_SERVICE_TYPE_JSONAPI = 0x0240;
const uint16_t RS_SERVICE_GXS_TYPE_FORUMS_CONFIG = 0x0315;
const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG = 0x0317;

View file

@ -33,7 +33,7 @@
#include "retroshare/rsinit.h"
#include "plugins/pluginmanager.h"
#include "util/rsdebug.h"
//const int p3facemsgzone = 11453;
#include "jsonapi/jsonapi.h"
#include <sys/time.h>
#include <time.h>
@ -92,6 +92,10 @@ void RsServer::rsGlobalShutDown()
mNetMgr->shutdown(); /* Handles UPnP */
#ifdef RS_JSONAPI
if(jsonApiServer) jsonApiServer->shutdown();
#endif
rsAutoProxyMonitor::instance()->stopAllRSShutdown();
fullstop() ;
@ -117,4 +121,6 @@ void RsServer::rsGlobalShutDown()
// #endif
AuthGPG::exit();
mShutdownCallback(0);
}

View file

@ -55,6 +55,9 @@ int rsserverzone = 101;
#include <sys/timeb.h>
#endif
/*extern*/ RsControl* rsControl = nullptr;
static double getCurrentTS()
{

View file

@ -19,8 +19,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef MRK_P3RS_INTERFACE_H
#define MRK_P3RS_INTERFACE_H
#pragma once
#include <functional>
//#include "server/filedexserver.h"
#include "ft/ftserver.h"
@ -74,19 +75,19 @@ class RsPluginManager;
class RsServer: public RsControl, public RsTickingThread
{
public:
/****************************************/
/* p3face-startup.cc: init... */
virtual int StartupRetroShare();
public:
RsServer();
virtual ~RsServer();
/****************************************/
/* p3face.cc: main loop / util fns / locking. */
virtual int StartupRetroShare();
/// @see RsControl::isReady()
virtual bool isReady() { return coreReady; }
RsServer() ;
virtual ~RsServer();
/// @see RsControl::setShutdownCallback
void setShutdownCallback(const std::function<void(int)>& callback)
{ mShutdownCallback = callback; }
/* Thread Fn: Run the Core */
virtual void data_tick();
@ -202,6 +203,9 @@ class RsServer: public RsControl, public RsTickingThread
static const double maxTimeDelta;
static const double kickLimit;
/// @see RsControl::setShutdownCallback
std::function<void(int)> mShutdownCallback;
/** Keep track of the core being fully ready, true only after
* StartupRetroShare() finish and before rsGlobalShutDown() begin
*/
@ -213,5 +217,3 @@ class RsServer: public RsControl, public RsTickingThread
*/
std::string make_path_unix(std::string winpath);
#endif

View file

@ -930,6 +930,14 @@ bool RsAccountsDetail::importIdentityFromString(const std::string &data, RsPgpId
return AuthGPG::getAuthGPG()->importProfileFromString(data, imported_pgp_id, import_error);
}
bool RsAccountsDetail::exportIdentityToString(
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
std::string& errorMsg )
{
return AuthGPG::getAuthGPG()->exportIdentityToString(
data, pgpId, includeSignatures, errorMsg );
}
bool RsAccountsDetail::copyGnuPGKeyrings()
{
std::string pgp_dir = PathPGPDirectory() ;
@ -1344,6 +1352,14 @@ bool RsAccounts::ImportIdentityFromString(const std::string& data,RsPgpId& im
return rsAccountsDetails->importIdentityFromString(data,imported_pgp_id,import_error);
}
/*static*/ bool RsAccounts::exportIdentityToString(
std::string& data, const RsPgpId& pgpId, std::string& errorMsg,
bool includeSignatures )
{
return rsAccountsDetails->exportIdentityToString(
data, pgpId, includeSignatures, errorMsg);
}
void RsAccounts::GetUnsupportedKeys(std::map<std::string,std::vector<std::string> > &unsupported_keys)
{
return rsAccountsDetails->getUnsupportedKeys(unsupported_keys);

View file

@ -99,6 +99,9 @@ class RsAccountsDetail
// PGP Support Functions.
bool exportIdentity(const std::string& fname,const RsPgpId& pgp_id) ;
bool importIdentity(const std::string& fname,RsPgpId& imported_pgp_id,std::string& import_error) ;
bool exportIdentityToString(
std::string& data, const RsPgpId& pgpId, bool includeSignatures,
std::string& errorMsg );
bool importIdentityFromString(const std::string& data,RsPgpId& imported_pgp_id,std::string& import_error) ;
void getUnsupportedKeys(std::map<std::string,std::vector<std::string> > &unsupported_keys);
bool copyGnuPGKeyrings() ;

View file

@ -94,6 +94,10 @@ RsDht *rsDht = NULL ;
# include "gxstrans/p3gxstrans.h"
#endif
#ifdef RS_JSONAPI
# include "jsonapi/jsonapi.h"
#endif
// #define GPG_DEBUG
// #define AUTHSSL_DEBUG
// #define FIM_DEBUG
@ -105,15 +109,15 @@ RsLoginHelper* rsLoginHelper = nullptr;
RsAccounts* rsAccounts = nullptr;
class RsInitConfig
struct RsInitConfig
{
public:
RsInitConfig() : jsonApiPort(0), jsonApiBindAddress("127.0.0.1") {}
RsFileHash main_executable_hash;
RsFileHash main_executable_hash;
#ifdef WINDOWS_SYS
bool portable;
bool isWindowsXP;
bool portable;
bool isWindowsXP;
#endif
rs_lock_handle_t lockHandle;
@ -146,31 +150,25 @@ class RsInitConfig
int debugLevel;
std::string logfname;
bool load_trustedpeer;
std::string load_trustedpeer_file;
bool udpListenerOnly;
std::string opModeStr;
uint16_t jsonApiPort;
std::string jsonApiBindAddress;
};
static RsInitConfig *rsInitConfig = NULL;
//const int p3facestartupzone = 47238;
// initial configuration bootstrapping...
//static const std::string configInitFile = "default_cert.txt";
//static const std::string configConfFile = "config.rs";
//static const std::string configCertDir = "friends";
//static const std::string configKeyDir = "keys";
//static const std::string configCaFile = "cacerts.pem";
//static const std::string configHelpName = "retro.htm";
static RsInitConfig* rsInitConfig = nullptr;
static const std::string configLogFileName = "retro.log";
static const int SSLPWD_LEN = 64;
void RsInit::InitRsConfig()
{
rsInitConfig = new RsInitConfig ;
rsInitConfig = new RsInitConfig;
/* TODO almost all of this should be moved to RsInitConfig::RsInitConfig
* initializers */
/* Directories */
#ifdef WINDOWS_SYS
@ -181,14 +179,13 @@ void RsInit::InitRsConfig()
rsInitConfig->hiddenNodeSet = false;
// This doesn't seems a configuration...
#ifndef WINDOWS_SYS
rsInitConfig->lockHandle = -1;
#else
rsInitConfig->lockHandle = NULL;
#endif
rsInitConfig->load_trustedpeer = false;
rsInitConfig->port = 0 ;
rsInitConfig->forceLocalAddr = false;
rsInitConfig->haveLogFile = false;
@ -204,9 +201,6 @@ void RsInit::InitRsConfig()
rsInitConfig->udpListenerOnly = false;
rsInitConfig->opModeStr = std::string("");
/* setup the homePath (default save location) */
// rsInitConfig->homePath = getHomePath();
#ifdef WINDOWS_SYS
// test for portable version
if (GetFileAttributes(L"portable") != (DWORD) -1) {
@ -243,31 +237,7 @@ void RsInit::InitRsConfig()
}
#endif
/* Setup the Debugging */
// setup debugging for desired zones.
setOutputLevel(RsLog::Warning); // default to Warnings.
// For Testing purposes.
// We can adjust everything under Linux.
//setZoneLevel(PQL_DEBUG_BASIC, 38422); // pqipacket.
//setZoneLevel(PQL_DEBUG_BASIC, 96184); // pqinetwork;
//setZoneLevel(PQL_DEBUG_BASIC, 82371); // pqiperson.
//setZoneLevel(PQL_DEBUG_BASIC, 34283); // pqihandler.
//setZoneLevel(PQL_DEBUG_BASIC, 44863); // discItems.
//setZoneLevel(PQL_DEBUG_BASIC, 1728); // pqi/p3proxy
//setZoneLevel(PQL_DEBUG_BASIC, 1211); // sslroot.
//setZoneLevel(PQL_DEBUG_BASIC, 37714); // pqissl.
//setZoneLevel(PQL_DEBUG_BASIC, 8221); // pqistreamer.
//setZoneLevel(PQL_DEBUG_BASIC, 9326); // pqiarchive
//setZoneLevel(PQL_DEBUG_BASIC, 3334); // p3channel.
//setZoneLevel(PQL_DEBUG_BASIC, 354); // pqipersongrp.
//setZoneLevel(PQL_DEBUG_BASIC, 6846); // pqiudpproxy
//setZoneLevel(PQL_DEBUG_BASIC, 3144); // pqissludp;
//setZoneLevel(PQL_DEBUG_BASIC, 86539); // pqifiler.
//setZoneLevel(PQL_DEBUG_BASIC, 91393); // Funky_Browser.
//setZoneLevel(PQL_DEBUG_BASIC, 25915); // fltkserver
//setZoneLevel(PQL_DEBUG_BASIC, 47659); // fldxsrvr
//setZoneLevel(PQL_DEBUG_BASIC, 49787); // pqissllistener
setOutputLevel(RsLog::Warning);
}
/********
@ -294,69 +264,60 @@ bool doPortRestrictions = false;
int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
{
#ifdef DEBUG_RSINIT
for(int i=0; i<argc; i++)
printf("%d: %s\n", i, argv[i]);
for(int i=0; i<argc; i++) printf("%d: %s\n", i, argv[i]);
#endif
/* for static PThreads under windows... we need to init the library... */
#ifdef PTW32_STATIC_LIB
pthread_win32_process_attach_np();
// for static PThreads under windows... we need to init the library...
pthread_win32_process_attach_np();
#endif
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
std::string prefUserString = "";
std::string opt_base_dir;
/* getopt info: every availiable option is listed here. if it is followed by a ':' it
needs an argument. If it is followed by a '::' the argument is optional.
*/
//rsInitConfig->logfname = "" ;
//rsInitConfig->inet = "" ;
std::string prefUserString = "";
std::string opt_base_dir;
#ifdef __APPLE__
/* HACK to avoid stupid OSX Finder behaviour
// TODO: is this still needed with argstream?
/* HACK to avoid stupid OSX Finder behaviour
* remove the commandline arguments - if we detect we are launched from Finder,
* and we have the unparsable "-psn_0_12332" option.
* this is okay, as you cannot pass commandline arguments via Finder anyway
*/
if ((argc >= 2) && (0 == strncmp(argv[1], "-psn", 4)))
{
argc = 1;
}
if ((argc >= 2) && (0 == strncmp(argv[1], "-psn", 4))) argc = 1;
#endif
argstream as(argc,argv) ;
argstream as(argc,argv);
as >> option('m',"minimized" ,rsInitConfig->startMinimised ,"Start minimized." )
>> option('s',"stderr" ,rsInitConfig->outStderr ,"output to stderr instead of log file." )
>> option('u',"udp" ,rsInitConfig->udpListenerOnly,"Only listen to UDP." )
>> option('e',"external-port" ,rsInitConfig->forceExtPort ,"Use a forwarded external port." )
>> parameter('l',"log-file" ,rsInitConfig->logfname ,"logfile" ,"Set Log filename." ,false)
>> parameter('d',"debug-level" ,rsInitConfig->debugLevel ,"level" ,"Set debug level." ,false)
>> parameter('i',"ip-address" ,rsInitConfig->inet ,"nnn.nnn.nnn.nnn", "Force IP address to use (if cannot be detected)." ,false)
>> parameter('o',"opmode" ,rsInitConfig->opModeStr ,"opmode" ,"Set Operating mode (Full, NoTurtle, Gaming, Minimal)." ,false)
>> parameter('p',"port" ,rsInitConfig->port ,"port", "Set listenning port to use." ,false)
>> parameter('c',"base-dir" ,opt_base_dir ,"directory", "Set base directory." ,false)
>> parameter('U',"user-id" ,prefUserString ,"ID", "[ocation Id] Sets Account to Use, Useful when Autologin is enabled.",false);
#ifdef RS_JSONAPI
as >> parameter(
"jsonApiPort", rsInitConfig->jsonApiPort, "jsonApiPort",
"Enable JSON API on the specified port", false )
>> parameter(
"jsonApiBindAddress", rsInitConfig->jsonApiBindAddress,
"jsonApiBindAddress", "JSON API Bind Address.", false);
#endif // ifdef RS_JSONAPI
as
#ifdef RS_AUTOLOGIN
>> option('a',"auto-login" ,rsInitConfig->autoLogin ,"AutoLogin (Windows Only) + StartMinimised")
#endif
>> option('m',"minimized" ,rsInitConfig->startMinimised ,"Start minimized." )
>> option('s',"stderr" ,rsInitConfig->outStderr ,"output to stderr instead of log file." )
>> option('u',"udp" ,rsInitConfig->udpListenerOnly,"Only listen to UDP." )
>> option('e',"external-port" ,rsInitConfig->forceExtPort ,"Use a forwarded external port." )
>> parameter('l',"log-file" ,rsInitConfig->logfname ,"logfile" ,"Set Log filename." ,false)
>> parameter('d',"debug-level" ,rsInitConfig->debugLevel ,"level" ,"Set debug level." ,false)
#ifdef TO_REMOVE
// This was removed because it is not used anymore.
>> parameter('w',"password" ,rsInitConfig->passwd ,"password" ,"Set Login Password." ,false)
#endif
>> parameter('i',"ip-address" ,rsInitConfig->inet ,"nnn.nnn.nnn.nnn", "Force IP address to use (if cannot be detected)." ,false)
>> parameter('o',"opmode" ,rsInitConfig->opModeStr ,"opmode" ,"Set Operating mode (Full, NoTurtle, Gaming, Minimal)." ,false)
>> parameter('p',"port" ,rsInitConfig->port ,"port", "Set listenning port to use." ,false)
>> parameter('c',"base-dir" ,opt_base_dir ,"directory", "Set base directory." ,false)
>> parameter('U',"user-id" ,prefUserString ,"ID", "[ocation Id] Sets Account to Use, Useful when Autologin is enabled.",false)
// by rshare 'r' "link" "Link" "Open RsLink with protocol retroshare://"
// by rshare 'f' "rsfile" "RsFile" "Open RsFile like RsCollection"
#ifdef LOCALNET_TESTING
>> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false)
#endif
>> help('h',"help","Display this Help") ;
as >> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false);
#endif // ifdef LOCALNET_TESTING
as.defaultErrorHandling(true,true) ;
#ifdef RS_AUTOLOGIN
as >> option('a',"auto-login" ,rsInitConfig->autoLogin ,"AutoLogin (Windows Only) + StartMinimised");
#endif // ifdef RS_AUTOLOGIN
as >> help('h',"help","Display this Help");
as.defaultErrorHandling(true,true);
if(rsInitConfig->autoLogin) rsInitConfig->startMinimised = true ;
if(rsInitConfig->outStderr) rsInitConfig->haveLogFile = false ;
@ -477,6 +438,16 @@ int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
}
#endif
#ifdef RS_JSONAPI
if(rsInitConfig->jsonApiPort)
{
jsonApiServer = new JsonApiServer(
rsInitConfig->jsonApiPort,
rsInitConfig->jsonApiBindAddress );
jsonApiServer->start("JSON API Server");
}
#endif // ifdef RS_JSONAPI
return RS_INIT_OK;
}
@ -1277,6 +1248,14 @@ int RsServer::StartupRetroShare()
//
mPluginsManager->loadPlugins(programatically_inserted_plugins) ;
#ifdef RS_JSONAPI
{
mConfigMgr->addConfiguration("jsonApi.cfg", jsonApiServer);
RsFileHash dummyHash;
jsonApiServer->loadConfiguration(dummyHash);
}
#endif
/**** Reputation system ****/
p3GxsReputation *mReputations = new p3GxsReputation(mLinkMgr) ;
@ -1940,6 +1919,7 @@ int RsServer::StartupRetroShare()
RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin(
const RsPeerId& account, const std::string& password)
{
if(isLoggedIn()) return RsInit::ERR_ALREADY_RUNNING;
if(!rsNotify->cachePgpPassphrase(password)) return RsInit::ERR_UNKOWN;
if(!rsNotify->setDisableAskPassword(true)) return RsInit::ERR_UNKOWN;
if(!RsAccounts::SelectAccount(account)) return RsInit::ERR_UNKOWN;
@ -1973,6 +1953,8 @@ bool RsLoginHelper::createLocation(
RsLoginHelper::Location& l, const std::string& password,
bool makeHidden, bool makeAutoTor, std::string& errorMessage )
{
if(isLoggedIn()) return (errorMessage="Already Running", false);
if(l.mLocationName.empty())
{
errorMessage = "Location name is needed";