mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-19 20:04:24 -04:00
Merge pull request #1349 from G10h4ck/jsonapi
Implement JSON API HTTP Basic authentication
This commit is contained in:
commit
f09bef2ac8
42 changed files with 1302 additions and 425 deletions
|
@ -55,7 +55,7 @@ extern RsGxsChannels* rsGxsChannels;
|
||||||
.Calling the JSON API with curl on the terminal
|
.Calling the JSON API with curl on the terminal
|
||||||
[source,bash]
|
[source,bash]
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
curl --data @paramethers.json http://127.0.0.1:9092/rsGxsChannels/createGroup
|
curl -u $API_USER --data @paramethers.json http://127.0.0.1:9092/rsGxsChannels/createGroup
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
.JSON API call result
|
.JSON API call result
|
||||||
|
@ -76,7 +76,7 @@ least in two different ways.
|
||||||
.Calling the JSON API with GET method with curl on the terminal
|
.Calling the JSON API with GET method with curl on the terminal
|
||||||
[source,bash]
|
[source,bash]
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
curl --get --data-urlencode jsonData@paramethers.json \
|
curl -u $API_USER --get --data-urlencode jsonData@paramethers.json \
|
||||||
http://127.0.0.1:9092/rsGxsChannels/createGroup
|
http://127.0.0.1:9092/rsGxsChannels/createGroup
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -85,12 +85,53 @@ equivalent to the following.
|
||||||
|
|
||||||
.Calling the JSON API with GET method and pre-encoded data with curl on the terminal
|
.Calling the JSON API with GET method and pre-encoded data with curl on the terminal
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
curl http://127.0.0.1:9092/rsGxsChannels/createGroup?jsonData=%7B%0A%20%20%20%20%22group%22%3A%7B%0A%20%20%20%20%20%20%20%20%22mMeta%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupName%22%3A%22JSON%20test%20group%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupFlags%22%3A4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mSignFlags%22%3A520%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22mDescription%22%3A%22JSON%20test%20group%20description%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22caller_data%22%3A%22Here%20can%20go%20any%20kind%20of%20JSON%20data%20%28even%20objects%29%20that%20the%20caller%20want%20to%20get%20back%20together%20with%20the%20response%22%0A%7D
|
curl -u $API_USER http://127.0.0.1:9092/rsGxsChannels/createGroup?jsonData=%7B%0A%20%20%20%20%22group%22%3A%7B%0A%20%20%20%20%20%20%20%20%22mMeta%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupName%22%3A%22JSON%20test%20group%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupFlags%22%3A4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mSignFlags%22%3A520%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22mDescription%22%3A%22JSON%20test%20group%20description%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22caller_data%22%3A%22Here%20can%20go%20any%20kind%20of%20JSON%20data%20%28even%20objects%29%20that%20the%20caller%20want%20to%20get%20back%20together%20with%20the%20response%22%0A%7D
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Note that using +GET+ method +?jsonData=+ and then the JSON data URL encoded are
|
Note that using +GET+ method +?jsonData=+ and then the JSON data URL encoded are
|
||||||
added after the path in the HTTP request.
|
added after the path in the HTTP request.
|
||||||
|
|
||||||
|
|
||||||
|
== JSON API authentication
|
||||||
|
|
||||||
|
Most of JSON API methods require authentication as they give access to
|
||||||
|
RetroShare user data, and we don't want any application running on the system
|
||||||
|
eventually by other users be able to access private data indiscriminately.
|
||||||
|
JSON API support HTTP Basic as authentication scheme, this is enough as JSON API
|
||||||
|
server is intented for usage on the same system (127.0.0.1) not over an
|
||||||
|
untrusted network.
|
||||||
|
If you need to use JSON API over an untrusted network consider using a reverse
|
||||||
|
proxy with HTTPS such as NGINX in front of JSON API server.
|
||||||
|
If RetroShare login has been effectuated through the JSON API you can use your
|
||||||
|
location SSLID as username and your PGP password as credential for the JSON API,
|
||||||
|
but we suggests you use specific meaningful and human readable credentials for
|
||||||
|
each JSON API client so the human user can have better control over which client
|
||||||
|
can access the JSON API.
|
||||||
|
|
||||||
|
.NewToken.json
|
||||||
|
[source,json]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
{
|
||||||
|
"token": "myNewUser:myNewPassword"
|
||||||
|
}
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.An authenticated client can authorize new tokens like this
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
curl -u $API_USER --data @NewToken.json http://127.0.0.1:9092/jsonApiServer/authorizeToken
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.An unauthenticated JSON API client can request access with
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
curl --data @NewToken.json http://127.0.0.1:9092/jsonApiServer/requestNewTokenAutorization
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
When an unauthenticated client request his token to be authorized, JSON API
|
||||||
|
server will try to ask confirmation to the human user if possible through
|
||||||
|
+mNewAccessRequestCallback+, if it is not possible or the user didn't authorized
|
||||||
|
the token +false+ is returned.
|
||||||
|
|
||||||
|
|
||||||
== Offer new RetroShare services through JSON API
|
== Offer new RetroShare services through JSON API
|
||||||
|
|
||||||
To offer a retroshare service through the JSON API, first of all one need find
|
To offer a retroshare service through the JSON API, first of all one need find
|
||||||
|
@ -231,6 +272,17 @@ data: {"results":[{"size":668,"hash":"e8845280912ebf3779e400000000000000000000",
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
By default JSON API methods requires client authentication and their wrappers
|
||||||
|
are automatically generated by +json-api-generator+.
|
||||||
|
In some cases methods need do be accessible without authentication such as
|
||||||
|
+rsLoginHelper/getLocations+ so in the doxygen documentaion they have the custom
|
||||||
|
command +@jsonapi{RS_VERSION,unauthenticated}+.
|
||||||
|
Other methods such as +/rsControl/rsGlobalShutDown+ need special care so they
|
||||||
|
are marked with the custom doxygen command +@jsonapi{RS_VERSION,manualwrapper}+
|
||||||
|
and their wrappers are not automatically generated but written manually into
|
||||||
|
+JsonApiServer::JsonApiServer(...)+.
|
||||||
|
|
||||||
|
|
||||||
== A bit of history
|
== A bit of history
|
||||||
|
|
||||||
=== First writings about this
|
=== First writings about this
|
||||||
|
|
|
@ -61,5 +61,5 @@ $%outputParamsSerialization%$
|
||||||
session->yield(message.str());
|
session->yield(message.str());
|
||||||
$%sessionDelayedClose%$
|
$%sessionDelayedClose%$
|
||||||
} );
|
} );
|
||||||
});
|
}, $%requiresAuth%$);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ DOXYFILE_ENCODING = UTF-8
|
||||||
PROJECT_NAME = "libretroshare"
|
PROJECT_NAME = "libretroshare"
|
||||||
|
|
||||||
ALIASES += jsonapi{1}="\xmlonly<jsonapi minversion=\"\1\"/>\endxmlonly"
|
ALIASES += jsonapi{1}="\xmlonly<jsonapi minversion=\"\1\"/>\endxmlonly"
|
||||||
|
ALIASES += jsonapi{2}="\xmlonly<jsonapi minversion=\"\1\" access=\"\2\"/>\endxmlonly"
|
||||||
|
|
||||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||||
# documentation from any documented member that it re-implements.
|
# documentation from any documented member that it re-implements.
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <QtCore/QDirIterator>
|
#include <QtCore/QDirIterator>
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <functional>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
struct MethodParam
|
struct MethodParam
|
||||||
{
|
{
|
||||||
|
@ -40,7 +42,10 @@ struct MethodParam
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if(argc != 3)
|
if(argc != 3)
|
||||||
qFatal("Usage: jsonapi-generator SOURCE_PATH OUTPUT_PATH");
|
{
|
||||||
|
qDebug() << "Usage: jsonapi-generator SOURCE_PATH OUTPUT_PATH";
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
QString sourcePath(argv[1]);
|
QString sourcePath(argv[1]);
|
||||||
QString outputPath(argv[2]);
|
QString outputPath(argv[2]);
|
||||||
|
@ -59,6 +64,20 @@ int main(int argc, char *argv[])
|
||||||
qFatal(QString("Can't open: " + cppApiIncludesFilePath).toLatin1().data());
|
qFatal(QString("Can't open: " + cppApiIncludesFilePath).toLatin1().data());
|
||||||
QSet<QString> cppApiIncludesSet;
|
QSet<QString> cppApiIncludesSet;
|
||||||
|
|
||||||
|
auto fatalError = [&](
|
||||||
|
std::initializer_list<QVariant> errors, int ernum = EINVAL )
|
||||||
|
{
|
||||||
|
QString errorMsg;
|
||||||
|
for(const QVariant& error: errors)
|
||||||
|
errorMsg += error.toString() + " ";
|
||||||
|
errorMsg.chop(1);
|
||||||
|
QByteArray cppError(QString("#error "+errorMsg+"\n").toLocal8Bit());
|
||||||
|
wrappersDefFile.write(cppError);
|
||||||
|
cppApiIncludesFile.write(cppError);
|
||||||
|
qDebug() << errorMsg;
|
||||||
|
return ernum;
|
||||||
|
};
|
||||||
|
|
||||||
QDirIterator it(doxPrefix, QStringList() << "*8h.xml", QDir::Files);
|
QDirIterator it(doxPrefix, QStringList() << "*8h.xml", QDir::Files);
|
||||||
while(it.hasNext())
|
while(it.hasNext())
|
||||||
{
|
{
|
||||||
|
@ -74,9 +93,10 @@ int main(int argc, char *argv[])
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFileInfo hfi(hFile);
|
QFileInfo headerFileInfo(hDoc.elementsByTagName("location").at(0)
|
||||||
QString headerFileName(hfi.fileName());
|
.attributes().namedItem("file").nodeValue());
|
||||||
headerFileName.replace(QString("_8h.xml"), QString(".h"));
|
QString headerRelPath = headerFileInfo.dir().dirName() + "/" +
|
||||||
|
headerFileInfo.fileName();
|
||||||
|
|
||||||
QDomNodeList sectiondefs = hDoc.elementsByTagName("memberdef");
|
QDomNodeList sectiondefs = hDoc.elementsByTagName("memberdef");
|
||||||
for(int j = 0; j < sectiondefs.size(); ++j)
|
for(int j = 0; j < sectiondefs.size(); ++j)
|
||||||
|
@ -112,6 +132,7 @@ int main(int argc, char *argv[])
|
||||||
QDomNode member = members.item(i);
|
QDomNode member = members.item(i);
|
||||||
QString refid(member.attributes().namedItem("refid").nodeValue());
|
QString refid(member.attributes().namedItem("refid").nodeValue());
|
||||||
QString methodName(member.firstChildElement("name").toElement().text());
|
QString methodName(member.firstChildElement("name").toElement().text());
|
||||||
|
bool requiresAuth = true;
|
||||||
QString defFilePath(doxPrefix + refid.split('_')[0] + ".xml");
|
QString defFilePath(doxPrefix + refid.split('_')[0] + ".xml");
|
||||||
|
|
||||||
qDebug() << "Looking for" << typeName << methodName << "into"
|
qDebug() << "Looking for" << typeName << methodName << "into"
|
||||||
|
@ -134,10 +155,21 @@ int main(int argc, char *argv[])
|
||||||
QDomElement tmpMBD = memberdefs.item(k).toElement();
|
QDomElement tmpMBD = memberdefs.item(k).toElement();
|
||||||
QString tmpId = tmpMBD.attributes().namedItem("id").nodeValue();
|
QString tmpId = tmpMBD.attributes().namedItem("id").nodeValue();
|
||||||
QString tmpKind = tmpMBD.attributes().namedItem("kind").nodeValue();
|
QString tmpKind = tmpMBD.attributes().namedItem("kind").nodeValue();
|
||||||
bool hasJsonApi = !tmpMBD.elementsByTagName("jsonapi").isEmpty();
|
QDomNodeList tmpJsonApiTagList(tmpMBD.elementsByTagName("jsonapi"));
|
||||||
if( tmpId == refid && tmpKind == "function" && hasJsonApi )
|
|
||||||
|
if( tmpJsonApiTagList.count() && tmpId == refid &&
|
||||||
|
tmpKind == "function")
|
||||||
{
|
{
|
||||||
memberdef = tmpMBD;
|
QDomElement tmpJsonApiTag = tmpJsonApiTagList.item(0).toElement();
|
||||||
|
QString tmpAccessValue;
|
||||||
|
if(tmpJsonApiTag.hasAttribute("access"))
|
||||||
|
tmpAccessValue = tmpJsonApiTag.attributeNode("access").nodeValue();
|
||||||
|
|
||||||
|
requiresAuth = "unauthenticated" != tmpAccessValue;
|
||||||
|
|
||||||
|
if("manualwrapper" != tmpAccessValue)
|
||||||
|
memberdef = tmpMBD;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +221,7 @@ int main(int argc, char *argv[])
|
||||||
pType.replace(QString("&"), QString());
|
pType.replace(QString("&"), QString());
|
||||||
pType.replace(QString(" "), QString());
|
pType.replace(QString(" "), QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap.insert(tmpParam.name, tmpParam);
|
paramsMap.insert(tmpParam.name, tmpParam);
|
||||||
orderedParamNames.push_back(tmpParam.name);
|
orderedParamNames.push_back(tmpParam.name);
|
||||||
}
|
}
|
||||||
|
@ -211,6 +244,16 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Params sanity check
|
||||||
|
for( const MethodParam& pm : paramsMap)
|
||||||
|
if( !(pm.isMultiCallback || pm.isSingleCallback
|
||||||
|
|| pm.in || pm.out) )
|
||||||
|
return fatalError(
|
||||||
|
{ "Parameter:", pm.name, "of:", apiPath,
|
||||||
|
"declared in:", headerRelPath,
|
||||||
|
"miss doxygen parameter direction attribute!",
|
||||||
|
defFile.fileName() });
|
||||||
|
|
||||||
QString functionCall("\t\t");
|
QString functionCall("\t\t");
|
||||||
if(retvalType != "void")
|
if(retvalType != "void")
|
||||||
{
|
{
|
||||||
|
@ -325,7 +368,6 @@ int main(int argc, char *argv[])
|
||||||
substitutionsMap.insert("inputParamsDeserialization", inputParamsDeserialization);
|
substitutionsMap.insert("inputParamsDeserialization", inputParamsDeserialization);
|
||||||
substitutionsMap.insert("outputParamsSerialization", outputParamsSerialization);
|
substitutionsMap.insert("outputParamsSerialization", outputParamsSerialization);
|
||||||
substitutionsMap.insert("instanceName", instanceName);
|
substitutionsMap.insert("instanceName", instanceName);
|
||||||
substitutionsMap.insert("headerFileName", headerFileName);
|
|
||||||
substitutionsMap.insert("functionCall", functionCall);
|
substitutionsMap.insert("functionCall", functionCall);
|
||||||
substitutionsMap.insert("apiPath", apiPath);
|
substitutionsMap.insert("apiPath", apiPath);
|
||||||
substitutionsMap.insert("sessionEarlyClose", sessionEarlyClose);
|
substitutionsMap.insert("sessionEarlyClose", sessionEarlyClose);
|
||||||
|
@ -334,6 +376,7 @@ int main(int argc, char *argv[])
|
||||||
substitutionsMap.insert("callbackName", callbackName);
|
substitutionsMap.insert("callbackName", callbackName);
|
||||||
substitutionsMap.insert("callbackParams", callbackParams);
|
substitutionsMap.insert("callbackParams", callbackParams);
|
||||||
substitutionsMap.insert("callbackParamsSerialization", callbackParamsSerialization);
|
substitutionsMap.insert("callbackParamsSerialization", callbackParamsSerialization);
|
||||||
|
substitutionsMap.insert("requiresAuth", requiresAuth ? "true" : "false");
|
||||||
|
|
||||||
QString templFilePath(sourcePath);
|
QString templFilePath(sourcePath);
|
||||||
if(hasMultiCallback || hasSingleCallback)
|
if(hasMultiCallback || hasSingleCallback)
|
||||||
|
@ -351,7 +394,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
wrappersDefFile.write(wrapperDef.toLocal8Bit());
|
wrappersDefFile.write(wrapperDef.toLocal8Bit());
|
||||||
|
|
||||||
cppApiIncludesSet.insert("#include \"retroshare/" + headerFileName + "\"\n");
|
cppApiIncludesSet.insert("#include \"" + headerRelPath + "\"\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,5 +44,5 @@ $%outputParamsSerialization%$
|
||||||
// return them to the API caller
|
// return them to the API caller
|
||||||
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
||||||
} );
|
} );
|
||||||
});
|
}, $%requiresAuth%$);
|
||||||
|
|
||||||
|
|
|
@ -432,9 +432,8 @@ void RsControlModule::handleLogin(Request &req, Response &resp)
|
||||||
|
|
||||||
void RsControlModule::handleShutdown(Request &, Response &resp)
|
void RsControlModule::handleShutdown(Request &, Response &resp)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mExitFlagMtx); // ********** LOCKED **********
|
requestShutdown();
|
||||||
mProcessShouldExit = true;
|
resp.setOk();
|
||||||
resp.setOk();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsControlModule::handleImportPgp(Request &req, Response &resp)
|
void RsControlModule::handleImportPgp(Request &req, Response &resp)
|
||||||
|
@ -582,6 +581,12 @@ bool RsControlModule::askForDeferredSelfSignature(const void *data, const uint32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RsControlModule::requestShutdown()
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mExitFlagMtx);
|
||||||
|
mProcessShouldExit = true;
|
||||||
|
}
|
||||||
|
|
||||||
void RsControlModule::setRunState(RunState s, std::string errstr)
|
void RsControlModule::setRunState(RunState s, std::string errstr)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mDataMtx); // ********** LOCKED **********
|
RS_STACK_MUTEX(mDataMtx); // ********** LOCKED **********
|
||||||
|
|
|
@ -62,6 +62,8 @@ public:
|
||||||
virtual bool askForPassword(const std::string &title, const std::string& key_details, bool prev_is_bad , std::string& password,bool& canceled) override;
|
virtual bool askForPassword(const std::string &title, const std::string& key_details, bool prev_is_bad , std::string& password,bool& canceled) override;
|
||||||
virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason = "") override;
|
virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason = "") override;
|
||||||
|
|
||||||
|
virtual bool requestShutdown();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// from RsThread
|
// from RsThread
|
||||||
// wee need a thread to call into things which block like askForPassword()
|
// wee need a thread to call into things which block like askForPassword()
|
||||||
|
|
|
@ -18,19 +18,28 @@
|
||||||
|
|
||||||
#include "jsonapi.h"
|
#include "jsonapi.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <restbed>
|
#include <restbed>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
|
||||||
#include "util/rsjson.h"
|
#include "util/rsjson.h"
|
||||||
#include "retroshare/rsfiles.h"
|
#include "retroshare/rsfiles.h"
|
||||||
#include "util/radix64.h"
|
#include "util/radix64.h"
|
||||||
#include "retroshare/rsversion.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
|
// Generated at compile time
|
||||||
#include "jsonapi-includes.inl"
|
#include "jsonapi-includes.inl"
|
||||||
|
|
||||||
|
/*extern*/ JsonApiServer* jsonApiServer = nullptr;
|
||||||
|
|
||||||
#define INITIALIZE_API_CALL_JSON_CONTEXT \
|
#define INITIALIZE_API_CALL_JSON_CONTEXT \
|
||||||
RsGenericSerializer::SerializeContext cReq( \
|
RsGenericSerializer::SerializeContext cReq( \
|
||||||
nullptr, 0, \
|
nullptr, 0, \
|
||||||
|
@ -71,10 +80,10 @@ static bool checkRsServicePtrReady(
|
||||||
{
|
{
|
||||||
if(serviceInstance) return true;
|
if(serviceInstance) return true;
|
||||||
|
|
||||||
std::string jsonApiError;
|
std::string jsonApiError = __PRETTY_FUNCTION__;
|
||||||
jsonApiError += "Service: ";
|
jsonApiError += "Service: ";
|
||||||
jsonApiError += serviceName;
|
jsonApiError += serviceName;
|
||||||
jsonApiError += " not initialized! Are you sure you logged in already?";
|
jsonApiError += " not initialized!";
|
||||||
|
|
||||||
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
|
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
|
||||||
RS_SERIAL_PROCESS(jsonApiError);
|
RS_SERIAL_PROCESS(jsonApiError);
|
||||||
|
@ -84,13 +93,53 @@ static bool checkRsServicePtrReady(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonApiServer::JsonApiServer(uint16_t port, const std::string& bindAddress,
|
||||||
JsonApiServer::JsonApiServer(
|
const std::function<bool(const std::string&)> newAccessRequestCallback ) :
|
||||||
uint16_t port, const std::string& bindAddress,
|
mPort(port), mBindAddress(bindAddress),
|
||||||
const std::function<void(int)> shutdownCallback ) :
|
mNewAccessRequestCallback(newAccessRequestCallback),
|
||||||
mPort(port), mBindAddress(bindAddress), mShutdownCallback(shutdownCallback)
|
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)
|
[this](const std::shared_ptr<rb::Session> session)
|
||||||
{
|
{
|
||||||
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
||||||
|
@ -100,37 +149,9 @@ JsonApiServer::JsonApiServer(
|
||||||
{
|
{
|
||||||
INITIALIZE_API_CALL_JSON_CONTEXT;
|
INITIALIZE_API_CALL_JSON_CONTEXT;
|
||||||
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
||||||
shutdown();
|
rsControl->rsGlobalShutDown();
|
||||||
} );
|
} );
|
||||||
});
|
}, true);
|
||||||
|
|
||||||
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);
|
|
||||||
} );
|
|
||||||
});
|
|
||||||
|
|
||||||
registerHandler("/rsFiles/getFileData",
|
registerHandler("/rsFiles/getFileData",
|
||||||
[](const std::shared_ptr<rb::Session> session)
|
[](const std::shared_ptr<rb::Session> session)
|
||||||
|
@ -186,7 +207,7 @@ JsonApiServer::JsonApiServer(
|
||||||
|
|
||||||
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
||||||
} );
|
} );
|
||||||
});
|
}, true);
|
||||||
|
|
||||||
// Generated at compile time
|
// Generated at compile time
|
||||||
#include "jsonapi-wrappers.inl"
|
#include "jsonapi-wrappers.inl"
|
||||||
|
@ -198,22 +219,191 @@ void JsonApiServer::run()
|
||||||
settings->set_port(mPort);
|
settings->set_port(mPort);
|
||||||
settings->set_bind_address(mBindAddress);
|
settings->set_bind_address(mBindAddress);
|
||||||
settings->set_default_header("Cache-Control", "no-cache");
|
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);
|
mService.start(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonApiServer::registerHandler(
|
void JsonApiServer::registerHandler(
|
||||||
const std::string& path,
|
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);
|
std::shared_ptr<restbed::Resource> resource(new rb::Resource);
|
||||||
resource->set_path(path);
|
resource->set_path(path);
|
||||||
resource->set_method_handler("GET", handler);
|
resource->set_method_handler("GET", handler);
|
||||||
resource->set_method_handler("POST", 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);
|
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();
|
if(rsLoginHelper->isLoggedIn() && mNewAccessRequestCallback(token))
|
||||||
mShutdownCallback(exitCode);
|
return authorizeToken(token);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JsonApiServer::isAuthTokenValid(const std::string& token)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(configMutex);
|
||||||
|
|
||||||
|
// attempt avoiding +else CRYPTO_memcmp+ being optimized away
|
||||||
|
int noOptimiz = 1;
|
||||||
|
|
||||||
|
/* Do not use mAuthTokenStorage.mAuthorizedTokens.count(token), because
|
||||||
|
* std::string comparison is usually not constant time on content to be
|
||||||
|
* faster, so an attacker may use timings to guess authorized tokens */
|
||||||
|
for(const std::string& vTok : mAuthTokenStorage.mAuthorizedTokens)
|
||||||
|
{
|
||||||
|
if( token.size() == vTok.size() &&
|
||||||
|
( noOptimiz = CRYPTO_memcmp( token.data(), vTok.data(),
|
||||||
|
vTok.size() ) ) == 0 )
|
||||||
|
return true;
|
||||||
|
// Make token size guessing harder
|
||||||
|
else noOptimiz = CRYPTO_memcmp(token.data(), token.data(), token.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt avoiding +else CRYPTO_memcmp+ being optimized away
|
||||||
|
return static_cast<uint32_t>(noOptimiz) + 1 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(); }
|
||||||
|
|
||||||
|
|
|
@ -15,36 +15,59 @@
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <restbed>
|
#include <restbed>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "util/rsthreads.h"
|
||||||
|
#include "pqi/p3cfgmgr.h"
|
||||||
|
#include "rsitems/rsitem.h"
|
||||||
|
#include "jsonapi/jsonapiitems.h"
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
|
|
||||||
namespace rb = restbed;
|
namespace rb = restbed;
|
||||||
|
|
||||||
|
struct JsonApiServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to global instance of JsonApiServer
|
||||||
|
* @jsonapi{development}
|
||||||
|
*/
|
||||||
|
extern JsonApiServer* jsonApiServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple usage
|
* Simple usage
|
||||||
* \code{.cpp}
|
* \code{.cpp}
|
||||||
* JsonApiServer jas(9092);
|
* JsonApiServer jas(9092);
|
||||||
|
* jsonApiServer = &jas;
|
||||||
* jas.start("JsonApiServer");
|
* jas.start("JsonApiServer");
|
||||||
* \endcode
|
* \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(
|
JsonApiServer(
|
||||||
uint16_t port = 9092,
|
uint16_t port = 9092,
|
||||||
const std::string& bindAddress = "127.0.0.1",
|
const std::string& bindAddress = "127.0.0.1",
|
||||||
const std::function<void(int)> shutdownCallback = [](int){} );
|
const std::function<bool(const std::string&)> newAccessRequestCallback = [](const std::string&){return false;} );
|
||||||
|
|
||||||
/// @see RsSingleJobThread
|
|
||||||
virtual void run();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param[in] path Path itno which publish the API call
|
* @param[in] path Path itno which publish the API call
|
||||||
* @param[in] handler function which will be called to handle the requested
|
* @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:
|
* path, the function must be declared like:
|
||||||
* \code{.cpp}
|
* \code{.cpp}
|
||||||
* void functionName(const shared_ptr<restbed::Session> session)
|
* void functionName(const shared_ptr<restbed::Session> session)
|
||||||
|
@ -52,24 +75,118 @@ struct JsonApiServer : RsSingleJobThread
|
||||||
*/
|
*/
|
||||||
void registerHandler(
|
void registerHandler(
|
||||||
const std::string& path,
|
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
|
* @brief Set new access request callback
|
||||||
* @jsonapi{development}
|
* @param callback function to call when a new JSON API access is requested
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
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:
|
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 uint16_t mPort;
|
||||||
const std::string mBindAddress;
|
const std::string mBindAddress;
|
||||||
rb::Service mService;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
69
libretroshare/src/jsonapi/jsonapiitems.h
Normal file
69
libretroshare/src/jsonapi/jsonapiitems.h
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -918,7 +918,7 @@ rs_jsonapi {
|
||||||
# Force recalculation of libretroshare dependencies see https://stackoverflow.com/a/47884045
|
# Force recalculation of libretroshare dependencies see https://stackoverflow.com/a/47884045
|
||||||
QMAKE_EXTRA_TARGETS += libretroshare
|
QMAKE_EXTRA_TARGETS += libretroshare
|
||||||
|
|
||||||
HEADERS += jsonapi/jsonapi.h
|
HEADERS += jsonapi/jsonapi.h jsonapi/jsonapiitems.h
|
||||||
SOURCES += jsonapi/jsonapi.cpp
|
SOURCES += jsonapi/jsonapi.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -709,6 +709,36 @@ bool PGPHandler::exportGPGKeyPair(const std::string& filename,const RsPgpId& exp
|
||||||
return true ;
|
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
|
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();
|
ops_keyring_t *tmp_keyring = allocateOPSKeyring();
|
||||||
|
|
|
@ -99,6 +99,9 @@ class PGPHandler
|
||||||
bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_id,std::string& import_error) ;
|
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 importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) ;
|
||||||
bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_id) const ;
|
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 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) ;
|
bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) ;
|
||||||
|
|
|
@ -327,6 +327,14 @@ bool AuthGPG::exportProfile(const std::string& fname,const RsPgpId& exported_id)
|
||||||
return PGPHandler::exportGPGKeyPair(fname,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)
|
bool AuthGPG::importProfile(const std::string& fname,RsPgpId& imported_id,std::string& import_error)
|
||||||
{
|
{
|
||||||
return PGPHandler::importGPGKeyPair(fname,imported_id,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);
|
return PGPHandler::importGPGKeyPairFromString(data, gpg_id, import_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AuthGPG::active()
|
bool AuthGPG::active()
|
||||||
{
|
{
|
||||||
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
|
||||||
|
|
|
@ -158,6 +158,9 @@ public:
|
||||||
virtual bool importProfile(const std::string& filename,RsPgpId& gpg_id,std::string& import_error) ;
|
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 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 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) ;
|
virtual bool removeKeysFromPGPKeyring(const std::set<RsPgpId> &pgp_ids,std::string& backup_file,uint32_t& error_code) ;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
std::map<uint32_t, std::set<RsPeerId> >::iterator mit;
|
||||||
mit = mServicePeerMap.find(serviceId);
|
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;
|
std::map<uint32_t, std::set<RsPeerId> >::iterator mit;
|
||||||
mit = mServicePeerMap.find(serviceId);
|
mit = mServicePeerMap.find(serviceId);
|
||||||
|
|
|
@ -95,8 +95,8 @@ virtual bool getServicePermissions(uint32_t serviceId, RsServicePermissions &per
|
||||||
virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions);
|
virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions);
|
||||||
|
|
||||||
// Get List of Peers using this Service.
|
// Get List of Peers using this Service.
|
||||||
virtual void getPeersConnected(const uint32_t serviceId, std::set<RsPeerId> &peerSet);
|
virtual void getPeersConnected(uint32_t serviceId, std::set<RsPeerId> &peerSet);
|
||||||
virtual bool isPeerConnected(const uint32_t serviceId, const RsPeerId &peerId);
|
virtual bool isPeerConnected(uint32_t serviceId, const RsPeerId &peerId);
|
||||||
|
|
||||||
// Gets the list of items used by that service
|
// Gets the list of items used by that service
|
||||||
virtual bool getServiceItemNames(uint32_t serviceId,std::map<uint8_t,std::string>& names) ;
|
virtual bool getServiceItemNames(uint32_t serviceId,std::map<uint8_t,std::string>& names) ;
|
||||||
|
|
|
@ -204,7 +204,7 @@ public:
|
||||||
* as available or a sensible maximum. Expect a block size of around 1MiB.
|
* as available or a sensible maximum. Expect a block size of around 1MiB.
|
||||||
* To get more data, call this function repeatedly with different offsets.
|
* 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
|
* note the missing @ the wrapper for this is written manually not
|
||||||
* autogenerated @see JsonApiServer.
|
* autogenerated @see JsonApiServer.
|
||||||
*
|
*
|
||||||
|
|
|
@ -200,8 +200,8 @@ public:
|
||||||
* @brief Share channel publishing key
|
* @brief Share channel publishing key
|
||||||
* This can be used to authorize other peers to post on the channel
|
* This can be used to authorize other peers to post on the channel
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
* param[in] groupId Channel id
|
* @param[in] groupId Channel id
|
||||||
* param[in] peers peers to which share the key
|
* @param[in] peers peers to which share the key
|
||||||
* @return false on error, true otherwise
|
* @return false on error, true otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool groupShareKeys(
|
virtual bool groupShareKeys(
|
||||||
|
|
|
@ -19,24 +19,22 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef RETROSHARE_GUI_INTERFACE_H
|
#pragma once
|
||||||
#define RETROSHARE_GUI_INTERFACE_H
|
|
||||||
|
|
||||||
#include "retroshare/rsnotify.h"
|
#include "retroshare/rsnotify.h"
|
||||||
#include "rstypes.h"
|
#include "rstypes.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class NotifyBase;
|
|
||||||
class RsServer;
|
class RsServer;
|
||||||
class RsInit;
|
class RsInit;
|
||||||
class RsPeerCryptoParams;
|
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 */
|
/* extract various options for GUI */
|
||||||
const char *RsConfigDirectory(RsInit *config);
|
const char *RsConfigDirectory(RsInit *config);
|
||||||
bool RsConfigStartMinimised(RsInit *config);
|
bool RsConfigStartMinimised(RsInit *config);
|
||||||
|
@ -46,35 +44,50 @@ void CleanupRsConfig(RsInit *);
|
||||||
// Called First... (handles comandline options)
|
// Called First... (handles comandline options)
|
||||||
int InitRetroShare(int argc, char **argv, RsInit *config);
|
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:
|
public:
|
||||||
/// TODO: This should return a reference instead of a pointer!
|
/// TODO: This should return a reference instead of a pointer!
|
||||||
static RsControl *instance();
|
static RsControl* instance();
|
||||||
static void earlyInitNotificationSystem() { instance(); }
|
static void earlyInitNotificationSystem() { rsControl = instance(); }
|
||||||
|
|
||||||
/* Real Startup Fn */
|
/* Real Startup Fn */
|
||||||
virtual int StartupRetroShare() = 0;
|
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;
|
virtual bool isReady() = 0;
|
||||||
|
|
||||||
/****************************************/
|
virtual void ConfigFinalSave() = 0;
|
||||||
/* Config */
|
|
||||||
|
|
||||||
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:
|
protected:
|
||||||
RsControl() {} // should not be used, hence it's private.
|
RsControl() {} // should not be used, hence it's private.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ public:
|
||||||
* PreLogin
|
* PreLogin
|
||||||
* Call before init retroshare, initialises rsinitconfig's public attributes
|
* 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
|
* 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 systemDataDirectory(bool check = true);
|
||||||
static std::string PGPDirectory();
|
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 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);
|
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.
|
// PGP Support Functions.
|
||||||
static bool ExportIdentity(const std::string& fname,const RsPgpId& pgp_id) ;
|
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 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 void GetUnsupportedKeys(std::map<std::string,std::vector<std::string> > &unsupported_keys);
|
||||||
static bool CopyGnuPGKeyrings() ;
|
static bool CopyGnuPGKeyrings() ;
|
||||||
|
|
||||||
|
@ -233,7 +263,7 @@ struct RsLoginHelper
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @brief Normal way to attempt login
|
* @brief Normal way to attempt login
|
||||||
* @jsonapi{development}
|
* @jsonapi{development,manualwrapper}
|
||||||
* @param[in] account Id of the account to which attempt login
|
* @param[in] account Id of the account to which attempt login
|
||||||
* @param[in] password Password for the given account
|
* @param[in] password Password for the given account
|
||||||
* @return RsInit::OK if login attempt success, error code otherwhise
|
* @return RsInit::OK if login attempt success, error code otherwhise
|
||||||
|
@ -255,14 +285,14 @@ struct RsLoginHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get locations and associated information
|
* @brief Get locations and associated information
|
||||||
* @jsonapi{development}
|
* @jsonapi{development,unauthenticated}
|
||||||
* @param[out] locations storage for the retrived locations
|
* @param[out] locations storage for the retrived locations
|
||||||
*/
|
*/
|
||||||
void getLocations(std::vector<RsLoginHelper::Location>& locations);
|
void getLocations(std::vector<RsLoginHelper::Location>& locations);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new RetroShare location, and log in once is created
|
* @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
|
* @param[inout] location provide input information to generate the location
|
||||||
* and storage to output the data of the generated location
|
* and storage to output the data of the generated location
|
||||||
* @param[in] password to protect and unlock the associated PGP key
|
* @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
|
* @brief Check if RetroShare is already logged in, this usually return true
|
||||||
* after a successfull attemptLogin() and before closeSession()
|
* after a successfull attemptLogin() and before closeSession()
|
||||||
* @jsonapi{development}
|
* @jsonapi{development,unauthenticated}
|
||||||
* @return true if already logged in, false otherwise
|
* @return true if already logged in, false otherwise
|
||||||
*/
|
*/
|
||||||
bool isLoggedIn();
|
bool isLoggedIn();
|
||||||
|
|
|
@ -36,7 +36,7 @@ class RsServiceControl;
|
||||||
* Pointer to global instance of RsServiceControl service implementation
|
* Pointer to global instance of RsServiceControl service implementation
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
*/
|
*/
|
||||||
extern RsServiceControl *rsServiceControl;
|
extern RsServiceControl* rsServiceControl;
|
||||||
|
|
||||||
struct RsServiceInfo : RsSerializable
|
struct RsServiceInfo : RsSerializable
|
||||||
{
|
{
|
||||||
|
@ -131,9 +131,9 @@ public:
|
||||||
virtual ~RsServiceControl(){}
|
virtual ~RsServiceControl(){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getOwnServices return a map off all services.
|
* @brief get a map off all services.
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
* @param[out] info
|
* @param[out] info storage for service information
|
||||||
* @return always true
|
* @return always true
|
||||||
*/
|
*/
|
||||||
virtual bool getOwnServices(RsPeerServiceInfo &info) = 0;
|
virtual bool getOwnServices(RsPeerServiceInfo &info) = 0;
|
||||||
|
@ -197,7 +197,8 @@ public:
|
||||||
* @param[in] serviceId service to look up.
|
* @param[in] serviceId service to look up.
|
||||||
* @param[out] peerSet set of peers using this service.
|
* @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
|
#endif
|
||||||
|
|
|
@ -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_GXS_TYPE_REPUTATION = 0x0219;
|
||||||
const uint16_t RS_SERVICE_TYPE_GXS_RECOGN = 0x0220;
|
const uint16_t RS_SERVICE_TYPE_GXS_RECOGN = 0x0220;
|
||||||
const uint16_t RS_SERVICE_TYPE_GXS_TRANS = 0x0230;
|
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_FORUMS_CONFIG = 0x0315;
|
||||||
const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG = 0x0317;
|
const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG = 0x0317;
|
||||||
|
|
|
@ -33,7 +33,10 @@
|
||||||
#include "retroshare/rsinit.h"
|
#include "retroshare/rsinit.h"
|
||||||
#include "plugins/pluginmanager.h"
|
#include "plugins/pluginmanager.h"
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
//const int p3facemsgzone = 11453;
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
# include "jsonapi/jsonapi.h"
|
||||||
|
#endif // ifdef RS_JSONAPI
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -92,6 +95,10 @@ void RsServer::rsGlobalShutDown()
|
||||||
|
|
||||||
mNetMgr->shutdown(); /* Handles UPnP */
|
mNetMgr->shutdown(); /* Handles UPnP */
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
if(jsonApiServer) jsonApiServer->shutdown();
|
||||||
|
#endif
|
||||||
|
|
||||||
rsAutoProxyMonitor::instance()->stopAllRSShutdown();
|
rsAutoProxyMonitor::instance()->stopAllRSShutdown();
|
||||||
|
|
||||||
fullstop() ;
|
fullstop() ;
|
||||||
|
@ -117,4 +124,6 @@ void RsServer::rsGlobalShutDown()
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
AuthGPG::exit();
|
AuthGPG::exit();
|
||||||
|
|
||||||
|
mShutdownCallback(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,9 @@ int rsserverzone = 101;
|
||||||
#include <sys/timeb.h>
|
#include <sys/timeb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*extern*/ RsControl* rsControl = nullptr;
|
||||||
|
|
||||||
static double getCurrentTS()
|
static double getCurrentTS()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -80,7 +83,8 @@ const double RsServer::kickLimit = 0.15;
|
||||||
|
|
||||||
|
|
||||||
RsServer::RsServer() :
|
RsServer::RsServer() :
|
||||||
coreMutex("RsServer"), coreReady(false)
|
coreMutex("RsServer"), mShutdownCallback([](int){}),
|
||||||
|
coreReady(false)
|
||||||
{
|
{
|
||||||
// This is needed asap.
|
// This is needed asap.
|
||||||
//
|
//
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef MRK_P3RS_INTERFACE_H
|
#pragma once
|
||||||
#define MRK_P3RS_INTERFACE_H
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
//#include "server/filedexserver.h"
|
//#include "server/filedexserver.h"
|
||||||
#include "ft/ftserver.h"
|
#include "ft/ftserver.h"
|
||||||
|
@ -74,19 +75,19 @@ class RsPluginManager;
|
||||||
|
|
||||||
class RsServer: public RsControl, public RsTickingThread
|
class RsServer: public RsControl, public RsTickingThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/****************************************/
|
RsServer();
|
||||||
/* p3face-startup.cc: init... */
|
virtual ~RsServer();
|
||||||
virtual int StartupRetroShare();
|
|
||||||
|
|
||||||
/****************************************/
|
virtual int StartupRetroShare();
|
||||||
/* p3face.cc: main loop / util fns / locking. */
|
|
||||||
|
|
||||||
/// @see RsControl::isReady()
|
/// @see RsControl::isReady()
|
||||||
virtual bool isReady() { return coreReady; }
|
virtual bool isReady() { return coreReady; }
|
||||||
|
|
||||||
RsServer() ;
|
/// @see RsControl::setShutdownCallback
|
||||||
virtual ~RsServer();
|
void setShutdownCallback(const std::function<void(int)>& callback)
|
||||||
|
{ mShutdownCallback = callback; }
|
||||||
|
|
||||||
|
|
||||||
/* Thread Fn: Run the Core */
|
/* Thread Fn: Run the Core */
|
||||||
virtual void data_tick();
|
virtual void data_tick();
|
||||||
|
@ -202,6 +203,9 @@ class RsServer: public RsControl, public RsTickingThread
|
||||||
static const double maxTimeDelta;
|
static const double maxTimeDelta;
|
||||||
static const double kickLimit;
|
static const double kickLimit;
|
||||||
|
|
||||||
|
/// @see RsControl::setShutdownCallback
|
||||||
|
std::function<void(int)> mShutdownCallback;
|
||||||
|
|
||||||
/** Keep track of the core being fully ready, true only after
|
/** Keep track of the core being fully ready, true only after
|
||||||
* StartupRetroShare() finish and before rsGlobalShutDown() begin
|
* StartupRetroShare() finish and before rsGlobalShutDown() begin
|
||||||
*/
|
*/
|
||||||
|
@ -213,5 +217,3 @@ class RsServer: public RsControl, public RsTickingThread
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::string make_path_unix(std::string winpath);
|
std::string make_path_unix(std::string winpath);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -930,6 +930,14 @@ bool RsAccountsDetail::importIdentityFromString(const std::string &data, RsPgpId
|
||||||
return AuthGPG::getAuthGPG()->importProfileFromString(data, imported_pgp_id, import_error);
|
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()
|
bool RsAccountsDetail::copyGnuPGKeyrings()
|
||||||
{
|
{
|
||||||
std::string pgp_dir = PathPGPDirectory() ;
|
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);
|
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)
|
void RsAccounts::GetUnsupportedKeys(std::map<std::string,std::vector<std::string> > &unsupported_keys)
|
||||||
{
|
{
|
||||||
return rsAccountsDetails->getUnsupportedKeys(unsupported_keys);
|
return rsAccountsDetails->getUnsupportedKeys(unsupported_keys);
|
||||||
|
|
|
@ -99,6 +99,9 @@ class RsAccountsDetail
|
||||||
// PGP Support Functions.
|
// PGP Support Functions.
|
||||||
bool exportIdentity(const std::string& fname,const RsPgpId& pgp_id) ;
|
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 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) ;
|
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);
|
void getUnsupportedKeys(std::map<std::string,std::vector<std::string> > &unsupported_keys);
|
||||||
bool copyGnuPGKeyrings() ;
|
bool copyGnuPGKeyrings() ;
|
||||||
|
|
|
@ -94,6 +94,10 @@ RsDht *rsDht = NULL ;
|
||||||
# include "gxstrans/p3gxstrans.h"
|
# include "gxstrans/p3gxstrans.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
# include "jsonapi/jsonapi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// #define GPG_DEBUG
|
// #define GPG_DEBUG
|
||||||
// #define AUTHSSL_DEBUG
|
// #define AUTHSSL_DEBUG
|
||||||
// #define FIM_DEBUG
|
// #define FIM_DEBUG
|
||||||
|
@ -105,15 +109,15 @@ RsLoginHelper* rsLoginHelper = nullptr;
|
||||||
|
|
||||||
RsAccounts* rsAccounts = 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
|
#ifdef WINDOWS_SYS
|
||||||
bool portable;
|
bool portable;
|
||||||
bool isWindowsXP;
|
bool isWindowsXP;
|
||||||
#endif
|
#endif
|
||||||
rs_lock_handle_t lockHandle;
|
rs_lock_handle_t lockHandle;
|
||||||
|
|
||||||
|
@ -146,31 +150,25 @@ class RsInitConfig
|
||||||
int debugLevel;
|
int debugLevel;
|
||||||
std::string logfname;
|
std::string logfname;
|
||||||
|
|
||||||
bool load_trustedpeer;
|
|
||||||
std::string load_trustedpeer_file;
|
|
||||||
|
|
||||||
bool udpListenerOnly;
|
bool udpListenerOnly;
|
||||||
std::string opModeStr;
|
std::string opModeStr;
|
||||||
|
|
||||||
|
uint16_t jsonApiPort;
|
||||||
|
std::string jsonApiBindAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
static RsInitConfig *rsInitConfig = NULL;
|
static RsInitConfig* rsInitConfig = nullptr;
|
||||||
|
|
||||||
//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 const std::string configLogFileName = "retro.log";
|
static const std::string configLogFileName = "retro.log";
|
||||||
static const int SSLPWD_LEN = 64;
|
static const int SSLPWD_LEN = 64;
|
||||||
|
|
||||||
void RsInit::InitRsConfig()
|
void RsInit::InitRsConfig()
|
||||||
{
|
{
|
||||||
rsInitConfig = new RsInitConfig ;
|
rsInitConfig = new RsInitConfig;
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO almost all of this should be moved to RsInitConfig::RsInitConfig
|
||||||
|
* initializers */
|
||||||
|
|
||||||
/* Directories */
|
/* Directories */
|
||||||
#ifdef WINDOWS_SYS
|
#ifdef WINDOWS_SYS
|
||||||
|
@ -181,14 +179,13 @@ void RsInit::InitRsConfig()
|
||||||
rsInitConfig->hiddenNodeSet = false;
|
rsInitConfig->hiddenNodeSet = false;
|
||||||
|
|
||||||
|
|
||||||
|
// This doesn't seems a configuration...
|
||||||
#ifndef WINDOWS_SYS
|
#ifndef WINDOWS_SYS
|
||||||
rsInitConfig->lockHandle = -1;
|
rsInitConfig->lockHandle = -1;
|
||||||
#else
|
#else
|
||||||
rsInitConfig->lockHandle = NULL;
|
rsInitConfig->lockHandle = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
rsInitConfig->load_trustedpeer = false;
|
|
||||||
rsInitConfig->port = 0 ;
|
rsInitConfig->port = 0 ;
|
||||||
rsInitConfig->forceLocalAddr = false;
|
rsInitConfig->forceLocalAddr = false;
|
||||||
rsInitConfig->haveLogFile = false;
|
rsInitConfig->haveLogFile = false;
|
||||||
|
@ -204,9 +201,6 @@ void RsInit::InitRsConfig()
|
||||||
rsInitConfig->udpListenerOnly = false;
|
rsInitConfig->udpListenerOnly = false;
|
||||||
rsInitConfig->opModeStr = std::string("");
|
rsInitConfig->opModeStr = std::string("");
|
||||||
|
|
||||||
/* setup the homePath (default save location) */
|
|
||||||
// rsInitConfig->homePath = getHomePath();
|
|
||||||
|
|
||||||
#ifdef WINDOWS_SYS
|
#ifdef WINDOWS_SYS
|
||||||
// test for portable version
|
// test for portable version
|
||||||
if (GetFileAttributes(L"portable") != (DWORD) -1) {
|
if (GetFileAttributes(L"portable") != (DWORD) -1) {
|
||||||
|
@ -243,31 +237,7 @@ void RsInit::InitRsConfig()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Setup the Debugging */
|
setOutputLevel(RsLog::Warning);
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********
|
/********
|
||||||
|
@ -294,69 +264,60 @@ bool doPortRestrictions = false;
|
||||||
int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
|
int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_RSINIT
|
#ifdef DEBUG_RSINIT
|
||||||
for(int i=0; i<argc; i++)
|
for(int i=0; i<argc; i++) printf("%d: %s\n", i, argv[i]);
|
||||||
printf("%d: %s\n", i, argv[i]);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* for static PThreads under windows... we need to init the library... */
|
|
||||||
#ifdef PTW32_STATIC_LIB
|
#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
|
#endif
|
||||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
|
||||||
|
|
||||||
std::string prefUserString = "";
|
std::string prefUserString = "";
|
||||||
std::string opt_base_dir;
|
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 = "" ;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#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,
|
* remove the commandline arguments - if we detect we are launched from Finder,
|
||||||
* and we have the unparsable "-psn_0_12332" option.
|
* and we have the unparsable "-psn_0_12332" option.
|
||||||
* this is okay, as you cannot pass commandline arguments via Finder anyway
|
* this is okay, as you cannot pass commandline arguments via Finder anyway
|
||||||
*/
|
*/
|
||||||
if ((argc >= 2) && (0 == strncmp(argv[1], "-psn", 4)))
|
if ((argc >= 2) && (0 == strncmp(argv[1], "-psn", 4))) argc = 1;
|
||||||
{
|
|
||||||
argc = 1;
|
|
||||||
}
|
|
||||||
#endif
|
#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
|
#ifdef LOCALNET_TESTING
|
||||||
>> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false)
|
as >> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false);
|
||||||
#endif
|
#endif // ifdef LOCALNET_TESTING
|
||||||
>> help('h',"help","Display this Help") ;
|
|
||||||
|
|
||||||
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->autoLogin) rsInitConfig->startMinimised = true ;
|
||||||
if(rsInitConfig->outStderr) rsInitConfig->haveLogFile = false ;
|
if(rsInitConfig->outStderr) rsInitConfig->haveLogFile = false ;
|
||||||
|
@ -477,6 +438,16 @@ int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
return RS_INIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1277,6 +1248,15 @@ int RsServer::StartupRetroShare()
|
||||||
//
|
//
|
||||||
mPluginsManager->loadPlugins(programatically_inserted_plugins) ;
|
mPluginsManager->loadPlugins(programatically_inserted_plugins) ;
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
if(jsonApiServer) // JsonApiServer may be disabled at runtime
|
||||||
|
{
|
||||||
|
mConfigMgr->addConfiguration("jsonApi.cfg", jsonApiServer);
|
||||||
|
RsFileHash dummyHash;
|
||||||
|
jsonApiServer->loadConfiguration(dummyHash);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**** Reputation system ****/
|
/**** Reputation system ****/
|
||||||
|
|
||||||
p3GxsReputation *mReputations = new p3GxsReputation(mLinkMgr) ;
|
p3GxsReputation *mReputations = new p3GxsReputation(mLinkMgr) ;
|
||||||
|
@ -1940,6 +1920,7 @@ int RsServer::StartupRetroShare()
|
||||||
RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin(
|
RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin(
|
||||||
const RsPeerId& account, const std::string& password)
|
const RsPeerId& account, const std::string& password)
|
||||||
{
|
{
|
||||||
|
if(isLoggedIn()) return RsInit::ERR_ALREADY_RUNNING;
|
||||||
if(!rsNotify->cachePgpPassphrase(password)) return RsInit::ERR_UNKOWN;
|
if(!rsNotify->cachePgpPassphrase(password)) return RsInit::ERR_UNKOWN;
|
||||||
if(!rsNotify->setDisableAskPassword(true)) return RsInit::ERR_UNKOWN;
|
if(!rsNotify->setDisableAskPassword(true)) return RsInit::ERR_UNKOWN;
|
||||||
if(!RsAccounts::SelectAccount(account)) return RsInit::ERR_UNKOWN;
|
if(!RsAccounts::SelectAccount(account)) return RsInit::ERR_UNKOWN;
|
||||||
|
@ -1973,6 +1954,8 @@ bool RsLoginHelper::createLocation(
|
||||||
RsLoginHelper::Location& l, const std::string& password,
|
RsLoginHelper::Location& l, const std::string& password,
|
||||||
bool makeHidden, bool makeAutoTor, std::string& errorMessage )
|
bool makeHidden, bool makeAutoTor, std::string& errorMessage )
|
||||||
{
|
{
|
||||||
|
if(isLoggedIn()) return (errorMessage="Already Running", false);
|
||||||
|
|
||||||
if(l.mLocationName.empty())
|
if(l.mLocationName.empty())
|
||||||
{
|
{
|
||||||
errorMessage = "Location name is needed";
|
errorMessage = "Location name is needed";
|
||||||
|
|
|
@ -90,6 +90,7 @@ int main(int argc, char *argv[])
|
||||||
RsInit::InitRsConfig();
|
RsInit::InitRsConfig();
|
||||||
RsInit::InitRetroShare(argc, argv, true);
|
RsInit::InitRetroShare(argc, argv, true);
|
||||||
RsControl::earlyInitNotificationSystem();
|
RsControl::earlyInitNotificationSystem();
|
||||||
|
rsControl->setShutdownCallback(QCoreApplication::exit);
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
&app, &QCoreApplication::aboutToQuit,
|
&app, &QCoreApplication::aboutToQuit,
|
||||||
[](){
|
[](){
|
||||||
|
@ -97,71 +98,5 @@ int main(int argc, char *argv[])
|
||||||
RsControl::instance()->rsGlobalShutDown(); } );
|
RsControl::instance()->rsGlobalShutDown(); } );
|
||||||
#endif // ifdef LIBRESAPI_LOCAL_SERVER
|
#endif // ifdef LIBRESAPI_LOCAL_SERVER
|
||||||
|
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
uint16_t jsonApiPort = 9092;
|
|
||||||
std::string jsonApiBindAddress = "127.0.0.1";
|
|
||||||
|
|
||||||
{
|
|
||||||
QCommandLineOption jsonApiPortOpt(
|
|
||||||
"jsonApiPort", "JSON API listening port.", "port", "9092");
|
|
||||||
QCommandLineOption jsonApiBindAddressOpt(
|
|
||||||
"jsonApiBindAddress", "JSON API Bind Address.",
|
|
||||||
"IP Address", "127.0.0.1");
|
|
||||||
|
|
||||||
QCommandLineParser cmdParser;
|
|
||||||
cmdParser.addHelpOption();
|
|
||||||
cmdParser.addOption(jsonApiPortOpt);
|
|
||||||
cmdParser.addOption(jsonApiBindAddressOpt);
|
|
||||||
|
|
||||||
cmdParser.parse(app.arguments());
|
|
||||||
|
|
||||||
if(cmdParser.isSet(jsonApiPortOpt))
|
|
||||||
{
|
|
||||||
QString jsonApiPortStr = cmdParser.value(jsonApiPortOpt);
|
|
||||||
bool portOk;
|
|
||||||
jsonApiPort = jsonApiPortStr.toUShort(&portOk);
|
|
||||||
if(!portOk)
|
|
||||||
{
|
|
||||||
std::cerr << "ERROR: jsonApiPort option value must be a valid "
|
|
||||||
<< "TCP port!" << std::endl;
|
|
||||||
cmdParser.showHelp();
|
|
||||||
QCoreApplication::exit(EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cmdParser.isSet(jsonApiBindAddressOpt))
|
|
||||||
{
|
|
||||||
sockaddr_storage tmp;
|
|
||||||
jsonApiBindAddress =
|
|
||||||
cmdParser.value(jsonApiBindAddressOpt).toStdString();
|
|
||||||
if(!sockaddr_storage_inet_pton(tmp, jsonApiBindAddress))
|
|
||||||
{
|
|
||||||
std::cerr << "ERROR: jsonApiBindAddress option value must "
|
|
||||||
<< "be a valid IP address!" << std::endl;
|
|
||||||
cmdParser.showHelp();
|
|
||||||
QCoreApplication::exit(EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonApiServer jas( jsonApiPort, jsonApiBindAddress,
|
|
||||||
[](int ec) { QCoreApplication::exit(ec); } );
|
|
||||||
jas.start();
|
|
||||||
|
|
||||||
{
|
|
||||||
sockaddr_storage tmp;
|
|
||||||
sockaddr_storage_inet_pton(tmp, jsonApiBindAddress);
|
|
||||||
sockaddr_storage_setport(tmp, jsonApiPort);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // ifdef RS_JSONAPI
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
173
retroshare-gui/src/gui/settings/JsonApiPage.cc
Normal file
173
retroshare-gui/src/gui/settings/JsonApiPage.cc
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#include "JsonApiPage.h"
|
||||||
|
|
||||||
|
#include "rsharesettings.h"
|
||||||
|
#include "jsonapi/jsonapi.h"
|
||||||
|
#include "util/misc.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QStringListModel>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
|
||||||
|
|
||||||
|
JsonApiPage::JsonApiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/)
|
||||||
|
{
|
||||||
|
ui.setupUi(this);
|
||||||
|
connect( ui.addTokenPushButton, &QPushButton::clicked,
|
||||||
|
this, &JsonApiPage::addTokenClicked);
|
||||||
|
connect( ui.removeTokenPushButton, &QPushButton::clicked,
|
||||||
|
this, &JsonApiPage::removeTokenClicked );
|
||||||
|
connect( ui.tokensListView, &QListView::clicked,
|
||||||
|
this, &JsonApiPage::tokenClicked );
|
||||||
|
connect( ui.applyConfigPushButton, &QPushButton::clicked,
|
||||||
|
this, &JsonApiPage::onApplyClicked );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonApiPage::updateParams(QString &errmsg)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
bool enabled = ui.enableCheckBox->isChecked();
|
||||||
|
if( enabled != Settings->getJsonApiEnabled())
|
||||||
|
{
|
||||||
|
Settings->setJsonApiEnabled(enabled);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t port = ui.portSpinBox->value();
|
||||||
|
if(port != Settings->getJsonApiPort())
|
||||||
|
{
|
||||||
|
Settings->setJsonApiPort(port);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString listenAddress = ui.listenAddressLineEdit->text();
|
||||||
|
if(listenAddress != Settings->getJsonApiListenAddress())
|
||||||
|
{
|
||||||
|
Settings->setJsonApiListenAddress(listenAddress);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changed)
|
||||||
|
{
|
||||||
|
checkShutdownJsonApi();
|
||||||
|
ok = checkStartJsonApi();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ok) errmsg = "Could not start JSON API Server!";
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonApiPage::load()
|
||||||
|
{
|
||||||
|
whileBlocking(ui.enableCheckBox)->setChecked(Settings->getJsonApiEnabled());
|
||||||
|
whileBlocking(ui.portSpinBox)->setValue(Settings->getJsonApiPort());
|
||||||
|
whileBlocking(ui.listenAddressLineEdit)->setText(Settings->getJsonApiListenAddress());
|
||||||
|
whileBlocking(ui.tokensListView)->setModel(new QStringListModel(Settings->getJsonApiAuthTokens()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString JsonApiPage::helpText() const { return ""; }
|
||||||
|
|
||||||
|
/*static*/ bool JsonApiPage::checkStartJsonApi()
|
||||||
|
{
|
||||||
|
checkShutdownJsonApi();
|
||||||
|
|
||||||
|
if(Settings->getJsonApiEnabled())
|
||||||
|
{
|
||||||
|
jsonApiServer = new JsonApiServer(
|
||||||
|
Settings->getJsonApiPort(),
|
||||||
|
Settings->getJsonApiListenAddress().toStdString() );
|
||||||
|
jsonApiServer->start("jsonApiServer");
|
||||||
|
|
||||||
|
for(const QString& token : Settings->getJsonApiAuthTokens())
|
||||||
|
jsonApiServer->authorizeToken(token.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ void JsonApiPage::checkShutdownJsonApi()
|
||||||
|
{
|
||||||
|
if(jsonApiServer)
|
||||||
|
{
|
||||||
|
/* It is important to make a copy of +jsonApiServer+ pointer so the old
|
||||||
|
* object can be deleted later, while the original pointer is
|
||||||
|
* reassigned */
|
||||||
|
JsonApiServer* oldJsonApiServer = jsonApiServer;
|
||||||
|
jsonApiServer = nullptr;
|
||||||
|
|
||||||
|
oldJsonApiServer->shutdown();
|
||||||
|
|
||||||
|
QProgressDialog* pd = new QProgressDialog(
|
||||||
|
"Stopping JSON API Server", QString(), 0, 3000);
|
||||||
|
QTimer* prtm = new QTimer;
|
||||||
|
prtm->setInterval(16); // 60 FPS
|
||||||
|
connect( prtm, &QTimer::timeout,
|
||||||
|
pd, [=](){pd->setValue(pd->value()+16);} );
|
||||||
|
pd->show();
|
||||||
|
prtm->start();
|
||||||
|
|
||||||
|
/* Must wait for deletion because stopping of the server is async.
|
||||||
|
* It is important to capture a copy so it "survive" after
|
||||||
|
* safeStopJsonApiServer returns */
|
||||||
|
QTimer::singleShot(3*1000, [=]()
|
||||||
|
{
|
||||||
|
delete oldJsonApiServer;
|
||||||
|
prtm->stop();
|
||||||
|
pd->close();
|
||||||
|
prtm->deleteLater();
|
||||||
|
pd->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonApiPage::onApplyClicked(bool)
|
||||||
|
{
|
||||||
|
QString errmsg;
|
||||||
|
updateParams(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonApiPage::addTokenClicked(bool)
|
||||||
|
{
|
||||||
|
QString token(ui.tokenLineEdit->text());
|
||||||
|
if(jsonApiServer) jsonApiServer->authorizeToken(token.toStdString());
|
||||||
|
QStringList newTk(Settings->getJsonApiAuthTokens());
|
||||||
|
newTk.removeAll(token);
|
||||||
|
newTk.append(token);
|
||||||
|
Settings->setJsonApiAuthTokens(newTk);
|
||||||
|
whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonApiPage::removeTokenClicked(bool)
|
||||||
|
{
|
||||||
|
QString token(ui.tokenLineEdit->text());
|
||||||
|
if(jsonApiServer) jsonApiServer->revokeAuthToken(token.toStdString());
|
||||||
|
QStringList newTk(Settings->getJsonApiAuthTokens());
|
||||||
|
newTk.removeAll(token);
|
||||||
|
Settings->setJsonApiAuthTokens(newTk);
|
||||||
|
whileBlocking(ui.tokensListView)->setModel(
|
||||||
|
new QStringListModel(Settings->getJsonApiAuthTokens()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonApiPage::tokenClicked(const QModelIndex& index)
|
||||||
|
{
|
||||||
|
ui.tokenLineEdit->setText(ui.tokensListView->model()->data(index).toString());
|
||||||
|
}
|
||||||
|
|
58
retroshare-gui/src/gui/settings/JsonApiPage.h
Normal file
58
retroshare-gui/src/gui/settings/JsonApiPage.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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 <retroshare-gui/configpage.h>
|
||||||
|
#include "ui_JsonApiPage.h"
|
||||||
|
|
||||||
|
class JsonApiPage : public ConfigPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
JsonApiPage(QWidget * parent = nullptr, Qt::WindowFlags flags = 0);
|
||||||
|
~JsonApiPage() {}
|
||||||
|
|
||||||
|
/** Loads the settings for this page */
|
||||||
|
virtual void load();
|
||||||
|
|
||||||
|
virtual QPixmap iconPixmap() const
|
||||||
|
{ return QPixmap(":/icons/svg/empty-circle.svg"); }
|
||||||
|
virtual QString pageName() const { return tr("JSON API"); }
|
||||||
|
virtual QString helpText() const;
|
||||||
|
|
||||||
|
/** Call this after start of libretroshare/Retroshare
|
||||||
|
* checks the settings and starts JSON API if required */
|
||||||
|
static bool checkStartJsonApi();
|
||||||
|
|
||||||
|
/** call this before shutdown of libretroshare
|
||||||
|
* it stops the JSON API if its running */
|
||||||
|
static void checkShutdownJsonApi();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onApplyClicked(bool);
|
||||||
|
void addTokenClicked(bool);
|
||||||
|
void removeTokenClicked(bool);
|
||||||
|
void tokenClicked(const QModelIndex& index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::JsonApiPage ui; /// Qt Designer generated object
|
||||||
|
|
||||||
|
bool updateParams(QString &errmsg);
|
||||||
|
};
|
147
retroshare-gui/src/gui/settings/JsonApiPage.ui
Normal file
147
retroshare-gui/src/gui/settings/JsonApiPage.ui
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>JsonApiPage</class>
|
||||||
|
<widget class="QWidget" name="JsonApiPage">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>521</width>
|
||||||
|
<height>393</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="WebuiPageVLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="jsonApiGroupBox">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>274</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>JSON API Server</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="enableCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable RetroShare JSON API Server</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Port:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="portSpinBox">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1024</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>65535</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>9092</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Listen Address:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="listenAddressLineEdit">
|
||||||
|
<property name="text">
|
||||||
|
<string>127.0.0.1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Token:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="tokenLineEdit">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>ApiUser:ApiPassword</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="addTokenPushButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="removeTokenPushButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Authenticated Tokens</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListView" name="tokensListView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="applyConfigPushButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Restart JSON API Server to apply settings</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="mainVSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>17</width>
|
||||||
|
<height>632</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -23,11 +23,6 @@ resource_api::ApiServerLocal* WebuiPage::apiServerLocal = 0;
|
||||||
#endif
|
#endif
|
||||||
resource_api::RsControlModule* WebuiPage::controlModule = 0;
|
resource_api::RsControlModule* WebuiPage::controlModule = 0;
|
||||||
|
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
# include <csignal>
|
|
||||||
|
|
||||||
JsonApiServer* WebuiPage::jsonApiServer = nullptr;
|
|
||||||
#endif // ifdef RS_JSONAPI
|
|
||||||
|
|
||||||
WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/)
|
WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/)
|
||||||
{
|
{
|
||||||
|
@ -113,15 +108,6 @@ QString WebuiPage::helpText() const
|
||||||
apiServerLocal = new resource_api::ApiServerLocal(apiServer, resource_api::ApiServerLocal::serverPath());
|
apiServerLocal = new resource_api::ApiServerLocal(apiServer, resource_api::ApiServerLocal::serverPath());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
// Use same port of libresapi + 2
|
|
||||||
jsonApiServer = new JsonApiServer(
|
|
||||||
Settings->getWebinterfacePort() + 2,
|
|
||||||
Settings->getWebinterfaceAllowAllIps() ? "::" : "127.0.0.1",
|
|
||||||
[](int /*ec*/) { std::raise(SIGTERM); } );
|
|
||||||
jsonApiServer->start("WebuiPage::jsonApiServer");
|
|
||||||
#endif // ifdef RS_JSONAPI
|
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,10 +128,6 @@ QString WebuiPage::helpText() const
|
||||||
delete controlModule;
|
delete controlModule;
|
||||||
controlModule = 0;
|
controlModule = 0;
|
||||||
}
|
}
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
delete jsonApiServer;
|
|
||||||
jsonApiServer = nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void WebuiPage::showWebui()
|
/*static*/ void WebuiPage::showWebui()
|
||||||
|
|
|
@ -3,10 +3,6 @@
|
||||||
#include <retroshare-gui/configpage.h>
|
#include <retroshare-gui/configpage.h>
|
||||||
#include "ui_WebuiPage.h"
|
#include "ui_WebuiPage.h"
|
||||||
|
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
# include "jsonapi/jsonapi.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace resource_api{
|
namespace resource_api{
|
||||||
class ApiServer;
|
class ApiServer;
|
||||||
class ApiServerMHD;
|
class ApiServerMHD;
|
||||||
|
@ -59,7 +55,4 @@ private:
|
||||||
static resource_api::ApiServerLocal* apiServerLocal;
|
static resource_api::ApiServerLocal* apiServerLocal;
|
||||||
#endif
|
#endif
|
||||||
static resource_api::RsControlModule* controlModule;
|
static resource_api::RsControlModule* controlModule;
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
static JsonApiServer* jsonApiServer;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,10 @@
|
||||||
# include "WebuiPage.h"
|
# include "WebuiPage.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
# include "JsonApiPage.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IMAGE_GENERAL ":/images/kcmsystem24.png"
|
#define IMAGE_GENERAL ":/images/kcmsystem24.png"
|
||||||
|
|
||||||
#define ITEM_SPACING 2
|
#define ITEM_SPACING 2
|
||||||
|
@ -165,8 +169,12 @@ SettingsPage::initStackedWidget()
|
||||||
#ifdef ENABLE_WEBUI
|
#ifdef ENABLE_WEBUI
|
||||||
addPage(new WebuiPage() );
|
addPage(new WebuiPage() );
|
||||||
#endif // ENABLE_WEBUI
|
#endif // ENABLE_WEBUI
|
||||||
// add widgets from plugins
|
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
addPage(new JsonApiPage());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// add widgets from plugins
|
||||||
for(int i=0;i<rsPlugins->nbPlugins();++i)
|
for(int i=0;i<rsPlugins->nbPlugins();++i)
|
||||||
{
|
{
|
||||||
RsPlugin *pl = rsPlugins->plugin(i) ;
|
RsPlugin *pl = rsPlugins->plugin(i) ;
|
||||||
|
|
|
@ -1171,3 +1171,45 @@ void RshareSettings::setPageAlreadyDisplayed(const QString& page_name,bool b)
|
||||||
{
|
{
|
||||||
return setValueToGroup("PageAlreadyDisplayed",page_name,b);
|
return setValueToGroup("PageAlreadyDisplayed",page_name,b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
bool RshareSettings::getJsonApiEnabled()
|
||||||
|
{
|
||||||
|
return valueFromGroup("JsonApi", "enabled", false).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RshareSettings::setJsonApiEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
setValueToGroup("JsonApi", "enabled", enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t RshareSettings::getJsonApiPort()
|
||||||
|
{
|
||||||
|
return valueFromGroup("JsonApi", "port", 9092).toUInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RshareSettings::setJsonApiPort(uint16_t port)
|
||||||
|
{
|
||||||
|
setValueToGroup("JsonApi", "port", port);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RshareSettings::getJsonApiListenAddress()
|
||||||
|
{
|
||||||
|
return valueFromGroup("JsonApi", "listenAddress", "127.0.0.1").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RshareSettings::setJsonApiListenAddress(const QString& listenAddress)
|
||||||
|
{
|
||||||
|
setValueToGroup("JsonApi", "listenAddress", listenAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList RshareSettings::getJsonApiAuthTokens()
|
||||||
|
{
|
||||||
|
return valueFromGroup("JsonApi", "authTokens", QStringList()).toStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RshareSettings::setJsonApiAuthTokens(const QStringList& authTokens)
|
||||||
|
{
|
||||||
|
setValueToGroup("JsonApi", "authTokens", authTokens);
|
||||||
|
}
|
||||||
|
#endif // RS_JSONAPI
|
||||||
|
|
|
@ -341,6 +341,20 @@ public:
|
||||||
bool getPageAlreadyDisplayed(const QString& page_code) ;
|
bool getPageAlreadyDisplayed(const QString& page_code) ;
|
||||||
void setPageAlreadyDisplayed(const QString& page_code,bool b) ;
|
void setPageAlreadyDisplayed(const QString& page_code,bool b) ;
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
bool getJsonApiEnabled();
|
||||||
|
void setJsonApiEnabled(bool enabled);
|
||||||
|
|
||||||
|
uint16_t getJsonApiPort();
|
||||||
|
void setJsonApiPort(uint16_t port);
|
||||||
|
|
||||||
|
QString getJsonApiListenAddress();
|
||||||
|
void setJsonApiListenAddress(const QString& listenAddress);
|
||||||
|
|
||||||
|
QStringList getJsonApiAuthTokens();
|
||||||
|
void setJsonApiAuthTokens(const QStringList& authTokens);
|
||||||
|
#endif // ifdef RS_JSONAPI
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Default constructor. */
|
/** Default constructor. */
|
||||||
RshareSettings();
|
RshareSettings();
|
||||||
|
|
|
@ -51,6 +51,10 @@
|
||||||
# include "gui/settings/WebuiPage.h"
|
# include "gui/settings/WebuiPage.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
# include "gui/settings/JsonApiPage.h"
|
||||||
|
#endif // RS_JSONAPI
|
||||||
|
|
||||||
#include "TorControl/TorManager.h"
|
#include "TorControl/TorManager.h"
|
||||||
#include "TorControl/TorControlWindow.h"
|
#include "TorControl/TorControlWindow.h"
|
||||||
|
|
||||||
|
@ -536,6 +540,10 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO);
|
||||||
WebuiPage::checkStartWebui();
|
WebuiPage::checkStartWebui();
|
||||||
#endif // ENABLE_WEBUI
|
#endif // ENABLE_WEBUI
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
JsonApiPage::checkStartJsonApi();
|
||||||
|
#endif // RS_JSONAPI
|
||||||
|
|
||||||
// This is done using a timer, because the passphrase request from notify is asynchrouneous and therefore clearing the
|
// This is done using a timer, because the passphrase request from notify is asynchrouneous and therefore clearing the
|
||||||
// passphrase here makes it request for a passphrase when creating the default chat identity.
|
// passphrase here makes it request for a passphrase when creating the default chat identity.
|
||||||
|
|
||||||
|
@ -545,6 +553,10 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO);
|
||||||
int ti = rshare.exec();
|
int ti = rshare.exec();
|
||||||
delete w ;
|
delete w ;
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
JsonApiPage::checkShutdownJsonApi();
|
||||||
|
#endif // RS_JSONAPI
|
||||||
|
|
||||||
#ifdef ENABLE_WEBUI
|
#ifdef ENABLE_WEBUI
|
||||||
WebuiPage::checkShutdownWebui();
|
WebuiPage::checkShutdownWebui();
|
||||||
#endif // ENABLE_WEBUI
|
#endif // ENABLE_WEBUI
|
||||||
|
|
|
@ -17,6 +17,12 @@ libresapihttpserver {
|
||||||
FORMS *= gui/settings/WebuiPage.ui
|
FORMS *= gui/settings/WebuiPage.ui
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rs_jsonapi {
|
||||||
|
HEADERS *= gui/settings/JsonApiPage.h
|
||||||
|
SOURCES *= gui/settings/JsonApiPage.cc
|
||||||
|
FORMS *= gui/settings/JsonApiPage.ui
|
||||||
|
}
|
||||||
|
|
||||||
!include("../../libretroshare/src/use_libretroshare.pri"):error("Including")
|
!include("../../libretroshare/src/use_libretroshare.pri"):error("Including")
|
||||||
|
|
||||||
FORMS += TorControl/TorControlWindow.ui
|
FORMS += TorControl/TorControlWindow.ui
|
||||||
|
|
|
@ -24,15 +24,15 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <retroshare/rsiface.h> /* definition of iface */
|
#include "retroshare/rsiface.h"
|
||||||
#include <retroshare/rsinit.h> /* definition of iface */
|
#include "retroshare/rsinit.h"
|
||||||
|
|
||||||
#include "notifytxt.h"
|
#include "notifytxt.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "util/argstream.h"
|
#include "util/argstream.h"
|
||||||
#include "util/rstime.h"
|
#include "util/rstime.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifdef WINDOWS_SYS
|
#ifdef WINDOWS_SYS
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,18 +43,12 @@
|
||||||
|
|
||||||
#ifdef ENABLE_WEBUI
|
#ifdef ENABLE_WEBUI
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <csignal>
|
||||||
#include "api/ApiServerMHD.h"
|
#include "api/ApiServerMHD.h"
|
||||||
#include "api/RsControlModule.h"
|
#include "api/RsControlModule.h"
|
||||||
#include "TerminalApiClient.h"
|
#include "TerminalApiClient.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
# include <csignal>
|
|
||||||
# include "jsonapi/jsonapi.h"
|
|
||||||
# include "util/rsnet.h"
|
|
||||||
# include "util/rsurl.h"
|
|
||||||
#endif // RS_JSONAPI
|
|
||||||
|
|
||||||
/* Basic instructions for running libretroshare as background thread.
|
/* Basic instructions for running libretroshare as background thread.
|
||||||
* ******************************************************************* *
|
* ******************************************************************* *
|
||||||
* This allows your program to communicate with authenticated peers.
|
* This allows your program to communicate with authenticated peers.
|
||||||
|
@ -67,45 +61,6 @@
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
JsonApiServer* jsonApiServer = nullptr;
|
|
||||||
uint16_t jsonApiPort = 0;
|
|
||||||
std::string jsonApiBindAddress = "127.0.0.1";
|
|
||||||
|
|
||||||
{
|
|
||||||
argstream jsonApiArgs(argc, argv);
|
|
||||||
jsonApiArgs >> parameter(
|
|
||||||
"jsonApiPort", jsonApiPort, "jsonApiPort",
|
|
||||||
"Enable JSON API on the specified port", false );
|
|
||||||
jsonApiArgs >> parameter(
|
|
||||||
"jsonApiBindAddress", jsonApiBindAddress,
|
|
||||||
"jsonApiBindAddress", "JSON API Bind Address.", false);
|
|
||||||
jsonApiArgs >> help('h', "help", "Display this Help");
|
|
||||||
|
|
||||||
if (jsonApiArgs.helpRequested())
|
|
||||||
std::cerr << jsonApiArgs.usage() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(jsonApiPort)
|
|
||||||
{
|
|
||||||
jsonApiServer = new JsonApiServer(
|
|
||||||
jsonApiPort, jsonApiBindAddress,
|
|
||||||
[](int /*ec*/) { std::raise(SIGTERM); } );
|
|
||||||
|
|
||||||
jsonApiServer->start("JSON API Server");
|
|
||||||
|
|
||||||
sockaddr_storage tmp;
|
|
||||||
sockaddr_storage_inet_pton(tmp, jsonApiBindAddress);
|
|
||||||
sockaddr_storage_setport(tmp, jsonApiPort);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif // RS_JSONAPI
|
|
||||||
|
|
||||||
#ifdef ENABLE_WEBUI
|
#ifdef ENABLE_WEBUI
|
||||||
|
|
||||||
std::string docroot = resource_api::getDefaultDocroot();
|
std::string docroot = resource_api::getDefaultDocroot();
|
||||||
|
@ -146,11 +101,14 @@ int main(int argc, char **argv)
|
||||||
httpd->start();
|
httpd->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
resource_api::TerminalApiClient tac(&api);
|
RsControl::earlyInitNotificationSystem();
|
||||||
|
rsControl->setShutdownCallback([](int){std::raise(SIGTERM);});
|
||||||
|
|
||||||
|
resource_api::TerminalApiClient tac(&api);
|
||||||
tac.start();
|
tac.start();
|
||||||
bool already = false ;
|
bool already = false ;
|
||||||
|
|
||||||
while(ctrl_mod.processShouldExit() == false)
|
while(!ctrl_mod.processShouldExit())
|
||||||
{
|
{
|
||||||
rstime::rs_usleep(1000*1000);
|
rstime::rs_usleep(1000*1000);
|
||||||
|
|
||||||
|
@ -170,28 +128,6 @@ int main(int argc, char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Retroshare startup is configured using an RsInit object.
|
|
||||||
* This is an opaque class, which the user cannot directly tweak
|
|
||||||
* If you want to peek at whats happening underneath look in
|
|
||||||
* libretroshare/src/rsserver/p3face-startup.cc
|
|
||||||
*
|
|
||||||
* You create it with InitRsConfig(), and delete with CleanupRsConfig()
|
|
||||||
* InitRetroshare(argv, argc, config) parses the command line options,
|
|
||||||
* and initialises the config paths.
|
|
||||||
*
|
|
||||||
* *** There are several functions that I should add to modify
|
|
||||||
* **** the config the moment these can only be set via the commandline
|
|
||||||
* - RsConfigDirectory(...) is probably the most useful.
|
|
||||||
* - RsConfigNetAddr(...) for setting port, etc.
|
|
||||||
* - RsConfigOutput(...) for logging and debugging.
|
|
||||||
*
|
|
||||||
* Next you need to worry about loading your certificate, or making
|
|
||||||
* a new one:
|
|
||||||
*
|
|
||||||
* RsGenerateCertificate(...) To create a new key, certificate
|
|
||||||
* LoadPassword(...) set password for existing certificate.
|
|
||||||
**/
|
|
||||||
|
|
||||||
bool strictCheck = true;
|
bool strictCheck = true;
|
||||||
RsInit::InitRsConfig();
|
RsInit::InitRsConfig();
|
||||||
int initResult = RsInit::InitRetroShare(argc, argv, strictCheck);
|
int initResult = RsInit::InitRetroShare(argc, argv, strictCheck);
|
||||||
|
@ -220,10 +156,13 @@ int main(int argc, char **argv)
|
||||||
* if you want to receive notifications of events */
|
* if you want to receive notifications of events */
|
||||||
|
|
||||||
// This is needed to allocate rsNotify, so that it can be used to ask for PGP passphrase
|
// This is needed to allocate rsNotify, so that it can be used to ask for PGP passphrase
|
||||||
//
|
RsControl::earlyInitNotificationSystem();
|
||||||
RsControl::earlyInitNotificationSystem() ;
|
|
||||||
|
|
||||||
NotifyTxt *notify = new NotifyTxt() ;
|
// an atomic might be safer but is probably unneded for this simple usage
|
||||||
|
bool keepRunning = true;
|
||||||
|
rsControl->setShutdownCallback([&](int){keepRunning = false;});
|
||||||
|
|
||||||
|
NotifyTxt *notify = new NotifyTxt();
|
||||||
rsNotify->registerNotifyClient(notify);
|
rsNotify->registerNotifyClient(notify);
|
||||||
|
|
||||||
/* PreferredId => Key + Certificate are loaded into libretroshare */
|
/* PreferredId => Key + Certificate are loaded into libretroshare */
|
||||||
|
@ -244,35 +183,19 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start-up libretroshare server threads */
|
/* Start-up libretroshare server threads */
|
||||||
RsControl::instance() -> StartupRetroShare();
|
RsControl::instance()->StartupRetroShare();
|
||||||
|
|
||||||
#ifdef RS_INTRO_SERVER
|
#ifdef RS_INTRO_SERVER
|
||||||
RsIntroServer rsIS;
|
RsIntroServer rsIS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* pass control to the GUI */
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
//std::cerr << "GUI Tick()" << std::endl;
|
|
||||||
|
|
||||||
|
while(keepRunning)
|
||||||
|
{
|
||||||
#ifdef RS_INTRO_SERVER
|
#ifdef RS_INTRO_SERVER
|
||||||
rsIS.tick();
|
rsIS.tick();
|
||||||
#endif
|
#endif
|
||||||
|
rstime::rs_usleep(10*1000);
|
||||||
int rt = 0;
|
|
||||||
// If we have a MenuTerminal ...
|
|
||||||
// only want to sleep if there is no input. (rt == 0).
|
|
||||||
if (rt == 0)
|
|
||||||
{
|
|
||||||
#ifndef WINDOWS_SYS
|
|
||||||
sleep(1);
|
|
||||||
#else
|
|
||||||
Sleep(1000);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
rstime::rs_usleep(1000);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class FakeServiceControl: public p3ServiceControl
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getPeersConnected(const uint32_t serviceId, std::set<RsPeerId> &peerSet)
|
virtual void getPeersConnected(uint32_t serviceId, std::set<RsPeerId> &peerSet)
|
||||||
{
|
{
|
||||||
(void) serviceId;
|
(void) serviceId;
|
||||||
std::list<RsPeerId> ids ;
|
std::list<RsPeerId> ids ;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue