mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-26 15:28:28 -05:00
Merge pull request #1289 from G10h4ck/jsonapi
Implement automatic JSON API generation
This commit is contained in:
commit
c294971633
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "supportlibs/restbed"]
|
||||
path = supportlibs/restbed
|
||||
url = https://github.com/Corvusoft/restbed.git
|
||||
[submodule "cmark"]
|
||||
path = supportlibs/cmark
|
||||
url = https://github.com/commonmark/cmark.git
|
||||
|
@ -23,6 +23,12 @@ TEMPLATE = subdirs
|
||||
SUBDIRS += openpgpsdk
|
||||
openpgpsdk.file = openpgpsdk/src/openpgpsdk.pro
|
||||
|
||||
rs_jsonapi {
|
||||
SUBDIRS += jsonapi-generator
|
||||
jsonapi-generator.file = jsonapi-generator/src/jsonapi-generator.pro
|
||||
libretroshare.depends += jsonapi-generator
|
||||
}
|
||||
|
||||
SUBDIRS += libbitdht
|
||||
libbitdht.file = libbitdht/src/libbitdht.pro
|
||||
libretroshare.depends = openpgpsdk libbitdht
|
||||
|
313
jsonapi-generator/README.adoc
Normal file
313
jsonapi-generator/README.adoc
Normal file
@ -0,0 +1,313 @@
|
||||
RetroShare JSON API
|
||||
===================
|
||||
|
||||
:Cxx: C++
|
||||
|
||||
== How to use RetroShare JSON API
|
||||
|
||||
Look for methods marked with +@jsonapi+ doxygen custom command into
|
||||
+libretroshare/src/retroshare+. The method path is composed by service instance
|
||||
pointer name like +rsGxsChannels+ for +RsGxsChannels+, and the method name like
|
||||
+createGroup+ and pass the input paramethers as a JSON object.
|
||||
|
||||
.Service instance pointer in rsgxschannels.h
|
||||
[source,cpp]
|
||||
--------------------------------------------------------------------------------
|
||||
/**
|
||||
* Pointer to global instance of RsGxsChannels service implementation
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
extern RsGxsChannels* rsGxsChannels;
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
.Method declaration in rsgxschannels.h
|
||||
[source,cpp]
|
||||
--------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Request channel creation.
|
||||
* The action is performed asyncronously, so it could fail in a subsequent
|
||||
* phase even after returning true.
|
||||
* @jsonapi{development}
|
||||
* @param[out] token Storage for RsTokenService token to track request
|
||||
* status.
|
||||
* @param[in] group Channel data (name, description...)
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool createGroup(uint32_t& token, RsGxsChannelGroup& group) = 0;
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
.paramethers.json
|
||||
[source,json]
|
||||
--------------------------------------------------------------------------------
|
||||
{
|
||||
"group":{
|
||||
"mMeta":{
|
||||
"mGroupName":"JSON test group",
|
||||
"mGroupFlags":4,
|
||||
"mSignFlags":520
|
||||
},
|
||||
"mDescription":"JSON test group description"
|
||||
},
|
||||
"caller_data":"Here can go any kind of JSON data (even objects) that the caller want to get back together with the response"
|
||||
}
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
.Calling the JSON API with curl on the terminal
|
||||
[source,bash]
|
||||
--------------------------------------------------------------------------------
|
||||
curl -H "Content-Type: application/json" --data @paramethers.json \
|
||||
http://127.0.0.1:9092/rsGxsChannels/createGroup
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
.JSON API call result
|
||||
[source,json]
|
||||
--------------------------------------------------------------------------------
|
||||
{
|
||||
"caller_data": "Here can go any kind of JSON data (even objects) that the caller want to get back together with the response",
|
||||
"retval": true,
|
||||
"token": 3
|
||||
}
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
== Offer new RetroShare services through JSON API
|
||||
|
||||
To offer a retroshare service through the JSON API, first of all one need find
|
||||
the global pointer to the service instance and document it in doxygen syntax,
|
||||
plus marking with the custom doxygen command +@jsonapi{RS_VERSION}+ where
|
||||
+RS_VERSION+ is the retroshare version in which this service became available
|
||||
with the current semantic (major changes to the service semantic, changes the
|
||||
meaning of the service itself, so the version should be updated in the
|
||||
documentation in that case).
|
||||
|
||||
.Service instance pointer in rsgxschannels.h
|
||||
[source,cpp]
|
||||
--------------------------------------------------------------------------------
|
||||
/**
|
||||
* Pointer to global instance of RsGxsChannels service implementation
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
extern RsGxsChannels* rsGxsChannels;
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Once the service instance itself is known to the JSON API you need to document
|
||||
in doxygen syntax and mark with the custom doxygen command
|
||||
+@jsonapi{RS_VERSION}+ the methods of the service that you want to make
|
||||
available through JSON API.
|
||||
|
||||
.Offering RsGxsChannels::getChannelDownloadDirectory in rsgxschannels.h
|
||||
[source,cpp]
|
||||
--------------------------------------------------------------------------------
|
||||
/**
|
||||
* Get download directory for the given channel
|
||||
* @jsonapi{development}
|
||||
* @param[in] channelId id of the channel
|
||||
* @param[out] directory reference to string where to store the path
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId,
|
||||
std::string& directory ) = 0;
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
For each paramether you must specify if it is used as input +@param[in]+ as
|
||||
output +@param[out]+ or both +@param[inout]+. Paramethers and return value
|
||||
types must be of a type supported by +RsTypeSerializer+ which already support
|
||||
most basic types (+bool+, +std::string+...), +RsSerializable+ and containers of
|
||||
them like +std::vector<std::string>+. Paramethers passed by value and by
|
||||
reference of those types are both supported, while passing by pointer is not
|
||||
supported. If your paramether or return +class+/+struct+ type is not supported
|
||||
yet by +RsTypeSerializer+ most convenient approach is to make it derive from
|
||||
+RsSerializable+ and implement +serial_process+ method like I did with
|
||||
+RsGxsChannelGroup+.
|
||||
|
||||
.Deriving RsGxsChannelGroup from RsSerializable in rsgxschannels.h
|
||||
[source,cpp]
|
||||
--------------------------------------------------------------------------------
|
||||
struct RsGxsChannelGroup : RsSerializable
|
||||
{
|
||||
RsGroupMetaData mMeta;
|
||||
std::string mDescription;
|
||||
RsGxsImage mImage;
|
||||
|
||||
bool mAutoDownload;
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mMeta);
|
||||
RS_SERIAL_PROCESS(mDescription);
|
||||
RS_SERIAL_PROCESS(mImage);
|
||||
RS_SERIAL_PROCESS(mAutoDownload);
|
||||
}
|
||||
};
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
You can do the same recursively for any member of your +struct+ that is not yet
|
||||
supported by +RsTypeSerializer+.
|
||||
|
||||
Some Retroshare {Cxx} API functions are asyncronous, historically RetroShare
|
||||
didn't follow a policy on how to expose asyncronous API so differents services
|
||||
and some times even differents method of the same service follow differents
|
||||
asyncronous patterns, thus making automatic generation of JSON API wrappers for
|
||||
those methods impractical. Instead of dealing with all those differents patterns
|
||||
I have chosed to support only one new pattern taking advantage of modern {Cxx}11
|
||||
and restbed features. On the {Cxx}11 side lambdas and +std::function+s are used,
|
||||
on the restbed side Server Side Events are used to send asyncronous results.
|
||||
|
||||
Lets see an example so it will be much esier to understand.
|
||||
|
||||
.RsGxsChannels::turtleSearchRequest asyncronous API
|
||||
[source,cpp]
|
||||
--------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Request remote channels search
|
||||
* @jsonapi{development}
|
||||
* @param[in] matchString string to look for in the search
|
||||
* @param multiCallback function that will be called each time a search
|
||||
* result is received
|
||||
* @param[in] maxWait maximum wait time in seconds for search results
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool turtleSearchRequest(
|
||||
const std::string& matchString,
|
||||
const std::function<void (const RsGxsGroupSummary& result)>& multiCallback,
|
||||
std::time_t maxWait = 300 ) = 0;
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
+RsGxsChannels::turtleSearchRequest(...)+ is an asyncronous method because it
|
||||
send a channel search request on turtle network and then everytime a result is
|
||||
received from the network +multiCallback+ is called and the result is passed as
|
||||
parameter. To be supported by the automatic JSON API wrappers generator an
|
||||
asyncronous method need a parameter of type +std::function<void (...)>+ called
|
||||
+callback+ if the callback will be called only once or +multiCallback+ if the
|
||||
callback is expected to be called more then once like in this case.
|
||||
A second mandatory parameter is +maxWait+ of type +std::time_t+ it indicates the
|
||||
maximum amount of time in seconds for which the caller is willing to wait for
|
||||
results, in case the timeout is reached the callback will not be called anymore.
|
||||
|
||||
[IMPORTANT]
|
||||
================================================================================
|
||||
+callback+ and +multiCallback+ parameters documentation must *not* specify
|
||||
+[in]+, +[out]+, +[inout]+, in Doxygen documentation as this would fool the
|
||||
automatic wrapper generator, and ultimately break the compilation.
|
||||
================================================================================
|
||||
|
||||
.RsFiles::turtleSearchRequest asyncronous JSON API usage example
|
||||
[source,bash]
|
||||
--------------------------------------------------------------------------------
|
||||
$ cat turtle_search.json
|
||||
{
|
||||
"matchString":"linux"
|
||||
}
|
||||
$ curl --data @turtle_search.json http://127.0.0.1:9092/rsFiles/turtleSearchRequest
|
||||
data: {"retval":true}
|
||||
|
||||
data: {"results":[{"size":157631,"hash":"69709b4d01025584a8def5cd78ebbd1a3cf3fd05","name":"kill_bill_linux_1024x768.jpg"},{"size":192560,"hash":"000000000000000000009a93e5be8486c496f46c","name":"coffee_box_linux2.jpg"},{"size":455087,"hash":"9a93e5be8486c496f46c00000000000000000000","name":"Linux.png"},{"size":182004,"hash":"e8845280912ebf3779e400000000000000000000","name":"Linux_2_6.png"}]}
|
||||
|
||||
data: {"results":[{"size":668,"hash":"e8845280912ebf3779e400000000000000000000","name":"linux.png"},{"size":70,"hash":"e8845280912ebf3779e400000000000000000000","name":"kali-linux-2016.2-amd64.txt.sha1sum"},{"size":3076767744,"hash":"e8845280912ebf3779e400000000000000000000","name":"kali-linux-2016.2-amd64.iso"},{"size":2780872,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.bin"},{"size":917504,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.lzma"},{"size":2278404096,"hash":"e8845280912ebf3779e400000000000000000000","name":"gentoo-linux-livedvd-amd64-multilib-20160704.iso"},{"size":151770333,"hash":"e8845280912ebf3779e400000000000000000000","name":"flashtool-0.9.23.0-linux.tar.7z"},{"size":2847372,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.elf"},{"size":1310720,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.gz"},{"size":987809,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux-lzma.elf"}]}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
== A bit of history
|
||||
|
||||
=== First writings about this
|
||||
|
||||
The previous attempt of exposing a RetroShare JSON API is called +libresapi+ and
|
||||
unfortunatley it requires a bunch of boilerplate code when we want to expose
|
||||
something present in the {Cxx} API in the JSON API.
|
||||
|
||||
As an example here you can see the libresapi that exposes part of the retroshare
|
||||
chat {Cxx} API and lot of boilerplate code just to convert {Cxx} objects to JSON
|
||||
|
||||
https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ChatHandler.cpp#L44
|
||||
|
||||
To avoid the {Cxx} to JSON and back conversion boilerplate code I have worked out
|
||||
an extension to our {Cxx} serialization code so it is capable to serialize and
|
||||
deserialize to JSON you can see it in this pull request
|
||||
|
||||
https://github.com/RetroShare/RetroShare/pull/1155
|
||||
|
||||
So first step toward having a good API is to take advantage of the fact that RS
|
||||
is now capable of converting C++ objects from and to JSON.
|
||||
|
||||
The current API is accessible via HTTP and unix socket, there is no
|
||||
authentication in both of them, so anyone having access to the HTTP server or to
|
||||
the unix socket can access the API without extra restrictions.
|
||||
Expecially for the HTTP API this is a big risk because also if the http server
|
||||
listen on 127.0.0.1 every application on the machine (even rogue javascript
|
||||
running on your web browser) can access that and for example on android it is
|
||||
not safe at all (because of that I implemented the unix socket access so at
|
||||
least in android API was reasonably safe) because of this.
|
||||
|
||||
A second step to improve the API would be to implement some kind of API
|
||||
authentication mechanism (it would be nice that the mechanism is handled at API
|
||||
level and not at transport level so we can use it for any API trasport not just
|
||||
HTTP for example)
|
||||
|
||||
The HTTP server used by libresapi is libmicrohttpd server that is very minimal,
|
||||
it doesn't provide HTTPS nor modern HTTP goodies, like server notifications,
|
||||
websockets etc. because the lack of support we have a token polling mechanism in
|
||||
libresapi to avoid polling for every thing but it is still ugly, so if we can
|
||||
completely get rid of polling in the API that would be really nice.
|
||||
I have done a crawl to look for a replacement and briefly looked at
|
||||
|
||||
- https://www.gnu.org/software/libmicrohttpd/
|
||||
- http://wolkykim.github.io/libasyncd/
|
||||
- https://github.com/corvusoft/restbed
|
||||
- https://code.facebook.com/posts/1503205539947302/introducing-proxygen-facebook-s-c-http-framework/
|
||||
- https://github.com/cmouse/yahttp
|
||||
|
||||
taking in account a few metrics like modern HTTP goodies support, license,
|
||||
platform support, external dependencies and documentation it seemed to me that
|
||||
restbed is the more appropriate.
|
||||
|
||||
Another source of boilerplate code into libresapi is the mapping between JSON
|
||||
API requests and C++ API methods as an example you can look at this
|
||||
|
||||
https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ChatHandler.cpp#L158
|
||||
|
||||
and this
|
||||
|
||||
https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ApiServer.cpp#L253
|
||||
|
||||
The abstract logic of this thing is, when libreasapi get a request like
|
||||
+/chat/initiate_distant_chat+ then call
|
||||
+ChatHandler::handleInitiateDistantChatConnexion+ which in turn is just a
|
||||
wrapper of +RsMsgs::initiateDistantChatConnexion+ all this process is basically
|
||||
implemented as boilerplate code and would be unnecessary in a smarter design of
|
||||
the API because almost all the information needed is already present in the
|
||||
C++ API +libretroshare/src/retroshare+.
|
||||
|
||||
So a third step to improve the JSON API would be to remove this source of
|
||||
boilerplate code by automatizing the mapping between C++ and JSON API call.
|
||||
|
||||
This may result a little tricky as language parsing or other adevanced things
|
||||
may be required.
|
||||
|
||||
Hope this dive is useful for you +
|
||||
Cheers +
|
||||
G10h4ck
|
||||
|
||||
=== Second writings about this
|
||||
|
||||
I have been investigating a bit more about:
|
||||
[verse, G10h4ck]
|
||||
________________________________________________________________________________
|
||||
So a third step to improve the JSON API would be to remove this source of
|
||||
boilerplate code by automatizing the mapping between C++ and JSON API call
|
||||
________________________________________________________________________________
|
||||
|
||||
After spending some hours investigating this topic the most reasonable approach
|
||||
seems to:
|
||||
|
||||
1. Properly document headers in +libretroshare/src/retroshare/+ in doxygen syntax
|
||||
specifying wihich params are input and/or output (doxygen sysntax for this is
|
||||
+@param[in/out/inout]+) this will be the API documentation too.
|
||||
|
||||
2. At compile time use doxygen to generate XML description of the headers and use
|
||||
the XML to generate the JSON api server stub.
|
||||
http://www.stack.nl/~dimitri/doxygen/manual/customize.html#xmlgenerator
|
||||
|
||||
3. Enjoy
|
73
jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl
Normal file
73
jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
registerHandler("$%apiPath%$",
|
||||
[$%captureVars%$](const std::shared_ptr<rb::Session> session)
|
||||
{
|
||||
const std::multimap<std::string, std::string> headers
|
||||
{
|
||||
{ "Connection", "keep-alive" },
|
||||
{ "Content-Type", "text/event-stream" }
|
||||
};
|
||||
session->yield(rb::OK, headers);
|
||||
|
||||
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
||||
session->fetch( reqSize, [$%captureVars%$](
|
||||
const std::shared_ptr<rb::Session> session,
|
||||
const rb::Bytes& body )
|
||||
{
|
||||
RsGenericSerializer::SerializeContext cReq(
|
||||
nullptr, 0,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING );
|
||||
RsJson& jReq(cReq.mJson);
|
||||
jReq.Parse(reinterpret_cast<const char*>(body.data()), body.size());
|
||||
|
||||
RsGenericSerializer::SerializeContext cAns;
|
||||
RsJson& jAns(cAns.mJson);
|
||||
|
||||
// if caller specified caller_data put it back in the answhere
|
||||
const char kcd[] = "caller_data";
|
||||
if(jReq.HasMember(kcd))
|
||||
jAns.AddMember(kcd, jReq[kcd], jAns.GetAllocator());
|
||||
|
||||
$%paramsDeclaration%$
|
||||
|
||||
$%inputParamsDeserialization%$
|
||||
|
||||
$%callbackName%$ = [session]($%callbackParams%$)
|
||||
{
|
||||
$%callbackParamsSerialization%$
|
||||
|
||||
std::stringstream message;
|
||||
message << "data: " << compactJSON << ctx.mJson << "\n\n";
|
||||
session->yield(message.str());
|
||||
$%sessionEarlyClose%$
|
||||
};
|
||||
|
||||
$%functionCall%$
|
||||
|
||||
$%outputParamsSerialization%$
|
||||
|
||||
// return them to the API caller
|
||||
std::stringstream message;
|
||||
message << "data: " << compactJSON << cAns.mJson << "\n\n";
|
||||
session->yield(message.str());
|
||||
$%sessionDelayedClose%$
|
||||
} );
|
||||
});
|
||||
|
229
jsonapi-generator/src/jsonapi-generator-doxygen.conf
Normal file
229
jsonapi-generator/src/jsonapi-generator-doxygen.conf
Normal file
@ -0,0 +1,229 @@
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "libretroshare"
|
||||
|
||||
ALIASES += jsonapi{1}="\xmlonly<jsonapi minversion=\"\1\"/>\endxmlonly"
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||
# documentation from any documented member that it re-implements.
|
||||
# The default value is: YES.
|
||||
|
||||
INHERIT_DOCS = YES
|
||||
|
||||
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
|
||||
# according to the Markdown format, which allows for more readable
|
||||
# documentation. See http://daringfireball.net/projects/markdown/ for details.
|
||||
# The output of markdown processing is further processed by doxygen, so you can
|
||||
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
|
||||
# case of backward compatibilities issues.
|
||||
# The default value is: YES.
|
||||
|
||||
MARKDOWN_SUPPORT = YES
|
||||
|
||||
# When enabled doxygen tries to link words that correspond to documented
|
||||
# classes, or namespaces to their corresponding documentation. Such a link can
|
||||
# be prevented in individual cases by putting a % sign in front of the word or
|
||||
# globally by setting AUTOLINK_SUPPORT to NO.
|
||||
# The default value is: YES.
|
||||
|
||||
AUTOLINK_SUPPORT = YES
|
||||
|
||||
|
||||
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
|
||||
# documentation are documented, even if no documentation was available. Private
|
||||
# class members and static file members will be hidden unless the
|
||||
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
|
||||
# Note: This will also disable the warnings about undocumented members that are
|
||||
# normally produced when WARNINGS is set to YES.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||
# undocumented members inside documented classes or files. If set to NO these
|
||||
# members will be included in the various overviews, but no documentation
|
||||
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
|
||||
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
|
||||
# undocumented classes that are normally visible in the class hierarchy. If set
|
||||
# to NO, these classes will be included in the various overviews. This option
|
||||
# has no effect if EXTRACT_ALL is enabled.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The INPUT tag is used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like myfile.cpp or
|
||||
# directories like /usr/src/myproject. Separate the files or directories with
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
#INPUT =
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
||||
# possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
|
||||
# *.h) to filter out the source-files in the directories.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
|
||||
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.idl \
|
||||
*.ddl \
|
||||
*.odl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.cs \
|
||||
*.d \
|
||||
*.php \
|
||||
*.php4 \
|
||||
*.php5 \
|
||||
*.phtml \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.markdown \
|
||||
*.md \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.pyw \
|
||||
*.f90 \
|
||||
*.f95 \
|
||||
*.f03 \
|
||||
*.f08 \
|
||||
*.f \
|
||||
*.for \
|
||||
*.tcl \
|
||||
*.vhd \
|
||||
*.vhdl \
|
||||
*.ucf \
|
||||
*.qsf
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
# The default value is: NO.
|
||||
|
||||
RECURSIVE = YES
|
||||
|
||||
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
||||
# excluded from the INPUT source files. This way you can easily exclude a
|
||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||
#
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE =
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
# from the input.
|
||||
# The default value is: NO.
|
||||
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
|
||||
# certain files from those directories.
|
||||
#
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories for example use the pattern */test/*
|
||||
|
||||
EXCLUDE_PATTERNS =
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# AClass::ANamespace, ANamespace::*Test
|
||||
#
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */test/*
|
||||
|
||||
EXCLUDE_SYMBOLS =
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_HTML = NO
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
|
||||
# captures the structure of the code including all documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_XML = YES
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
|
||||
# C-preprocessor directives found in the sources and include files.
|
||||
# The default value is: YES.
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
|
||||
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
|
||||
# in the source code. If set to NO, only conditional compilation will be
|
||||
# performed. Macro expansion can be done in a controlled way by setting
|
||||
# EXPAND_ONLY_PREDEF to YES.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
|
||||
# the macro expansion is limited to the macros specified with the PREDEFINED and
|
||||
# EXPAND_AS_DEFINED tags.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
|
364
jsonapi-generator/src/jsonapi-generator.cpp
Normal file
364
jsonapi-generator/src/jsonapi-generator.cpp
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* 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 <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QtXml>
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
#include <iterator>
|
||||
|
||||
struct MethodParam
|
||||
{
|
||||
MethodParam() :
|
||||
in(false), out(false), isMultiCallback(false), isSingleCallback(false){}
|
||||
|
||||
QString type;
|
||||
QString name;
|
||||
QString defval;
|
||||
bool in;
|
||||
bool out;
|
||||
bool isMultiCallback;
|
||||
bool isSingleCallback;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc != 3)
|
||||
qFatal("Usage: jsonapi-generator SOURCE_PATH OUTPUT_PATH");
|
||||
|
||||
QString sourcePath(argv[1]);
|
||||
QString outputPath(argv[2]);
|
||||
QString doxPrefix(outputPath+"/xml/");
|
||||
|
||||
QString wrappersDefFilePath(outputPath + "/jsonapi-wrappers.inl");
|
||||
QFile wrappersDefFile(wrappersDefFilePath);
|
||||
wrappersDefFile.remove();
|
||||
if(!wrappersDefFile.open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text))
|
||||
qFatal(QString("Can't open: " + wrappersDefFilePath).toLatin1().data());
|
||||
|
||||
QString cppApiIncludesFilePath(outputPath + "/jsonapi-includes.inl");
|
||||
QFile cppApiIncludesFile(cppApiIncludesFilePath);
|
||||
cppApiIncludesFile.remove();
|
||||
if(!cppApiIncludesFile.open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text))
|
||||
qFatal(QString("Can't open: " + cppApiIncludesFilePath).toLatin1().data());
|
||||
QSet<QString> cppApiIncludesSet;
|
||||
|
||||
QDirIterator it(doxPrefix, QStringList() << "*8h.xml", QDir::Files);
|
||||
while(it.hasNext())
|
||||
{
|
||||
QDomDocument hDoc;
|
||||
QString hFilePath(it.next());
|
||||
QString parseError; int line, column;
|
||||
QFile hFile(hFilePath);
|
||||
if (!hFile.open(QIODevice::ReadOnly) ||
|
||||
!hDoc.setContent(&hFile, &parseError, &line, &column))
|
||||
{
|
||||
qWarning() << "Error parsing:" << hFilePath
|
||||
<< parseError << line << column;
|
||||
continue;
|
||||
}
|
||||
|
||||
QFileInfo hfi(hFile);
|
||||
QString headerFileName(hfi.fileName());
|
||||
headerFileName.replace(QString("_8h.xml"), QString(".h"));
|
||||
|
||||
QDomNodeList sectiondefs = hDoc.elementsByTagName("sectiondef");
|
||||
for(int j = 0; j < sectiondefs.size(); ++j)
|
||||
{
|
||||
QDomElement sectDef = sectiondefs.item(j).toElement();
|
||||
|
||||
if( sectDef.attributes().namedItem("kind").nodeValue() != "var"
|
||||
|| sectDef.elementsByTagName("jsonapi").isEmpty() )
|
||||
continue;
|
||||
|
||||
QString instanceName =
|
||||
sectDef.elementsByTagName("name").item(0).toElement().text();
|
||||
QString typeName =
|
||||
sectDef.elementsByTagName("ref").item(0).toElement().text();
|
||||
QString typeFilePath(doxPrefix);
|
||||
typeFilePath += sectDef.elementsByTagName("ref").item(0)
|
||||
.attributes().namedItem("refid").nodeValue();
|
||||
typeFilePath += ".xml";
|
||||
|
||||
QDomDocument typeDoc;
|
||||
QFile typeFile(typeFilePath);
|
||||
if ( !typeFile.open(QIODevice::ReadOnly) ||
|
||||
!typeDoc.setContent(&typeFile, &parseError, &line, &column) )
|
||||
{
|
||||
qWarning() << "Error parsing:" << typeFilePath
|
||||
<< parseError << line << column;
|
||||
continue;
|
||||
}
|
||||
|
||||
QDomNodeList members = typeDoc.elementsByTagName("member");
|
||||
for (int i = 0; i < members.size(); ++i)
|
||||
{
|
||||
QDomNode member = members.item(i);
|
||||
QString refid(member.attributes().namedItem("refid").nodeValue());
|
||||
QString methodName(member.firstChildElement("name").toElement().text());
|
||||
QString wrapperName(instanceName+methodName+"Wrapper");
|
||||
QString defFilePath(doxPrefix + refid.split('_')[0] + ".xml");
|
||||
|
||||
qDebug() << "Looking for" << typeName << methodName << "into"
|
||||
<< typeFilePath;
|
||||
|
||||
QDomDocument defDoc;
|
||||
QFile defFile(defFilePath);
|
||||
if ( !defFile.open(QIODevice::ReadOnly) ||
|
||||
!defDoc.setContent(&defFile, &parseError, &line, &column) )
|
||||
{
|
||||
qWarning() << "Error parsing:" << defFilePath
|
||||
<< parseError << line << column;
|
||||
continue;
|
||||
}
|
||||
|
||||
QDomElement memberdef;
|
||||
QDomNodeList memberdefs = defDoc.elementsByTagName("memberdef");
|
||||
for (int k = 0; k < memberdefs.size(); ++k)
|
||||
{
|
||||
QDomElement tmpMBD = memberdefs.item(k).toElement();
|
||||
QString tmpId = tmpMBD.attributes().namedItem("id").nodeValue();
|
||||
QString tmpKind = tmpMBD.attributes().namedItem("kind").nodeValue();
|
||||
bool hasJsonApi = !tmpMBD.elementsByTagName("jsonapi").isEmpty();
|
||||
if( tmpId == refid && tmpKind == "function" && hasJsonApi )
|
||||
{
|
||||
memberdef = tmpMBD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(memberdef.isNull()) continue;
|
||||
|
||||
QString apiPath("/" + instanceName + "/" + methodName);
|
||||
QString retvalType = memberdef.firstChildElement("type").text();
|
||||
QMap<QString,MethodParam> paramsMap;
|
||||
QStringList orderedParamNames;
|
||||
bool hasInput = false;
|
||||
bool hasOutput = false;
|
||||
bool hasSingleCallback = false;
|
||||
bool hasMultiCallback = false;
|
||||
QString callbackName;
|
||||
QString callbackParams;
|
||||
|
||||
QDomNodeList params = memberdef.elementsByTagName("param");
|
||||
for (int k = 0; k < params.size(); ++k)
|
||||
{
|
||||
QDomElement tmpPE = params.item(k).toElement();
|
||||
MethodParam tmpParam;
|
||||
QString& pName(tmpParam.name);
|
||||
QString& pType(tmpParam.type);
|
||||
pName = tmpPE.firstChildElement("declname").text();
|
||||
QDomElement tmpDefval = tmpPE.firstChildElement("defval");
|
||||
if(!tmpDefval.isNull()) tmpParam.defval = tmpDefval.text();
|
||||
QDomElement tmpType = tmpPE.firstChildElement("type");
|
||||
pType = tmpType.text();
|
||||
if(pType.startsWith("const ")) pType.remove(0,6);
|
||||
if(pType.startsWith("std::function"))
|
||||
{
|
||||
if(pType.endsWith('&')) pType.chop(1);
|
||||
if(pName.startsWith("multiCallback"))
|
||||
{
|
||||
tmpParam.isMultiCallback = true;
|
||||
hasMultiCallback = true;
|
||||
}
|
||||
else if(pName.startsWith("callback"))
|
||||
{
|
||||
tmpParam.isSingleCallback = true;
|
||||
hasSingleCallback = true;
|
||||
}
|
||||
callbackName = pName;
|
||||
callbackParams = pType;
|
||||
}
|
||||
else
|
||||
{
|
||||
pType.replace(QString("&"), QString());
|
||||
pType.replace(QString(" "), QString());
|
||||
}
|
||||
paramsMap.insert(tmpParam.name, tmpParam);
|
||||
orderedParamNames.push_back(tmpParam.name);
|
||||
}
|
||||
|
||||
QDomNodeList parameternames = memberdef.elementsByTagName("parametername");
|
||||
for (int k = 0; k < parameternames.size(); ++k)
|
||||
{
|
||||
QDomElement tmpPN = parameternames.item(k).toElement();
|
||||
MethodParam& tmpParam = paramsMap[tmpPN.text()];
|
||||
QString tmpD = tmpPN.attributes().namedItem("direction").nodeValue();
|
||||
if(tmpD.contains("in"))
|
||||
{
|
||||
tmpParam.in = true;
|
||||
hasInput = true;
|
||||
}
|
||||
if(tmpD.contains("out"))
|
||||
{
|
||||
tmpParam.out = true;
|
||||
hasOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
QString functionCall("\t\t");
|
||||
if(retvalType != "void")
|
||||
{
|
||||
functionCall += retvalType + " retval = ";
|
||||
hasOutput = true;
|
||||
}
|
||||
functionCall += instanceName + "->" + methodName + "(";
|
||||
functionCall += orderedParamNames.join(", ") + ");\n";
|
||||
|
||||
qDebug() << instanceName << apiPath << retvalType << typeName
|
||||
<< methodName;
|
||||
for (const QString& pn : orderedParamNames)
|
||||
{
|
||||
const MethodParam& mp(paramsMap[pn]);
|
||||
qDebug() << "\t" << mp.type << mp.name << mp.in << mp.out;
|
||||
}
|
||||
|
||||
QString inputParamsDeserialization;
|
||||
if(hasInput)
|
||||
{
|
||||
inputParamsDeserialization +=
|
||||
"\t\t{\n"
|
||||
"\t\t\tRsGenericSerializer::SerializeContext& ctx(cReq);\n"
|
||||
"\t\t\tRsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);\n";
|
||||
}
|
||||
|
||||
QString outputParamsSerialization;
|
||||
if(hasOutput)
|
||||
{
|
||||
outputParamsSerialization +=
|
||||
"\t\t{\n"
|
||||
"\t\t\tRsGenericSerializer::SerializeContext& ctx(cAns);\n"
|
||||
"\t\t\tRsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);\n";
|
||||
}
|
||||
|
||||
QString paramsDeclaration;
|
||||
for (const QString& pn : orderedParamNames)
|
||||
{
|
||||
const MethodParam& mp(paramsMap[pn]);
|
||||
paramsDeclaration += "\t\t" + mp.type + " " + mp.name;
|
||||
if(!mp.defval.isEmpty())
|
||||
paramsDeclaration += "(" + mp.defval + ")";
|
||||
paramsDeclaration += ";\n";
|
||||
if(mp.in)
|
||||
inputParamsDeserialization += "\t\t\tRS_SERIAL_PROCESS("
|
||||
+ mp.name + ");\n";
|
||||
if(mp.out)
|
||||
outputParamsSerialization += "\t\t\tRS_SERIAL_PROCESS("
|
||||
+ mp.name + ");\n";
|
||||
}
|
||||
|
||||
if(hasInput) inputParamsDeserialization += "\t\t}\n";
|
||||
if(retvalType != "void")
|
||||
outputParamsSerialization +=
|
||||
"\t\t\tRS_SERIAL_PROCESS(retval);\n";
|
||||
if(hasOutput) outputParamsSerialization += "\t\t}\n";
|
||||
|
||||
QString captureVars;
|
||||
|
||||
QString sessionEarlyClose;
|
||||
if(hasSingleCallback)
|
||||
sessionEarlyClose = "session->close();";
|
||||
|
||||
QString sessionDelayedClose;
|
||||
if(hasMultiCallback)
|
||||
{
|
||||
sessionDelayedClose = "mService.schedule( [session](){session->close();}, std::chrono::seconds(maxWait+120) );";
|
||||
captureVars = "this";
|
||||
}
|
||||
|
||||
QString callbackParamsSerialization;
|
||||
|
||||
if(hasSingleCallback || hasMultiCallback ||
|
||||
((callbackParams.indexOf('(')+2) < callbackParams.indexOf(')')))
|
||||
{
|
||||
QString& cbs(callbackParamsSerialization);
|
||||
|
||||
callbackParams = callbackParams.split('(')[1];
|
||||
callbackParams = callbackParams.split(')')[0];
|
||||
|
||||
cbs += "\t\t\tRsGenericSerializer::SerializeContext ctx;\n";
|
||||
|
||||
for (QString cbPar : callbackParams.split(','))
|
||||
{
|
||||
bool isConst(cbPar.startsWith("const "));
|
||||
QChar pSep(' ');
|
||||
bool isRef(cbPar.contains('&'));
|
||||
if(isRef) pSep = '&';
|
||||
int sepIndex = cbPar.lastIndexOf(pSep)+1;
|
||||
QString cpt(cbPar.mid(0, sepIndex));
|
||||
cpt.remove(0,6);
|
||||
QString cpn(cbPar.mid(sepIndex));
|
||||
|
||||
cbs += "\t\t\tRsTypeSerializer::serial_process(";
|
||||
cbs += "RsGenericSerializer::TO_JSON, ctx, ";
|
||||
if(isConst)
|
||||
{
|
||||
cbs += "const_cast<";
|
||||
cbs += cpt;
|
||||
cbs += ">(";
|
||||
}
|
||||
cbs += cpn;
|
||||
if(isConst) cbs += ")";
|
||||
cbs += ", \"";
|
||||
cbs += cpn;
|
||||
cbs += "\" );\n";
|
||||
}
|
||||
}
|
||||
|
||||
QMap<QString,QString> substitutionsMap;
|
||||
substitutionsMap.insert("paramsDeclaration", paramsDeclaration);
|
||||
substitutionsMap.insert("inputParamsDeserialization", inputParamsDeserialization);
|
||||
substitutionsMap.insert("outputParamsSerialization", outputParamsSerialization);
|
||||
substitutionsMap.insert("wrapperName", wrapperName);
|
||||
substitutionsMap.insert("headerFileName", headerFileName);
|
||||
substitutionsMap.insert("functionCall", functionCall);
|
||||
substitutionsMap.insert("apiPath", apiPath);
|
||||
substitutionsMap.insert("sessionEarlyClose", sessionEarlyClose);
|
||||
substitutionsMap.insert("sessionDelayedClose", sessionDelayedClose);
|
||||
substitutionsMap.insert("captureVars", captureVars);
|
||||
substitutionsMap.insert("callbackName", callbackName);
|
||||
substitutionsMap.insert("callbackParams", callbackParams);
|
||||
substitutionsMap.insert("callbackParamsSerialization", callbackParamsSerialization);
|
||||
|
||||
QString templFilePath(sourcePath);
|
||||
if(hasMultiCallback || hasSingleCallback)
|
||||
templFilePath.append("/async-method-wrapper-template.cpp.tmpl");
|
||||
else templFilePath.append("/method-wrapper-template.cpp.tmpl");
|
||||
|
||||
QFile templFile(templFilePath);
|
||||
templFile.open(QIODevice::ReadOnly);
|
||||
QString wrapperDef(templFile.readAll());
|
||||
|
||||
QMap<QString,QString>::iterator it;
|
||||
for ( it = substitutionsMap.begin();
|
||||
it != substitutionsMap.end(); ++it )
|
||||
wrapperDef.replace(QString("$%"+it.key()+"%$"), QString(it.value()), Qt::CaseSensitive);
|
||||
|
||||
wrappersDefFile.write(wrapperDef.toLocal8Bit());
|
||||
|
||||
cppApiIncludesSet.insert("#include \"retroshare/" + headerFileName + "\"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const QString& incl : cppApiIncludesSet)
|
||||
cppApiIncludesFile.write(incl.toLocal8Bit());
|
||||
|
||||
return 0;
|
||||
}
|
6
jsonapi-generator/src/jsonapi-generator.pro
Normal file
6
jsonapi-generator/src/jsonapi-generator.pro
Normal file
@ -0,0 +1,6 @@
|
||||
TARGET = jsonapi-generator
|
||||
|
||||
QT *= core xml
|
||||
QT -= gui
|
||||
|
||||
SOURCES += jsonapi-generator.cpp
|
64
jsonapi-generator/src/method-wrapper-template.cpp.tmpl
Normal file
64
jsonapi-generator/src/method-wrapper-template.cpp.tmpl
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
registerHandler("$%apiPath%$",
|
||||
[$%captureVars%$](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 )
|
||||
{
|
||||
RsGenericSerializer::SerializeContext cReq(
|
||||
nullptr, 0,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING );
|
||||
RsJson& jReq(cReq.mJson);
|
||||
jReq.Parse(reinterpret_cast<const char*>(body.data()), body.size());
|
||||
|
||||
RsGenericSerializer::SerializeContext cAns;
|
||||
RsJson& jAns(cAns.mJson);
|
||||
|
||||
// if caller specified caller_data put it back in the answhere
|
||||
const char kcd[] = "caller_data";
|
||||
if(jReq.HasMember(kcd))
|
||||
jAns.AddMember(kcd, jReq[kcd], jAns.GetAllocator());
|
||||
|
||||
$%paramsDeclaration%$
|
||||
|
||||
// deserialize input parameters from JSON
|
||||
$%inputParamsDeserialization%$
|
||||
|
||||
// call retroshare C++ API
|
||||
$%functionCall%$
|
||||
|
||||
// serialize out parameters and return value to JSON
|
||||
$%outputParamsSerialization%$
|
||||
|
||||
// return them to the API caller
|
||||
std::stringstream ss;
|
||||
ss << jAns;
|
||||
std::string&& ans(ss.str());
|
||||
const std::multimap<std::string, std::string> headers
|
||||
{
|
||||
{ "Content-Type", "text/json" },
|
||||
{ "Content-Length", std::to_string(ans.length()) }
|
||||
};
|
||||
session->close(rb::OK, ans, headers);
|
||||
} );
|
||||
});
|
||||
|
@ -75,12 +75,12 @@ void ChannelsHandler::handleListChannels(Request& /*req*/, Response& resp)
|
||||
tChannels.requestGroupInfo(token, RS_DEPRECATED_TOKREQ_ANSTYPE, opts);
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((tChannels.requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))) rstime::rs_usleep(500*1000);
|
||||
|
||||
std::list<RsGroupMetaData> grps;
|
||||
if( tChannels.requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE
|
||||
if( tChannels.requestStatus(token) == RsTokenService::COMPLETE
|
||||
&& mChannels.getGroupSummary(token, grps) )
|
||||
{
|
||||
for( RsGroupMetaData& grp : grps )
|
||||
@ -140,12 +140,12 @@ void ChannelsHandler::handleGetChannelInfo(Request& req, Response& resp)
|
||||
opts, groupIds );
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((tChannels.requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))) rstime::rs_usleep(500*1000);
|
||||
|
||||
std::vector<RsGxsChannelGroup> grps;
|
||||
if( tChannels.requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE
|
||||
if( tChannels.requestStatus(token) == RsTokenService::COMPLETE
|
||||
&& mChannels.getGroupData(token, grps) )
|
||||
{
|
||||
for( RsGxsChannelGroup& grp : grps )
|
||||
@ -214,14 +214,14 @@ void ChannelsHandler::handleGetChannelContent(Request& req, Response& resp)
|
||||
}
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((mChannels.getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(mChannels.getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((mChannels.getTokenService()->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(mChannels.getTokenService()->requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))) rstime::rs_usleep(500*1000);
|
||||
|
||||
std::vector<RsGxsChannelPost> posts;
|
||||
std::vector<RsGxsComment> comments;
|
||||
if( mChannels.getTokenService()->requestStatus(token) ==
|
||||
RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE &&
|
||||
RsTokenService::COMPLETE &&
|
||||
mChannels.getPostData(token, posts, comments) )
|
||||
{
|
||||
for( std::vector<RsGxsChannelPost>::iterator vit = posts.begin();
|
||||
@ -290,11 +290,11 @@ void ChannelsHandler::handleToggleSubscription(Request& req, Response& resp)
|
||||
RsTokenService& tChannels = *mChannels.getTokenService();
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((tChannels.requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))) rstime::rs_usleep(500*1000);
|
||||
|
||||
if(tChannels.requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(tChannels.requestStatus(token) == RsTokenService::COMPLETE)
|
||||
resp.setOk();
|
||||
else resp.setFail("Unknown GXS error!");
|
||||
}
|
||||
@ -357,11 +357,11 @@ void ChannelsHandler::handleCreateChannel(Request& req, Response& resp)
|
||||
RsTokenService& tChannels = *mChannels.getTokenService();
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((tChannels.requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))) rstime::rs_usleep(500*1000);
|
||||
|
||||
if(tChannels.requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(tChannels.requestStatus(token) == RsTokenService::COMPLETE)
|
||||
resp.setOk();
|
||||
else resp.setFail("Unknown GXS error!");
|
||||
}
|
||||
@ -440,11 +440,11 @@ void ChannelsHandler::handleTogglePostRead(Request& req, Response& resp)
|
||||
RsTokenService& tChannels = *mChannels.getTokenService();
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((tChannels.requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))) rstime::rs_usleep(500*1000);
|
||||
|
||||
if(tChannels.requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(tChannels.requestStatus(token) == RsTokenService::COMPLETE)
|
||||
resp.setOk();
|
||||
else resp.setFail("Unknown GXS error!");
|
||||
}
|
||||
@ -526,11 +526,11 @@ void ChannelsHandler::handleCreatePost(Request &req, Response &resp)
|
||||
RsTokenService& tChannels = *mChannels.getTokenService();
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((tChannels.requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(tChannels.requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))) rstime::rs_usleep(500*1000);
|
||||
|
||||
if(tChannels.requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(tChannels.requestStatus(token) == RsTokenService::COMPLETE)
|
||||
resp.setOk();
|
||||
else resp.setFail("Unknown GXS error!");
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ void ForumHandler::handleWildcard(Request &req, Response &resp)
|
||||
mRsGxsForums->getTokenService()->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds);
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))
|
||||
)
|
||||
{
|
||||
@ -71,7 +71,7 @@ void ForumHandler::handleWildcard(Request &req, Response &resp)
|
||||
#endif
|
||||
}
|
||||
|
||||
if(mRsGxsForums->getTokenService()->requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(mRsGxsForums->getTokenService()->requestStatus(token) == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::vector<RsGxsForumMsg> grps;
|
||||
ok &= mRsGxsForums->getMsgData(token, grps);
|
||||
@ -107,8 +107,8 @@ void ForumHandler::handleWildcard(Request &req, Response &resp)
|
||||
mRsGxsForums->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts);
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(mRsGxsForums->getTokenService()->requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))
|
||||
)
|
||||
{
|
||||
@ -118,7 +118,7 @@ void ForumHandler::handleWildcard(Request &req, Response &resp)
|
||||
usleep(500*1000) ;
|
||||
#endif
|
||||
}
|
||||
if(mRsGxsForums->getTokenService()->requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(mRsGxsForums->getTokenService()->requestStatus(token) == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::vector<RsGxsForumGroup> grps;
|
||||
ok &= mRsGxsForums->getGroupData(token, grps);
|
||||
|
@ -42,11 +42,11 @@ bool GxsResponseTask::doWork(Request &req, Response &resp)
|
||||
for(std::vector<uint32_t>::iterator vit = mWaitingTokens.begin(); vit != mWaitingTokens.end(); ++vit)
|
||||
{
|
||||
uint8_t status = mTokenService->requestStatus(*vit);
|
||||
if(status != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(status != RsTokenService::COMPLETE)
|
||||
{
|
||||
ready = false;
|
||||
}
|
||||
if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
if(status == RsTokenService::FAILED)
|
||||
{
|
||||
std::cerr << "GxsResponseTask::doWork() Error: token failed. aborting." << std::endl;
|
||||
resp.setFail("GxsResponseTask::doWork() Error: token failed.");
|
||||
|
@ -223,15 +223,15 @@ void IdentityHandler::handleWildcard(Request & /*req*/, Response &resp)
|
||||
|
||||
time_t timeout = time(NULL)+10;
|
||||
uint8_t rStatus = mRsIdentity->getTokenService()->requestStatus(token);
|
||||
while( rStatus != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE &&
|
||||
rStatus != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED &&
|
||||
while( rStatus != RsTokenService::COMPLETE &&
|
||||
rStatus != RsTokenService::FAILED &&
|
||||
time(NULL) < timeout )
|
||||
{
|
||||
usleep(50*1000);
|
||||
rStatus = mRsIdentity->getTokenService()->requestStatus(token);
|
||||
}
|
||||
|
||||
if(rStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(rStatus == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::vector<RsGxsIdGroup> grps;
|
||||
ok &= mRsIdentity->getGroupData(token, grps);
|
||||
@ -280,15 +280,15 @@ void IdentityHandler::handleNotOwnIdsRequest(Request & /*req*/, Response &resp)
|
||||
|
||||
time_t timeout = time(NULL)+10;
|
||||
uint8_t rStatus = mRsIdentity->getTokenService()->requestStatus(token);
|
||||
while( rStatus != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE &&
|
||||
rStatus != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED &&
|
||||
while( rStatus != RsTokenService::COMPLETE &&
|
||||
rStatus != RsTokenService::FAILED &&
|
||||
time(NULL) < timeout )
|
||||
{
|
||||
usleep(50*1000);
|
||||
rStatus = mRsIdentity->getTokenService()->requestStatus(token);
|
||||
}
|
||||
|
||||
if(rStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(rStatus == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::vector<RsGxsIdGroup> grps;
|
||||
ok &= mRsIdentity->getGroupData(token, grps);
|
||||
@ -330,8 +330,8 @@ void IdentityHandler::handleOwnIdsRequest(Request & /*req*/, Response &resp)
|
||||
mRsIdentity->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts);
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))
|
||||
)
|
||||
{
|
||||
@ -342,7 +342,7 @@ void IdentityHandler::handleOwnIdsRequest(Request & /*req*/, Response &resp)
|
||||
#endif
|
||||
}
|
||||
|
||||
if(mRsIdentity->getTokenService()->requestStatus(token) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if(mRsIdentity->getTokenService()->requestStatus(token) == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::vector<RsGxsIdGroup> grps;
|
||||
ok &= mRsIdentity->getGroupData(token, grps);
|
||||
@ -413,8 +413,8 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp)
|
||||
mRsIdentity->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds);
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))
|
||||
)
|
||||
{
|
||||
@ -548,8 +548,8 @@ void IdentityHandler::handleSetAvatar(Request& req, Response& resp)
|
||||
mRsIdentity->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds);
|
||||
|
||||
time_t start = time(NULL);
|
||||
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
while((mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
&&(mRsIdentity->getTokenService()->requestStatus(token) != RsTokenService::FAILED)
|
||||
&&((time(NULL) < (start+10)))
|
||||
)
|
||||
{
|
||||
|
@ -71,7 +71,8 @@ ftServer::ftServer(p3PeerMgr *pm, p3ServiceControl *sc)
|
||||
mPeerMgr(pm), mServiceCtrl(sc),
|
||||
mFileDatabase(NULL),
|
||||
mFtController(NULL), mFtExtra(NULL),
|
||||
mFtDataplex(NULL), mFtSearch(NULL), srvMutex("ftServer")
|
||||
mFtDataplex(NULL), mFtSearch(NULL), srvMutex("ftServer"),
|
||||
mSearchCallbacksMapMutex("ftServer callbacks map")
|
||||
{
|
||||
addSerialType(new RsFileTransferSerialiser()) ;
|
||||
}
|
||||
@ -425,7 +426,7 @@ void ftServer::requestDirUpdate(void *ref)
|
||||
}
|
||||
|
||||
/* Directory Handling */
|
||||
bool ftServer::setDownloadDirectory(std::string path)
|
||||
bool ftServer::setDownloadDirectory(const std::string& path)
|
||||
{
|
||||
return mFtController->setDownloadDirectory(path);
|
||||
}
|
||||
@ -435,7 +436,7 @@ std::string ftServer::getDownloadDirectory()
|
||||
return mFtController->getDownloadDirectory();
|
||||
}
|
||||
|
||||
bool ftServer::setPartialsDirectory(std::string path)
|
||||
bool ftServer::setPartialsDirectory(const std::string& path)
|
||||
{
|
||||
return mFtController->setPartialsDirectory(path);
|
||||
}
|
||||
@ -1630,6 +1631,7 @@ int ftServer::tick()
|
||||
mFtDataplex->deleteUnusedServers() ;
|
||||
mFtDataplex->handlePendingCrcRequests() ;
|
||||
mFtDataplex->dispatchReceivedChunkCheckSum() ;
|
||||
cleanTimedOutSearches();
|
||||
}
|
||||
|
||||
return moreToTick;
|
||||
@ -1822,9 +1824,21 @@ int ftServer::handleIncoming()
|
||||
|
||||
void ftServer::receiveSearchResult(RsTurtleFTSearchResultItem *item)
|
||||
{
|
||||
// @Gio: add your thing here
|
||||
bool hasCallback = false;
|
||||
|
||||
RsServer::notify()->notifyTurtleSearchResult(item->request_id,item->result) ;
|
||||
{
|
||||
RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
auto cbpt = mSearchCallbacksMap.find(item->request_id);
|
||||
if(cbpt != mSearchCallbacksMap.end())
|
||||
{
|
||||
hasCallback = true;
|
||||
cbpt->second.first(item->result);
|
||||
}
|
||||
} // end RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
|
||||
if(!hasCallback)
|
||||
RsServer::notify()->notifyTurtleSearchResult(
|
||||
item->request_id, item->result );
|
||||
}
|
||||
|
||||
/***************************** CONFIG ****************************/
|
||||
@ -1839,3 +1853,38 @@ bool ftServer::addConfiguration(p3ConfigMgr *cfgmgr)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftServer::turtleSearchRequest(
|
||||
const std::string& matchString,
|
||||
const std::function<void (const std::list<TurtleFileInfo>& results)>& multiCallback,
|
||||
std::time_t maxWait )
|
||||
{
|
||||
if(matchString.empty())
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " match string can't be empty!"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
TurtleRequestId sId = turtleSearch(matchString);
|
||||
|
||||
RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
mSearchCallbacksMap.emplace(
|
||||
sId,
|
||||
std::make_pair(
|
||||
multiCallback,
|
||||
std::chrono::system_clock::now() +
|
||||
std::chrono::seconds(maxWait) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ftServer::cleanTimedOutSearches()
|
||||
{
|
||||
RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
auto now = std::chrono::system_clock::now();
|
||||
for( auto cbpt = mSearchCallbacksMap.begin();
|
||||
cbpt != mSearchCallbacksMap.end(); )
|
||||
if(cbpt->second.second <= now)
|
||||
cbpt = mSearchCallbacksMap.erase(cbpt);
|
||||
else ++cbpt;
|
||||
}
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
|
||||
#include "ft/ftdata.h"
|
||||
#include "turtle/turtleclientservice.h"
|
||||
@ -143,6 +145,12 @@ public:
|
||||
virtual void setFilePermDirectDL(uint32_t perm) ;
|
||||
virtual uint32_t filePermDirectDL() ;
|
||||
|
||||
/// @see RsFiles
|
||||
virtual bool turtleSearchRequest(
|
||||
const std::string& matchString,
|
||||
const std::function<void (const std::list<TurtleFileInfo>& results)>& multiCallback,
|
||||
std::time_t maxWait = 300 );
|
||||
|
||||
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
virtual TurtleSearchRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ;
|
||||
|
||||
@ -205,8 +213,8 @@ public:
|
||||
* Directory Handling
|
||||
***/
|
||||
virtual void requestDirUpdate(void *ref) ; // triggers the update of the given reference. Used when browsing.
|
||||
virtual bool setDownloadDirectory(std::string path);
|
||||
virtual bool setPartialsDirectory(std::string path);
|
||||
virtual bool setDownloadDirectory(const std::string& path);
|
||||
virtual bool setPartialsDirectory(const std::string& path);
|
||||
virtual std::string getDownloadDirectory();
|
||||
virtual std::string getPartialsDirectory();
|
||||
|
||||
@ -313,6 +321,18 @@ private:
|
||||
std::map<RsFileHash,RsFileHash> mEncryptedHashes ; // This map is such that sha1(it->second) = it->first
|
||||
std::map<RsPeerId,RsFileHash> mEncryptedPeerIds ; // This map holds the hash to be used with each peer id
|
||||
std::map<RsPeerId,std::map<RsFileHash,time_t> > mUploadLimitMap ;
|
||||
|
||||
/** Store search callbacks with timeout*/
|
||||
std::map<
|
||||
TurtleRequestId,
|
||||
std::pair<
|
||||
std::function<void (const std::list<TurtleFileInfo>& results)>,
|
||||
std::chrono::system_clock::time_point >
|
||||
> mSearchCallbacksMap;
|
||||
RsMutex mSearchCallbacksMapMutex;
|
||||
|
||||
/// Cleanup mSearchCallbacksMap
|
||||
void cleanTimedOutSearches();
|
||||
};
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ void GxsTokenQueue::checkRequests()
|
||||
uint32_t token = it->mToken;
|
||||
uint32_t status = mGenExchange->getTokenService()->requestStatus(token);
|
||||
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if (status == RsTokenService::COMPLETE)
|
||||
{
|
||||
toload.push_back(*it);
|
||||
it = mQueue.erase(it);
|
||||
@ -67,7 +67,7 @@ void GxsTokenQueue::checkRequests()
|
||||
#endif
|
||||
++it;
|
||||
}
|
||||
else if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
else if (status == RsTokenService::FAILED)
|
||||
{
|
||||
// maybe we should do alternative callback?
|
||||
std::cerr << "GxsTokenQueue::checkRequests() ERROR Request Failed: " << token;
|
||||
|
@ -1999,7 +1999,7 @@ void RsGenExchange::processMsgMetaChanges()
|
||||
|
||||
if(ok)
|
||||
{
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE);
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::COMPLETE);
|
||||
if (changed)
|
||||
{
|
||||
msgIds[m.msgId.first].insert(m.msgId.second);
|
||||
@ -2007,7 +2007,7 @@ void RsGenExchange::processMsgMetaChanges()
|
||||
}
|
||||
else
|
||||
{
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED);
|
||||
}
|
||||
|
||||
{
|
||||
@ -2053,11 +2053,11 @@ void RsGenExchange::processGrpMetaChanges()
|
||||
|
||||
if(ok)
|
||||
{
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE);
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::COMPLETE);
|
||||
grpChanged.push_back(g.grpId);
|
||||
}else
|
||||
{
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED);
|
||||
}
|
||||
|
||||
{
|
||||
@ -2290,7 +2290,7 @@ void RsGenExchange::publishMsgs()
|
||||
|
||||
// add to published to allow acknowledgement
|
||||
mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(grpId, msgId)));
|
||||
mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE);
|
||||
mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::COMPLETE);
|
||||
|
||||
}
|
||||
else
|
||||
@ -2300,7 +2300,7 @@ void RsGenExchange::publishMsgs()
|
||||
|
||||
if(!tryLater)
|
||||
mDataAccess->updatePublicRequestStatus(mit->first,
|
||||
RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
RsTokenService::FAILED);
|
||||
|
||||
std::cerr << "RsGenExchange::publishMsgs() failed to publish msg " << std::endl;
|
||||
}
|
||||
@ -2377,7 +2377,7 @@ void RsGenExchange::processGroupUpdatePublish()
|
||||
if(mit == grpMeta.end() || mit->second == NULL)
|
||||
{
|
||||
std::cerr << "Error! could not find meta of old group to update!" << std::endl;
|
||||
mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::FAILED);
|
||||
delete gup.grpItem;
|
||||
continue;
|
||||
}
|
||||
@ -2405,7 +2405,7 @@ void RsGenExchange::processGroupUpdatePublish()
|
||||
std::cerr << "(EE) publish group fails because RS cannot find the private publish and author keys" << std::endl;
|
||||
|
||||
delete gup.grpItem;
|
||||
mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2426,7 +2426,7 @@ void RsGenExchange::processRoutingClues()
|
||||
|
||||
void RsGenExchange::processGroupDelete()
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
RS_STACK_MUTEX(mGenMtx);
|
||||
|
||||
// get keys for group delete publish
|
||||
typedef std::pair<bool, RsGxsGroupId> GrpNote;
|
||||
@ -2447,8 +2447,9 @@ void RsGenExchange::processGroupDelete()
|
||||
for(; mit != toNotify.end(); ++mit)
|
||||
{
|
||||
GrpNote& note = mit->second;
|
||||
uint8_t status = note.first ? RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE
|
||||
: RsTokenService::GXS_REQUEST_V2_STATUS_FAILED;
|
||||
RsTokenService::GxsRequestStatus status =
|
||||
note.first ? RsTokenService::COMPLETE
|
||||
: RsTokenService::FAILED;
|
||||
|
||||
mGrpNotify.insert(std::make_pair(mit->first, note.second));
|
||||
mDataAccess->updatePublicRequestStatus(mit->first, status);
|
||||
@ -2756,8 +2757,9 @@ void RsGenExchange::publishGrps()
|
||||
for(; mit != toNotify.end(); ++mit)
|
||||
{
|
||||
GrpNote& note = mit->second;
|
||||
uint8_t status = note.first ? RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE
|
||||
: RsTokenService::GXS_REQUEST_V2_STATUS_FAILED;
|
||||
RsTokenService::GxsRequestStatus status =
|
||||
note.first ? RsTokenService::COMPLETE
|
||||
: RsTokenService::FAILED;
|
||||
|
||||
mGrpNotify.insert(std::make_pair(mit->first, note.second));
|
||||
mDataAccess->updatePublicRequestStatus(mit->first, status);
|
||||
@ -2793,7 +2795,8 @@ uint32_t RsGenExchange::generatePublicToken()
|
||||
return mDataAccess->generatePublicToken();
|
||||
}
|
||||
|
||||
bool RsGenExchange::updatePublicRequestStatus(const uint32_t &token, const uint32_t &status)
|
||||
bool RsGenExchange::updatePublicRequestStatus(
|
||||
uint32_t token, RsTokenService::GxsRequestStatus status )
|
||||
{
|
||||
return mDataAccess->updatePublicRequestStatus(token, status);
|
||||
}
|
||||
|
@ -479,7 +479,8 @@ public:
|
||||
* @param status
|
||||
* @return false if token could not be found, true if token disposed of
|
||||
*/
|
||||
bool updatePublicRequestStatus(const uint32_t &token, const uint32_t &status);
|
||||
bool updatePublicRequestStatus(
|
||||
uint32_t token, RsTokenService::GxsRequestStatus status);
|
||||
|
||||
/*!
|
||||
* This gets rid of a publicly issued token
|
||||
|
@ -26,15 +26,6 @@
|
||||
#include "rsgxsdataaccess.h"
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
|
||||
// TODO CLEANUP: This should be an enum defined in rstokenservice.h
|
||||
const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_FAILED = 0;
|
||||
const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_PENDING = 1;
|
||||
const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_PARTIAL = 2;
|
||||
const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_FINISHED_INCOMPLETE = 3;
|
||||
const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE = 4;
|
||||
const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_DONE = 5; // ONCE ALL DATA RETRIEVED.
|
||||
const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_CANCELLED = 6;
|
||||
|
||||
/***********
|
||||
* #define DATA_DEBUG 1
|
||||
**********/
|
||||
@ -314,22 +305,22 @@ void RsGxsDataAccess::storeRequest(GxsRequest* req)
|
||||
{
|
||||
RsStackMutex stack(mDataMutex); /****** LOCKED *****/
|
||||
|
||||
req->status = GXS_REQUEST_V2_STATUS_PENDING;
|
||||
req->status = PENDING;
|
||||
req->reqTime = time(NULL);
|
||||
mRequests[req->token] = req;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t RsGxsDataAccess::requestStatus(uint32_t token)
|
||||
RsTokenService::GxsRequestStatus RsGxsDataAccess::requestStatus(uint32_t token)
|
||||
{
|
||||
uint32_t status;
|
||||
RsTokenService::GxsRequestStatus status;
|
||||
uint32_t reqtype;
|
||||
uint32_t anstype;
|
||||
time_t ts;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mDataMutex);
|
||||
RS_STACK_MUTEX(mDataMutex);
|
||||
|
||||
// first check public tokens
|
||||
if(mPublicToken.find(token) != mPublicToken.end())
|
||||
@ -337,7 +328,7 @@ uint32_t RsGxsDataAccess::requestStatus(uint32_t token)
|
||||
}
|
||||
|
||||
if (!checkRequestStatus(token, status, reqtype, anstype, ts))
|
||||
return RsTokenService::GXS_REQUEST_V2_STATUS_FAILED;
|
||||
return RsTokenService::FAILED;
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -352,7 +343,7 @@ bool RsGxsDataAccess::cancelRequest(const uint32_t& token)
|
||||
return false;
|
||||
}
|
||||
|
||||
req->status = GXS_REQUEST_V2_STATUS_CANCELLED;
|
||||
req->status = CANCELLED;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -388,7 +379,7 @@ bool RsGxsDataAccess::getGroupSummary(const uint32_t& token, std::list<const RsG
|
||||
<< "group summary" << std::endl;
|
||||
return false;
|
||||
}
|
||||
else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
else if(req->status == COMPLETE)
|
||||
{
|
||||
GroupMetaReq* gmreq = dynamic_cast<GroupMetaReq*>(req);
|
||||
|
||||
@ -396,7 +387,7 @@ bool RsGxsDataAccess::getGroupSummary(const uint32_t& token, std::list<const RsG
|
||||
{
|
||||
groupInfo = gmreq->mGroupMetaData;
|
||||
gmreq->mGroupMetaData.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -427,7 +418,7 @@ bool RsGxsDataAccess::getGroupData(const uint32_t& token, std::list<RsNxsGrp*>&
|
||||
<< "data" << std::endl;
|
||||
return false;
|
||||
}
|
||||
else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
else if(req->status == COMPLETE)
|
||||
{
|
||||
GroupDataReq* gmreq = dynamic_cast<GroupDataReq*>(req);
|
||||
GroupSerializedDataReq* gsreq = dynamic_cast<GroupSerializedDataReq*>(req);
|
||||
@ -437,13 +428,13 @@ bool RsGxsDataAccess::getGroupData(const uint32_t& token, std::list<RsNxsGrp*>&
|
||||
grpData.swap(gsreq->mGroupData);
|
||||
gsreq->mGroupData.clear();
|
||||
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else if(gmreq)
|
||||
{
|
||||
grpData.swap(gmreq->mGroupData);
|
||||
gmreq->mGroupData.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -472,7 +463,7 @@ bool RsGxsDataAccess::getMsgData(const uint32_t& token, NxsMsgDataResult& msgDat
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getMsgData() Unable to retrieve group data" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
MsgDataReq* mdreq = dynamic_cast<MsgDataReq*>(req);
|
||||
|
||||
@ -480,7 +471,7 @@ bool RsGxsDataAccess::getMsgData(const uint32_t& token, NxsMsgDataResult& msgDat
|
||||
{
|
||||
msgData.swap(mdreq->mMsgData);
|
||||
mdreq->mMsgData.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -506,7 +497,7 @@ bool RsGxsDataAccess::getMsgRelatedData(const uint32_t &token, NxsMsgRelatedData
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getMsgRelatedData() Unable to retrieve group data" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
MsgRelatedInfoReq* mrireq = dynamic_cast<MsgRelatedInfoReq*>(req);
|
||||
|
||||
@ -517,7 +508,7 @@ bool RsGxsDataAccess::getMsgRelatedData(const uint32_t &token, NxsMsgRelatedData
|
||||
{
|
||||
msgData.swap(mrireq->mMsgDataResult);
|
||||
mrireq->mMsgDataResult.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -543,7 +534,7 @@ bool RsGxsDataAccess::getMsgSummary(const uint32_t& token, GxsMsgMetaResult& msg
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getMsgSummary() Unable to retrieve group data" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
MsgMetaReq* mmreq = dynamic_cast<MsgMetaReq*>(req);
|
||||
|
||||
@ -551,7 +542,7 @@ bool RsGxsDataAccess::getMsgSummary(const uint32_t& token, GxsMsgMetaResult& msg
|
||||
{
|
||||
msgInfo.swap(mmreq->mMsgMetaData);
|
||||
mmreq->mMsgMetaData.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
|
||||
}
|
||||
else
|
||||
@ -580,7 +571,7 @@ bool RsGxsDataAccess::getMsgRelatedSummary(const uint32_t &token, MsgRelatedMeta
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getMsgRelatedSummary() Unable to retrieve message summary" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_META)
|
||||
return false;
|
||||
@ -591,7 +582,7 @@ bool RsGxsDataAccess::getMsgRelatedSummary(const uint32_t &token, MsgRelatedMeta
|
||||
{
|
||||
msgMeta.swap(mrireq->mMsgMetaResult);
|
||||
mrireq->mMsgMetaResult.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -619,7 +610,7 @@ bool RsGxsDataAccess::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResul
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getMsgRelatedList() Unable to retrieve message data" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_IDS)
|
||||
return false;
|
||||
@ -630,7 +621,7 @@ bool RsGxsDataAccess::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResul
|
||||
{
|
||||
msgIds.swap(mrireq->mMsgIdResult);
|
||||
mrireq->mMsgIdResult.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else{
|
||||
std::cerr << "RsGxsDataAccess::getMsgRelatedList() Req found, failed caste" << std::endl;
|
||||
@ -656,7 +647,7 @@ bool RsGxsDataAccess::getMsgList(const uint32_t& token, GxsMsgIdResult& msgIds)
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getMsgList() Unable to retrieve msg Ids" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
MsgIdReq* mireq = dynamic_cast<MsgIdReq*>(req);
|
||||
|
||||
@ -664,7 +655,7 @@ bool RsGxsDataAccess::getMsgList(const uint32_t& token, GxsMsgIdResult& msgIds)
|
||||
{
|
||||
msgIds.swap(mireq->mMsgIdResult);
|
||||
mireq->mMsgIdResult.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else{
|
||||
std::cerr << "RsGxsDataAccess::getMsgList() Req found, failed caste" << std::endl;
|
||||
@ -689,7 +680,7 @@ bool RsGxsDataAccess::getGroupList(const uint32_t& token, std::list<RsGxsGroupId
|
||||
std::cerr << "RsGxsDataAccess::getGroupList() Unable to retrieve group Ids,"
|
||||
"\nRequest does not exist" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
GroupIdReq* gireq = dynamic_cast<GroupIdReq*>(req);
|
||||
|
||||
@ -697,7 +688,7 @@ bool RsGxsDataAccess::getGroupList(const uint32_t& token, std::list<RsGxsGroupId
|
||||
{
|
||||
groupIds.swap(gireq->mGroupIdResult);
|
||||
gireq->mGroupIdResult.clear();
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
|
||||
}else{
|
||||
std::cerr << "RsGxsDataAccess::getGroupList() Req found, failed caste" << std::endl;
|
||||
@ -739,21 +730,21 @@ void RsGxsDataAccess::processRequests()
|
||||
|
||||
switch (req->status)
|
||||
{
|
||||
case GXS_REQUEST_V2_STATUS_PENDING:
|
||||
case PENDING:
|
||||
// process request later
|
||||
break;
|
||||
case GXS_REQUEST_V2_STATUS_PARTIAL:
|
||||
case PARTIAL:
|
||||
// should not happen
|
||||
req->status = GXS_REQUEST_V2_STATUS_COMPLETE;
|
||||
req->status = COMPLETE;
|
||||
break;
|
||||
case GXS_REQUEST_V2_STATUS_DONE:
|
||||
case DONE:
|
||||
#ifdef DATA_DEBUG
|
||||
std::cerr << "RsGxsDataAccess::processrequests() Clearing Done Request Token: " << req->token;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
toClear.push_back(req->token);
|
||||
break;
|
||||
case GXS_REQUEST_V2_STATUS_CANCELLED:
|
||||
case CANCELLED:
|
||||
#ifdef DATA_DEBUG
|
||||
std::cerr << "RsGxsDataAccess::processrequests() Clearing Cancelled Request Token: " << req->token;
|
||||
std::cerr << std::endl;
|
||||
@ -791,10 +782,10 @@ void RsGxsDataAccess::processRequests()
|
||||
for (it = mRequests.begin(); it != mRequests.end(); ++it)
|
||||
{
|
||||
GxsRequest* reqCheck = it->second;
|
||||
if (reqCheck->status == GXS_REQUEST_V2_STATUS_PENDING)
|
||||
if (reqCheck->status == PENDING)
|
||||
{
|
||||
req = reqCheck;
|
||||
req->status = GXS_REQUEST_V2_STATUS_PARTIAL;
|
||||
req->status = PARTIAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -874,9 +865,9 @@ void RsGxsDataAccess::processRequests()
|
||||
|
||||
{
|
||||
RsStackMutex stack(mDataMutex); /******* LOCKED *******/
|
||||
if (req->status == GXS_REQUEST_V2_STATUS_PARTIAL)
|
||||
if (req->status == PARTIAL)
|
||||
{
|
||||
req->status = ok ? GXS_REQUEST_V2_STATUS_COMPLETE : GXS_REQUEST_V2_STATUS_FAILED;
|
||||
req->status = ok ? COMPLETE : FAILED;
|
||||
}
|
||||
} // END OF MUTEX.
|
||||
}
|
||||
@ -892,14 +883,14 @@ bool RsGxsDataAccess::getGroupStatistic(const uint32_t &token, GxsGroupStatistic
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getGroupStatistic() Unable to retrieve grp stats" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
GroupStatisticRequest* gsreq = dynamic_cast<GroupStatisticRequest*>(req);
|
||||
|
||||
if(gsreq)
|
||||
{
|
||||
grpStatistic = gsreq->mGroupStatistic;
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else{
|
||||
std::cerr << "RsGxsDataAccess::getGroupStatistic() Req found, failed caste" << std::endl;
|
||||
@ -923,14 +914,14 @@ bool RsGxsDataAccess::getServiceStatistic(const uint32_t &token, GxsServiceStati
|
||||
|
||||
std::cerr << "RsGxsDataAccess::getServiceStatistic() Unable to retrieve service stats" << std::endl;
|
||||
return false;
|
||||
}else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){
|
||||
}else if(req->status == COMPLETE){
|
||||
|
||||
ServiceStatisticRequest* ssreq = dynamic_cast<ServiceStatisticRequest*>(req);
|
||||
|
||||
if(ssreq)
|
||||
{
|
||||
servStatistic = ssreq->mServiceStatistic;
|
||||
locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE);
|
||||
locked_updateRequestStatus(token, DONE);
|
||||
}
|
||||
else{
|
||||
std::cerr << "RsGxsDataAccess::getServiceStatistic() Req found, failed caste" << std::endl;
|
||||
@ -1767,15 +1758,15 @@ void RsGxsDataAccess::filterGrpList(std::list<RsGxsGroupId> &grpIds, const RsTok
|
||||
}
|
||||
|
||||
|
||||
bool RsGxsDataAccess::checkRequestStatus(const uint32_t& token,
|
||||
uint32_t& status, uint32_t& reqtype, uint32_t& anstype, time_t& ts)
|
||||
bool RsGxsDataAccess::checkRequestStatus(
|
||||
uint32_t token, GxsRequestStatus& status, uint32_t& reqtype,
|
||||
uint32_t& anstype, time_t& ts )
|
||||
{
|
||||
|
||||
RsStackMutex stack(mDataMutex);
|
||||
RS_STACK_MUTEX(mDataMutex);
|
||||
|
||||
GxsRequest* req = locked_retrieveRequest(token);
|
||||
|
||||
if (req == NULL || req->status == GXS_REQUEST_V2_STATUS_CANCELLED)
|
||||
if (req == NULL || req->status == CANCELLED)
|
||||
return false;
|
||||
|
||||
anstype = req->ansType;
|
||||
@ -1845,70 +1836,52 @@ void RsGxsDataAccess::tokenList(std::list<uint32_t>& tokens)
|
||||
}
|
||||
}
|
||||
|
||||
bool RsGxsDataAccess::locked_updateRequestStatus(const uint32_t& token,
|
||||
const uint32_t& status)
|
||||
bool RsGxsDataAccess::locked_updateRequestStatus(
|
||||
uint32_t token, RsTokenService::GxsRequestStatus status )
|
||||
{
|
||||
|
||||
GxsRequest* req = locked_retrieveRequest(token);
|
||||
|
||||
if(req)
|
||||
req->status = status;
|
||||
else
|
||||
return false;
|
||||
if(req) req->status = status;
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t RsGxsDataAccess::generatePublicToken()
|
||||
{
|
||||
|
||||
uint32_t token;
|
||||
generateToken(token);
|
||||
|
||||
{
|
||||
RsStackMutex stack(mDataMutex);
|
||||
mPublicToken[token] = RsTokenService::GXS_REQUEST_V2_STATUS_PENDING;
|
||||
}
|
||||
{
|
||||
RS_STACK_MUTEX(mDataMutex);
|
||||
mPublicToken[token] = RsTokenService::PENDING;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool RsGxsDataAccess::updatePublicRequestStatus(const uint32_t& token,
|
||||
const uint32_t& status)
|
||||
bool RsGxsDataAccess::updatePublicRequestStatus(
|
||||
uint32_t token, RsTokenService::GxsRequestStatus status )
|
||||
{
|
||||
RsStackMutex stack(mDataMutex);
|
||||
std::map<uint32_t, uint32_t>::iterator mit = mPublicToken.find(token);
|
||||
|
||||
if(mit != mPublicToken.end())
|
||||
{
|
||||
mit->second = status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RS_STACK_MUTEX(mDataMutex);
|
||||
std::map<uint32_t, RsTokenService::GxsRequestStatus>::iterator mit =
|
||||
mPublicToken.find(token);
|
||||
if(mit != mPublicToken.end()) mit->second = status;
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool RsGxsDataAccess::disposeOfPublicToken(const uint32_t& token)
|
||||
bool RsGxsDataAccess::disposeOfPublicToken(uint32_t token)
|
||||
{
|
||||
RsStackMutex stack(mDataMutex);
|
||||
std::map<uint32_t, uint32_t>::iterator mit = mPublicToken.find(token);
|
||||
|
||||
if(mit != mPublicToken.end())
|
||||
{
|
||||
mPublicToken.erase(mit);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RS_STACK_MUTEX(mDataMutex);
|
||||
std::map<uint32_t, RsTokenService::GxsRequestStatus>::iterator mit =
|
||||
mPublicToken.find(token);
|
||||
if(mit != mPublicToken.end()) mPublicToken.erase(mit);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,8 @@ public:
|
||||
* deprecated and should be removed as soon as possible as it is cause of
|
||||
* many confusions, instead use const RsTokReqOptions::mReqType &opts to
|
||||
* specify the kind of data you are interested in.
|
||||
* Most of the methods use const uint32_t &token as param type change it to
|
||||
* uint32_t
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -117,7 +119,7 @@ public:
|
||||
|
||||
|
||||
/* Poll */
|
||||
uint32_t requestStatus(const uint32_t token);
|
||||
GxsRequestStatus requestStatus(const uint32_t token);
|
||||
|
||||
/* Cancel Request */
|
||||
bool cancelRequest(const uint32_t &token);
|
||||
@ -300,7 +302,7 @@ private:
|
||||
* @param status the status to set
|
||||
* @return
|
||||
*/
|
||||
bool locked_updateRequestStatus(const uint32_t &token, const uint32_t &status);
|
||||
bool locked_updateRequestStatus(uint32_t token, GxsRequestStatus status);
|
||||
|
||||
/*!
|
||||
* Use to query the status and other values of a given token
|
||||
@ -311,7 +313,8 @@ private:
|
||||
* @param ts time stamp
|
||||
* @return false if token does not exist, true otherwise
|
||||
*/
|
||||
bool checkRequestStatus(const uint32_t &token, uint32_t &status, uint32_t &reqtype, uint32_t &anstype, time_t &ts);
|
||||
bool checkRequestStatus( uint32_t token, GxsRequestStatus &status,
|
||||
uint32_t &reqtype, uint32_t &anstype, time_t &ts);
|
||||
|
||||
// special ones for testing (not in final design)
|
||||
/*!
|
||||
@ -341,14 +344,14 @@ public:
|
||||
* @param status
|
||||
* @return false if token could not be found, true if token disposed of
|
||||
*/
|
||||
bool updatePublicRequestStatus(const uint32_t &token, const uint32_t &status);
|
||||
bool updatePublicRequestStatus(uint32_t token, GxsRequestStatus status);
|
||||
|
||||
/*!
|
||||
* This gets rid of a publicly issued token
|
||||
* @param token
|
||||
* @return false if token could not found, true if token disposed of
|
||||
*/
|
||||
bool disposeOfPublicToken(const uint32_t &token);
|
||||
bool disposeOfPublicToken(uint32_t token);
|
||||
|
||||
private:
|
||||
|
||||
@ -488,7 +491,7 @@ private:
|
||||
RsMutex mDataMutex; /* protecting below */
|
||||
|
||||
uint32_t mNextToken;
|
||||
std::map<uint32_t, uint32_t> mPublicToken;
|
||||
std::map<uint32_t, GxsRequestStatus> mPublicToken;
|
||||
std::map<uint32_t, GxsRequest*> mRequests;
|
||||
|
||||
|
||||
|
@ -5181,43 +5181,51 @@ bool RsGxsNetService::clearDistantSearchResults(const TurtleRequestId& id)
|
||||
}
|
||||
void RsGxsNetService::receiveTurtleSearchResults(TurtleRequestId req, const std::list<RsGxsGroupSummary>& group_infos)
|
||||
{
|
||||
RS_STACK_MUTEX(mNxsMutex) ;
|
||||
std::set<RsGxsGroupId> groupsToNotifyResults;
|
||||
|
||||
RsGxsGrpMetaTemporaryMap grpMeta;
|
||||
std::map<RsGxsGroupId,RsGxsGroupSummary>& search_results_map(mDistantSearchResults[req]) ;
|
||||
{
|
||||
RS_STACK_MUTEX(mNxsMutex);
|
||||
|
||||
for(auto it(group_infos.begin());it!=group_infos.end();++it)
|
||||
if(search_results_map.find((*it).mGroupId) == search_results_map.end())
|
||||
grpMeta[(*it).mGroupId] = NULL;
|
||||
RsGxsGrpMetaTemporaryMap grpMeta;
|
||||
std::map<RsGxsGroupId,RsGxsGroupSummary>&
|
||||
search_results_map(mDistantSearchResults[req]);
|
||||
|
||||
mDataStore->retrieveGxsGrpMetaData(grpMeta);
|
||||
for(auto it(group_infos.begin());it!=group_infos.end();++it)
|
||||
if(search_results_map.find((*it).mGroupId) == search_results_map.end())
|
||||
grpMeta[(*it).mGroupId] = NULL;
|
||||
|
||||
std::list<RsGxsGroupSummary> filtered_results ;
|
||||
mDataStore->retrieveGxsGrpMetaData(grpMeta);
|
||||
|
||||
// only keep groups that are not locally known, and groups that are not already in the mDistantSearchResults structure
|
||||
// only keep groups that are not locally known, and groups that are not already in the mDistantSearchResults structure
|
||||
|
||||
for(auto it(group_infos.begin());it!=group_infos.end();++it)
|
||||
if(grpMeta[(*it).mGroupId] == NULL)
|
||||
{
|
||||
filtered_results.push_back(*it) ;
|
||||
for(auto it(group_infos.begin());it!=group_infos.end();++it)
|
||||
if(grpMeta[(*it).mGroupId] == NULL)
|
||||
{
|
||||
const RsGxsGroupId& grpId((*it).mGroupId);
|
||||
|
||||
auto it2 = search_results_map.find((*it).mGroupId) ;
|
||||
groupsToNotifyResults.insert(grpId);
|
||||
|
||||
if(it2 != search_results_map.end())
|
||||
{
|
||||
// update existing data
|
||||
auto it2 = search_results_map.find(grpId);
|
||||
|
||||
it2->second.mPopularity++ ;
|
||||
it2->second.mNumberOfMessages = std::max(it2->second.mNumberOfMessages,(*it).mNumberOfMessages) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
search_results_map[(*it).mGroupId] = *it;
|
||||
search_results_map[(*it).mGroupId].mPopularity = 1; // number of results so far
|
||||
}
|
||||
if(it2 != search_results_map.end())
|
||||
{
|
||||
// update existing data
|
||||
|
||||
mObserver->receiveDistantSearchResults(req,(*it).mGroupId) ;
|
||||
}
|
||||
it2->second.mPopularity++;
|
||||
it2->second.mNumberOfMessages = std::max(
|
||||
it2->second.mNumberOfMessages,
|
||||
(*it).mNumberOfMessages );
|
||||
}
|
||||
else
|
||||
{
|
||||
search_results_map[grpId] = *it;
|
||||
search_results_map[grpId].mPopularity = 1; // number of results so far
|
||||
}
|
||||
}
|
||||
} // end RS_STACK_MUTEX(mNxsMutex);
|
||||
|
||||
for(const RsGxsGroupId& grpId : groupsToNotifyResults)
|
||||
mObserver->receiveDistantSearchResults(req, grpId);
|
||||
}
|
||||
|
||||
void RsGxsNetService::receiveTurtleSearchResults(TurtleRequestId req,const unsigned char *encrypted_group_data,uint32_t encrypted_group_data_len)
|
||||
|
@ -28,7 +28,9 @@
|
||||
|
||||
struct GxsRequest
|
||||
{
|
||||
GxsRequest() : token(0), reqTime(0), ansType(0), reqType(0), status(0) {}
|
||||
GxsRequest() :
|
||||
token(0), reqTime(0), ansType(0), reqType(0),
|
||||
status(RsTokenService::FAILED) {}
|
||||
virtual ~GxsRequest() {}
|
||||
|
||||
uint32_t token;
|
||||
@ -38,7 +40,7 @@ struct GxsRequest
|
||||
uint32_t reqType;
|
||||
RsTokReqOptions Options;
|
||||
|
||||
uint32_t status;
|
||||
RsTokenService::GxsRequestStatus status;
|
||||
};
|
||||
|
||||
class GroupMetaReq : public GxsRequest
|
||||
|
@ -89,7 +89,7 @@ struct MsgSizeCount
|
||||
* @see GxsTransClient::receiveGxsTransMail(...),
|
||||
* @see GxsTransClient::notifyGxsTransSendStatus(...).
|
||||
*/
|
||||
class p3GxsTrans : public RsGenExchange, public GxsTokenQueue, public p3Config, public RsGxsTrans
|
||||
struct p3GxsTrans : RsGenExchange, GxsTokenQueue, p3Config, RsGxsTrans
|
||||
{
|
||||
public:
|
||||
p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes,
|
||||
@ -98,17 +98,16 @@ public:
|
||||
RS_SERVICE_TYPE_GXS_TRANS, &identities,
|
||||
AuthenPolicy()),
|
||||
GxsTokenQueue(this),
|
||||
RsGxsTrans(this),
|
||||
mIdService(identities),
|
||||
RsGxsTrans(static_cast<RsGxsIface&>(*this)),
|
||||
// always check 30 secs after start)
|
||||
mLastMsgCleanup(time(NULL) - MAX_DELAY_BETWEEN_CLEANUPS + 30),
|
||||
mIdService(identities),
|
||||
mServClientsMutex("p3GxsTrans client services map mutex"),
|
||||
mOutgoingMutex("p3GxsTrans outgoing queue map mutex"),
|
||||
mIngoingMutex("p3GxsTrans ingoing queue map mutex"),
|
||||
mCleanupThread(nullptr),
|
||||
mPerUserStatsMutex("p3GxsTrans user stats mutex"),
|
||||
mDataMutex("p3GxsTrans data mutex")
|
||||
{
|
||||
mLastMsgCleanup = time(NULL) - MAX_DELAY_BETWEEN_CLEANUPS + 30; // always check 30 secs after start
|
||||
mCleanupThread = NULL ;
|
||||
}
|
||||
mDataMutex("p3GxsTrans data mutex") {}
|
||||
|
||||
virtual ~p3GxsTrans();
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <time.h>
|
||||
|
145
libretroshare/src/jsonapi/jsonapi.cpp
Normal file
145
libretroshare/src/jsonapi/jsonapi.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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 "jsonapi.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <restbed>
|
||||
#include <vector>
|
||||
|
||||
#include "util/rsjson.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
#include "util/radix64.h"
|
||||
|
||||
// Generated at compile time
|
||||
#include "jsonapi-includes.inl"
|
||||
|
||||
JsonApiServer::JsonApiServer(
|
||||
uint16_t port, const std::function<void(int)> shutdownCallback) :
|
||||
mPort(port), mShutdownCallback(shutdownCallback)
|
||||
{
|
||||
registerHandler("/jsonApiServer/shutdown",
|
||||
[this](const std::shared_ptr<rb::Session>)
|
||||
{
|
||||
shutdown();
|
||||
});
|
||||
|
||||
registerHandler("/rsFiles/getFileData",
|
||||
[](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 )
|
||||
{
|
||||
RsGenericSerializer::SerializeContext cReq(
|
||||
nullptr, 0,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING );
|
||||
RsJson& jReq(cReq.mJson);
|
||||
jReq.Parse(reinterpret_cast<const char*>(body.data()), body.size());
|
||||
|
||||
RsGenericSerializer::SerializeContext cAns;
|
||||
RsJson& jAns(cAns.mJson);
|
||||
|
||||
// if caller specified caller_data put it back in the answhere
|
||||
const char kcd[] = "caller_data";
|
||||
if(jReq.HasMember(kcd))
|
||||
jAns.AddMember(kcd, jReq[kcd], jAns.GetAllocator());
|
||||
|
||||
RsFileHash hash;
|
||||
uint64_t offset;
|
||||
uint32_t requested_size;
|
||||
bool retval = false;
|
||||
std::string errorMessage;
|
||||
std::string base64data;
|
||||
|
||||
// deserialize input parameters from JSON
|
||||
{
|
||||
RsGenericSerializer::SerializeContext& ctx(cReq);
|
||||
RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);
|
||||
RS_SERIAL_PROCESS(hash);
|
||||
RS_SERIAL_PROCESS(offset);
|
||||
RS_SERIAL_PROCESS(requested_size);
|
||||
}
|
||||
|
||||
if(requested_size > 10485760)
|
||||
errorMessage = "requested_size is too big! Better less then 1M";
|
||||
else
|
||||
{
|
||||
std::vector<uint8_t> buffer(requested_size);
|
||||
|
||||
// call retroshare C++ API
|
||||
retval = rsFiles->getFileData(
|
||||
hash, offset, requested_size, buffer.data());
|
||||
|
||||
Radix64::encode(buffer.data(), requested_size, base64data);
|
||||
}
|
||||
|
||||
// serialize out parameters and return value to JSON
|
||||
{
|
||||
RsGenericSerializer::SerializeContext& ctx(cAns);
|
||||
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
|
||||
RS_SERIAL_PROCESS(retval);
|
||||
RS_SERIAL_PROCESS(requested_size);
|
||||
RS_SERIAL_PROCESS(base64data);
|
||||
if(!errorMessage.empty()) RS_SERIAL_PROCESS(errorMessage);
|
||||
}
|
||||
|
||||
// return them to the API caller
|
||||
std::stringstream ss;
|
||||
ss << jAns;
|
||||
std::string&& ans(ss.str());
|
||||
const std::multimap<std::string, std::string> headers
|
||||
{
|
||||
{ "Content-Type", "text/json" },
|
||||
{ "Content-Length", std::to_string(ans.length()) }
|
||||
};
|
||||
session->close(rb::OK, ans, headers);
|
||||
} );
|
||||
});
|
||||
|
||||
// Generated at compile time
|
||||
#include "jsonapi-wrappers.inl"
|
||||
}
|
||||
|
||||
void JsonApiServer::run()
|
||||
{
|
||||
std::shared_ptr<rb::Settings> settings(new rb::Settings);
|
||||
settings->set_port(mPort);
|
||||
// settings->set_default_header("Connection", "close");
|
||||
settings->set_default_header("Cache-Control", "no-cache");
|
||||
mService.start(settings);
|
||||
}
|
||||
|
||||
void JsonApiServer::registerHandler(
|
||||
const std::string& path,
|
||||
const std::function<void (const std::shared_ptr<restbed::Session>)>& handler)
|
||||
{
|
||||
std::shared_ptr<restbed::Resource> resource(new rb::Resource);
|
||||
resource->set_path(path);
|
||||
resource->set_method_handler("GET", handler);
|
||||
resource->set_method_handler("POST", handler);
|
||||
mService.publish(resource);
|
||||
}
|
||||
|
||||
void JsonApiServer::shutdown(int exitCode)
|
||||
{
|
||||
mService.stop();
|
||||
mShutdownCallback(exitCode);
|
||||
}
|
73
libretroshare/src/jsonapi/jsonapi.h
Normal file
73
libretroshare/src/jsonapi/jsonapi.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 <string>
|
||||
#include <memory>
|
||||
#include <restbed>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
namespace rb = restbed;
|
||||
|
||||
|
||||
/**
|
||||
* Simple usage
|
||||
* \code{.cpp}
|
||||
* JsonApiServer jas(9092);
|
||||
* jas.start("JsonApiServer");
|
||||
* \endcode
|
||||
*/
|
||||
struct JsonApiServer : RsSingleJobThread
|
||||
{
|
||||
JsonApiServer(
|
||||
uint16_t port,
|
||||
const std::function<void(int)> shutdownCallback = [](int){} );
|
||||
|
||||
/// @see RsSingleJobThread
|
||||
virtual void run();
|
||||
|
||||
/**
|
||||
* @param[in] path Path itno which publish the API call
|
||||
* @param[in] handler function which will be called to handle the requested
|
||||
* path, the function must be declared like:
|
||||
* \code{.cpp}
|
||||
* void functionName(const shared_ptr<restbed::Session> session)
|
||||
* \endcode
|
||||
*/
|
||||
void registerHandler(
|
||||
const std::string& path,
|
||||
const std::function<void(const std::shared_ptr<rb::Session>)>& handler );
|
||||
|
||||
/**
|
||||
* @brief Shutdown the JSON API server and call shutdownCallback
|
||||
* @jsonapi{development}
|
||||
* Beware that this method shout down only the JSON API server instance not
|
||||
* the whole RetroShare instance, this behaviour can be altered via
|
||||
* shutdownCallback paramether of @see JsonApiServer::JsonApiServer
|
||||
* This method is made available also via JSON API with path
|
||||
* /jsonApiServer/shutdown
|
||||
* @param exitCode just passed down to the shutdownCallback
|
||||
*/
|
||||
void shutdown(int exitCode = 0);
|
||||
|
||||
private:
|
||||
uint16_t mPort;
|
||||
rb::Service mService;
|
||||
const std::function<void(int)> mShutdownCallback;
|
||||
};
|
||||
|
@ -776,10 +776,12 @@ SOURCES += gxstunnel/p3gxstunnel.cc \
|
||||
# new serialization code
|
||||
HEADERS += serialiser/rsserializable.h \
|
||||
serialiser/rsserializer.h \
|
||||
serialiser/rstypeserializer.h
|
||||
serialiser/rstypeserializer.h \
|
||||
util/rsjson.h
|
||||
|
||||
SOURCES += serialiser/rsserializer.cc \
|
||||
serialiser/rstypeserializer.cc
|
||||
serialiser/rstypeserializer.cc \
|
||||
util/rsjson.cc
|
||||
|
||||
# Identity Service
|
||||
HEADERS += retroshare/rsidentity.h \
|
||||
@ -867,11 +869,64 @@ rs_gxs_trans {
|
||||
SOURCES += gxstrans/p3gxstransitems.cc gxstrans/p3gxstrans.cc
|
||||
}
|
||||
|
||||
rs_jsonapi {
|
||||
JSONAPI_GENERATOR_SRC=$$system_path($$clean_path($${RS_SRC_PATH}/jsonapi-generator/src/))
|
||||
JSONAPI_GENERATOR_OUT=$$system_path($$clean_path($${RS_BUILD_PATH}/jsonapi-generator/src/))
|
||||
JSONAPI_GENERATOR_EXE=$$system_path($$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-generator))
|
||||
DOXIGEN_INPUT_DIRECTORY=$$system_path($$clean_path($${PWD}))
|
||||
DOXIGEN_CONFIG_SRC=$$system_path($$clean_path($${RS_SRC_PATH}/jsonapi-generator/src/jsonapi-generator-doxygen.conf))
|
||||
DOXIGEN_CONFIG_OUT=$$system_path($$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-generator-doxygen.conf))
|
||||
WRAPPERS_INCL_FILE=$$system_path($$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-includes.inl))
|
||||
WRAPPERS_REG_FILE=$$system_path($$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-wrappers.inl))
|
||||
|
||||
restbed.target = $$system_path($$clean_path($${RESTBED_BUILD_PATH}/library/librestbed.a))
|
||||
restbed.commands = \
|
||||
cd $${RS_SRC_PATH};\
|
||||
git submodule update --init --recommend-shallow supportlibs/restbed;\
|
||||
cd $${RESTBED_SRC_PATH};\
|
||||
git submodule update --init --recommend-shallow dependency/asio;\
|
||||
git submodule update --init --recommend-shallow dependency/catch;\
|
||||
git submodule update --init --recommend-shallow dependency/kashmir;\
|
||||
mkdir -p $${RESTBED_BUILD_PATH}; cd $${RESTBED_BUILD_PATH};\
|
||||
cmake -DBUILD_SSL=OFF -DCMAKE_INSTALL_PREFIX=. -B. -H$${RESTBED_SRC_PATH};\
|
||||
make; make install
|
||||
QMAKE_EXTRA_TARGETS += restbed
|
||||
libretroshare.depends += restbed
|
||||
PRE_TARGETDEPS *= $${restbed.target}
|
||||
|
||||
PRE_TARGETDEPS *= $${JSONAPI_GENERATOR_EXE}
|
||||
INCLUDEPATH *= $${JSONAPI_GENERATOR_OUT}
|
||||
GENERATED_HEADERS += $${WRAPPERS_INCL_FILE}
|
||||
|
||||
jsonwrappersincl.target = $${WRAPPERS_INCL_FILE}
|
||||
jsonwrappersincl.commands = \
|
||||
cp $${DOXIGEN_CONFIG_SRC} $${DOXIGEN_CONFIG_OUT}; \
|
||||
echo OUTPUT_DIRECTORY=$${JSONAPI_GENERATOR_OUT} >> $${DOXIGEN_CONFIG_OUT};\
|
||||
echo INPUT=$${DOXIGEN_INPUT_DIRECTORY} >> $${DOXIGEN_CONFIG_OUT}; \
|
||||
doxygen $${DOXIGEN_CONFIG_OUT}; \
|
||||
$${JSONAPI_GENERATOR_EXE} $${JSONAPI_GENERATOR_SRC} $${JSONAPI_GENERATOR_OUT};
|
||||
QMAKE_EXTRA_TARGETS += jsonwrappersincl
|
||||
libretroshare.depends += jsonwrappersincl
|
||||
PRE_TARGETDEPS *= $${WRAPPERS_INCL_FILE}
|
||||
|
||||
jsonwrappersreg.target = $${WRAPPERS_REG_FILE}
|
||||
jsonwrappersreg.commands = touch $${WRAPPERS_REG_FILE}
|
||||
jsonwrappersreg.depends = jsonwrappersincl
|
||||
QMAKE_EXTRA_TARGETS += jsonwrappersreg
|
||||
libretroshare.depends += jsonwrappersreg
|
||||
PRE_TARGETDEPS *= $${WRAPPERS_REG_FILE}
|
||||
|
||||
# Force recalculation of libretroshare dependencies see https://stackoverflow.com/a/47884045
|
||||
QMAKE_EXTRA_TARGETS += libretroshare
|
||||
|
||||
HEADERS += jsonapi/jsonapi.h
|
||||
SOURCES += jsonapi/jsonapi.cpp
|
||||
}
|
||||
|
||||
rs_deep_search {
|
||||
HEADERS += deep_search/deep_search.h
|
||||
}
|
||||
|
||||
|
||||
###########################################################################################################
|
||||
# OLD CONFIG OPTIONS.
|
||||
# Not used much - but might be useful one day.
|
||||
|
@ -19,7 +19,6 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
|
||||
|
@ -95,7 +95,11 @@ std::string pgp_pwd_callback(void * /*hook*/, const char *uid_title, const char
|
||||
return password ;
|
||||
}
|
||||
|
||||
void AuthGPG::init(const std::string& path_to_public_keyring,const std::string& path_to_secret_keyring,const std::string& path_to_trustdb,const std::string& pgp_lock_file)
|
||||
void AuthGPG::init(
|
||||
const std::string& path_to_public_keyring,
|
||||
const std::string& path_to_secret_keyring,
|
||||
const std::string& path_to_trustdb,
|
||||
const std::string& pgp_lock_file)
|
||||
{
|
||||
if(_instance != NULL)
|
||||
{
|
||||
@ -103,8 +107,11 @@ void AuthGPG::init(const std::string& path_to_public_keyring,const std::string&
|
||||
std::cerr << "AuthGPG::init() called twice!" << std::endl ;
|
||||
}
|
||||
|
||||
PGPHandler::setPassphraseCallback(pgp_pwd_callback) ;
|
||||
_instance = new AuthGPG(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file) ;
|
||||
// if(cb) PGPHandler::setPassphraseCallback(cb);else
|
||||
PGPHandler::setPassphraseCallback(pgp_pwd_callback);
|
||||
_instance = new AuthGPG( path_to_public_keyring,
|
||||
path_to_secret_keyring,
|
||||
path_to_trustdb, pgp_lock_file );
|
||||
}
|
||||
|
||||
void AuthGPG::exit()
|
||||
|
@ -82,8 +82,8 @@ public:
|
||||
class AuthGPGService
|
||||
{
|
||||
public:
|
||||
AuthGPGService() {};
|
||||
~AuthGPGService() {};
|
||||
AuthGPGService() {}
|
||||
~AuthGPGService() {}
|
||||
|
||||
virtual AuthGPGOperation *getGPGOperation() = 0;
|
||||
virtual void setGPGOperation(AuthGPGOperation *operation) = 0;
|
||||
@ -91,12 +91,11 @@ public:
|
||||
|
||||
class AuthGPG: public p3Config, public RsTickingThread, public PGPHandler
|
||||
{
|
||||
public:
|
||||
|
||||
static void init( const std::string& path_to_pubring,
|
||||
const std::string& path_to_secring,
|
||||
const std::string& path_to_trustdb,
|
||||
const std::string& pgp_lock_file);
|
||||
public:
|
||||
static void init(const std::string& path_to_pubring,
|
||||
const std::string& path_to_secring,
|
||||
const std::string& path_to_trustdb,
|
||||
const std::string& pgp_lock_file);
|
||||
|
||||
static void exit();
|
||||
static AuthGPG *getAuthGPG() { return _instance ; }
|
||||
|
@ -19,18 +19,25 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef RS_FILES_GUI_INTERFACE_H
|
||||
#define RS_FILES_GUI_INTERFACE_H
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
|
||||
#include "rstypes.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "rsturtle.h"
|
||||
|
||||
class RsFiles;
|
||||
extern RsFiles *rsFiles;
|
||||
|
||||
/**
|
||||
* Pointer to global instance of RsFiles service implementation
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
extern RsFiles* rsFiles;
|
||||
|
||||
namespace RsRegularExpression { class Expression; }
|
||||
|
||||
@ -104,7 +111,7 @@ const TransferRequestFlags RS_FILE_REQ_NO_SEARCH ( 0x02000000 ); // di
|
||||
|
||||
const uint32_t RS_FILE_EXTRA_DELETE = 0x0010;
|
||||
|
||||
struct SharedDirInfo
|
||||
struct SharedDirInfo : RsSerializable
|
||||
{
|
||||
static bool sameLists(const std::list<RsNodeGroupId>& l1,const std::list<RsNodeGroupId>& l2)
|
||||
{
|
||||
@ -118,10 +125,22 @@ struct SharedDirInfo
|
||||
return it1 == l1.end() && it2 == l2.end() ;
|
||||
}
|
||||
|
||||
std::string filename ;
|
||||
std::string virtualname ;
|
||||
FileStorageFlags shareflags ; // combnation of DIR_FLAGS_ANONYMOUS_DOWNLOAD | DIR_FLAGS_BROWSABLE | ...
|
||||
std::list<RsNodeGroupId> parent_groups ;
|
||||
std::string filename;
|
||||
std::string virtualname;
|
||||
|
||||
/// combnation of DIR_FLAGS_ANONYMOUS_DOWNLOAD | DIR_FLAGS_BROWSABLE | ...
|
||||
FileStorageFlags shareflags;
|
||||
std::list<RsNodeGroupId> parent_groups;
|
||||
|
||||
/// @see RsSerializable::serial_process
|
||||
virtual void serial_process(RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RS_SERIAL_PROCESS(filename);
|
||||
RS_SERIAL_PROCESS(virtualname);
|
||||
RS_SERIAL_PROCESS(shareflags);
|
||||
RS_SERIAL_PROCESS(parent_groups);
|
||||
}
|
||||
};
|
||||
|
||||
struct SharedDirStats
|
||||
@ -168,38 +187,128 @@ public:
|
||||
RsFiles() {}
|
||||
virtual ~RsFiles() {}
|
||||
|
||||
/**
|
||||
* Provides file data for the gui: media streaming or rpc clients.
|
||||
* It may return unverified chunks. This allows streaming without having to wait for hashes or completion of the file.
|
||||
* This function returns an unspecified amount of bytes. Either as much data as available or a sensible maximum. Expect a block size of around 1MiB.
|
||||
* To get more data, call this function repeatedly with different offsets.
|
||||
* Returns false in case
|
||||
* - the files is not available on the local node
|
||||
* - not downloading
|
||||
* - the requested data was not downloaded yet
|
||||
* - end of file was reached
|
||||
* @param hash hash of a file. The file has to be available on this node or it has to be in downloading state.
|
||||
* @param offset where the desired block starts
|
||||
* @param requested_size size of pre-allocated data. Will be updated by the function.
|
||||
* @param data pre-allocated memory chunk of size 'requested_size' by the client
|
||||
*/
|
||||
virtual bool getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size,uint8_t *data)=0;
|
||||
/**
|
||||
* Provides file data for the gui, media streaming or rpc clients.
|
||||
* It may return unverified chunks. This allows streaming without having to
|
||||
* wait for hashes or completion of the file.
|
||||
* This function returns an unspecified amount of bytes. Either as much data
|
||||
* as available or a sensible maximum. Expect a block size of around 1MiB.
|
||||
* To get more data, call this function repeatedly with different offsets.
|
||||
*
|
||||
* jsonapi{development}
|
||||
* note the missing @ the wrapper for this is written manually not
|
||||
* autogenerated @see JsonApiServer.
|
||||
*
|
||||
* @param[in] hash hash of the file. The file has to be available on this node
|
||||
* or it has to be in downloading state.
|
||||
* @param[in] offset where the desired block starts
|
||||
* @param[inout] requested_size size of pre-allocated data. Will be updated
|
||||
* by the function.
|
||||
* @param data pre-allocated memory chunk of size 'requested_size' by the
|
||||
* client
|
||||
* @return Returns false in case
|
||||
* - the files is not available on the local node
|
||||
* - not downloading
|
||||
* - the requested data was not downloaded yet
|
||||
* - end of file was reached
|
||||
*/
|
||||
virtual bool getFileData( const RsFileHash& hash, uint64_t offset,
|
||||
uint32_t& requested_size, uint8_t* data ) = 0;
|
||||
|
||||
/***
|
||||
* Control of Downloads.
|
||||
***/
|
||||
/**
|
||||
* @brief Check if we already have a file
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash file identifier
|
||||
* @param[out] info storage for the possibly found file information
|
||||
* @return true if the file is already present, false otherwise
|
||||
*/
|
||||
virtual bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info) = 0;
|
||||
|
||||
/**
|
||||
* @brief Initiate downloading of a file
|
||||
* @jsonapi{development}
|
||||
* @param[in] fileName
|
||||
* @param[in] hash
|
||||
* @param[in] size
|
||||
* @param[in] destPath in not empty specify a destination path
|
||||
* @param[in] flags you usually want RS_FILE_REQ_ANONYMOUS_ROUTING
|
||||
* @param[in] srcIds eventually specify known sources
|
||||
* @return false if we already have the file, true otherwhise
|
||||
*/
|
||||
virtual bool FileRequest(
|
||||
const std::string& fileName, const RsFileHash& hash, uint64_t size,
|
||||
const std::string& destPath, TransferRequestFlags flags,
|
||||
const std::list<RsPeerId>& srcIds ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Cancel file downloading
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash
|
||||
* @return false if the file is not in the download queue, true otherwhise
|
||||
*/
|
||||
virtual bool FileCancel(const RsFileHash& hash) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set destination directory for given file
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash file identifier
|
||||
* @param[in] newPath
|
||||
* @return false if some error occurred, true otherwise
|
||||
*/
|
||||
virtual bool setDestinationDirectory(
|
||||
const RsFileHash& hash, const std::string& newPath ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set name for dowloaded file
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash file identifier
|
||||
* @param[in] newName
|
||||
* @return false if some error occurred, true otherwise
|
||||
*/
|
||||
virtual bool setDestinationName(
|
||||
const RsFileHash& hash, const std::string& newName ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set chunk strategy for file, useful to set streaming mode to be
|
||||
* able of see video or other media preview while it is still downloading
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash file identifier
|
||||
* @param[in] newStrategy
|
||||
* @return false if some error occurred, true otherwise
|
||||
*/
|
||||
virtual bool setChunkStrategy(
|
||||
const RsFileHash& hash,
|
||||
FileChunksInfo::ChunkStrategy newStrategy ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set default chunk strategy
|
||||
* @jsonapi{development}
|
||||
* @param[in] strategy
|
||||
*/
|
||||
virtual void setDefaultChunkStrategy(
|
||||
FileChunksInfo::ChunkStrategy strategy ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get default chunk strategy
|
||||
* @jsonapi{development}
|
||||
* @return current default chunck strategy
|
||||
*/
|
||||
virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() = 0;
|
||||
|
||||
/**
|
||||
* @brief Get free disk space limit
|
||||
* @jsonapi{development}
|
||||
* @return current current minimum free space on disk in MB
|
||||
*/
|
||||
virtual uint32_t freeDiskSpaceLimit() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Set minimum free disk space limit
|
||||
* @jsonapi{development}
|
||||
* @param[in] minimumFreeMB minimum free space in MB
|
||||
*/
|
||||
virtual void setFreeDiskSpaceLimit(uint32_t minimumFreeMB) = 0;
|
||||
|
||||
virtual bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info) = 0;
|
||||
/// Returns false is we already have the file. Otherwise, initiates the dl and returns true.
|
||||
virtual bool FileRequest(const std::string& fname, const RsFileHash& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list<RsPeerId>& srcIds) = 0;
|
||||
virtual bool FileCancel(const RsFileHash& hash) = 0;
|
||||
virtual bool setDestinationDirectory(const RsFileHash& hash,const std::string& new_path) = 0;
|
||||
virtual bool setDestinationName(const RsFileHash& hash,const std::string& new_name) = 0;
|
||||
virtual bool setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy) = 0;
|
||||
virtual void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy) = 0;
|
||||
virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() = 0;
|
||||
virtual uint32_t freeDiskSpaceLimit() const =0;
|
||||
virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) =0;
|
||||
virtual bool FileControl(const RsFileHash& hash, uint32_t flags) = 0;
|
||||
virtual bool FileClearCompleted() = 0;
|
||||
virtual void setDefaultEncryptionPolicy(uint32_t policy)=0; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE
|
||||
@ -208,8 +317,24 @@ public:
|
||||
virtual uint32_t getMaxUploadSlotsPerFriend()=0;
|
||||
virtual void setFilePermDirectDL(uint32_t perm)=0;
|
||||
virtual uint32_t filePermDirectDL()=0;
|
||||
virtual TurtleRequestId turtleSearch(const std::string& string_to_match) =0;
|
||||
virtual TurtleRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) =0;
|
||||
|
||||
/**
|
||||
* @brief Request remote files search
|
||||
* @jsonapi{development}
|
||||
* @param[in] matchString string to look for in the search
|
||||
* @param multiCallback function that will be called each time a search
|
||||
* result is received
|
||||
* @param[in] maxWait maximum wait time in seconds for search results
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool turtleSearchRequest(
|
||||
const std::string& matchString,
|
||||
const std::function<void (const std::list<TurtleFileInfo>& results)>& multiCallback,
|
||||
std::time_t maxWait = 300 ) = 0;
|
||||
|
||||
virtual TurtleRequestId turtleSearch(const std::string& string_to_match) = 0;
|
||||
virtual TurtleRequestId turtleSearch(
|
||||
const RsRegularExpression::LinearizedExpression& expr) = 0;
|
||||
|
||||
/***
|
||||
* Control of Downloads Priority.
|
||||
@ -220,21 +345,56 @@ public:
|
||||
virtual bool changeDownloadSpeed(const RsFileHash& hash, int speed) = 0;
|
||||
virtual bool getDownloadSpeed(const RsFileHash& hash, int & speed) = 0;
|
||||
virtual bool clearDownload(const RsFileHash& hash) = 0;
|
||||
// virtual void getDwlDetails(std::list<DwlDetails> & details) = 0;
|
||||
|
||||
/***
|
||||
* Download / Upload Details.
|
||||
***/
|
||||
virtual void FileDownloads(std::list<RsFileHash> &hashs) = 0;
|
||||
virtual bool FileUploads(std::list<RsFileHash> &hashs) = 0;
|
||||
virtual bool FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) = 0;
|
||||
/**
|
||||
* @brief Get incoming files list
|
||||
* @jsonapi{development}
|
||||
* @param[out] hashs storage for files identifiers list
|
||||
*/
|
||||
virtual void FileDownloads(std::list<RsFileHash>& hashs) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get outgoing files list
|
||||
* @jsonapi{development}
|
||||
* @param[out] hashs storage for files identifiers list
|
||||
* @return false if some error occurred, true otherwise
|
||||
*/
|
||||
virtual bool FileUploads(std::list<RsFileHash>& hashs) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get file details
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash file identifier
|
||||
* @param[in] hintflags filtering hint (RS_FILE_HINTS_EXTRA|...|RS_FILE_HINTS_LOCAL)
|
||||
* @param[out] info storage for file information
|
||||
* @return true if file found, false otherwise
|
||||
*/
|
||||
virtual bool FileDetails(
|
||||
const RsFileHash &hash, FileSearchFlags hintflags, FileInfo& info ) = 0;
|
||||
|
||||
virtual bool isEncryptedSource(const RsPeerId& virtual_peer_id) =0;
|
||||
|
||||
/// Gives chunk details about the downloaded file with given hash.
|
||||
virtual bool FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) = 0 ;
|
||||
/**
|
||||
* @brief Get chunk details about the downloaded file with given hash.
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash file identifier
|
||||
* @param[out] info storage for file information
|
||||
* @return true if file found, false otherwise
|
||||
*/
|
||||
virtual bool FileDownloadChunksDetails(
|
||||
const RsFileHash& hash, FileChunksInfo& info) = 0;
|
||||
|
||||
/// details about the upload with given hash
|
||||
virtual bool FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& map) = 0 ;
|
||||
/**
|
||||
* @brief Get details about the upload with given hash
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash file identifier
|
||||
* @param[in] peer_id peer identifier
|
||||
* @param[out] map storage for chunk info
|
||||
* @return true if file found, false otherwise
|
||||
*/
|
||||
virtual bool FileUploadChunksDetails(
|
||||
const RsFileHash& hash, const RsPeerId& peer_id,
|
||||
CompressedChunkMap& map ) = 0;
|
||||
|
||||
/***
|
||||
* Extra List Access
|
||||
@ -275,16 +435,76 @@ public:
|
||||
***/
|
||||
virtual void requestDirUpdate(void *ref) =0 ; // triggers the update of the given reference. Used when browsing.
|
||||
|
||||
virtual bool setDownloadDirectory(std::string path) = 0;
|
||||
virtual bool setPartialsDirectory(std::string path) = 0;
|
||||
virtual std::string getDownloadDirectory() = 0;
|
||||
virtual std::string getPartialsDirectory() = 0;
|
||||
/**
|
||||
* @brief Set default complete downloads directory
|
||||
* @jsonapi{development}
|
||||
* @param[in] path directory path
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool setDownloadDirectory(const std::string& path) = 0;
|
||||
|
||||
virtual bool getSharedDirectories(std::list<SharedDirInfo>& dirs) = 0;
|
||||
virtual bool setSharedDirectories(const std::list<SharedDirInfo>& dirs) = 0;
|
||||
virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0;
|
||||
virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; // updates the flags. The directory should already exist !
|
||||
virtual bool removeSharedDirectory(std::string dir) = 0;
|
||||
/**
|
||||
* @brief Set partial downloads directory
|
||||
* @jsonapi{development}
|
||||
* @param[in] path directory path
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool setPartialsDirectory(const std::string& path) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get default complete downloads directory
|
||||
* @jsonapi{development}
|
||||
* @return default completed downloads directory path
|
||||
*/
|
||||
virtual std::string getDownloadDirectory() = 0;
|
||||
|
||||
/**
|
||||
* @brief Get partial downloads directory
|
||||
* @jsonapi{development}
|
||||
* @return partials downloads directory path
|
||||
*/
|
||||
virtual std::string getPartialsDirectory() = 0;
|
||||
|
||||
/**
|
||||
* @brief Get list of current shared directories
|
||||
* @jsonapi{development}
|
||||
* @param[out] dirs storage for the list of share directories
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool getSharedDirectories(std::list<SharedDirInfo>& dirs) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set shared directories
|
||||
* @jsonapi{development}
|
||||
* @param[in] dirs list of shared directories with share options
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool setSharedDirectories(const std::list<SharedDirInfo>& dirs) = 0;
|
||||
|
||||
/**
|
||||
* @brief Add shared directory
|
||||
* @jsonapi{development}
|
||||
* @param[in] dir directory to share with sharing options
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0;
|
||||
|
||||
/**
|
||||
* @brief Updates shared directory sharing flags.
|
||||
* The directory should be already shared!
|
||||
* @jsonapi{development}
|
||||
* @param[in] dir Shared directory with updated sharing options
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool updateShareFlags(const SharedDirInfo& dir) = 0;
|
||||
|
||||
/**
|
||||
* @brief Remove directory from shared list
|
||||
* @jsonapi{development}
|
||||
* @param[in] dir Path of the directory to remove from shared list
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool removeSharedDirectory(std::string dir) = 0;
|
||||
|
||||
virtual bool getIgnoreLists(std::list<std::string>& ignored_prefixes, std::list<std::string>& ignored_suffixes,uint32_t& flags) =0;
|
||||
virtual void setIgnoreLists(const std::list<std::string>& ignored_prefixes, const std::list<std::string>& ignored_suffixes,uint32_t flags) =0;
|
||||
@ -306,8 +526,4 @@ public:
|
||||
|
||||
virtual bool ignoreDuplicates() = 0;
|
||||
virtual void setIgnoreDuplicates(bool ignore) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
/*******************************************************************************
|
||||
* libretroshare/src/retroshare: rsgxschannels.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2012-2012 by Robert Fernie <retroshare@lunamutt.com> *
|
||||
* 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 Lesser General Public License as *
|
||||
@ -19,44 +21,56 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef RETROSHARE_GXS_CHANNEL_GUI_INTERFACE_H
|
||||
#define RETROSHARE_GXS_CHANNEL_GUI_INTERFACE_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <functional>
|
||||
|
||||
#include "retroshare/rstokenservice.h"
|
||||
#include "retroshare/rsgxsifacehelper.h"
|
||||
#include "retroshare/rsgxscommon.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "retroshare/rsturtle.h"
|
||||
|
||||
/* The Main Interface Class - for information about your Peers */
|
||||
class RsGxsChannels;
|
||||
extern RsGxsChannels *rsGxsChannels;
|
||||
|
||||
/**
|
||||
* Pointer to global instance of RsGxsChannels service implementation
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
extern RsGxsChannels* rsGxsChannels;
|
||||
|
||||
// These should be in rsgxscommon.h
|
||||
|
||||
class RsGxsChannelGroup
|
||||
struct RsGxsChannelGroup : RsSerializable
|
||||
{
|
||||
public:
|
||||
RsGroupMetaData mMeta;
|
||||
std::string mDescription;
|
||||
RsGxsImage mImage;
|
||||
|
||||
bool mAutoDownload;
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mMeta);
|
||||
RS_SERIAL_PROCESS(mDescription);
|
||||
RS_SERIAL_PROCESS(mImage);
|
||||
RS_SERIAL_PROCESS(mAutoDownload);
|
||||
}
|
||||
};
|
||||
|
||||
class RsGxsChannelPost
|
||||
std::ostream &operator<<(std::ostream& out, const RsGxsChannelGroup& group);
|
||||
|
||||
|
||||
struct RsGxsChannelPost : RsSerializable
|
||||
{
|
||||
public:
|
||||
RsGxsChannelPost() : mCount(0), mSize(0) {}
|
||||
|
||||
public:
|
||||
RsMsgMetaData mMeta;
|
||||
|
||||
std::set<RsGxsMessageId> mOlderVersions ;
|
||||
std::set<RsGxsMessageId> mOlderVersions;
|
||||
std::string mMsg; // UTF8 encoded.
|
||||
|
||||
std::list<RsGxsFile> mFiles;
|
||||
@ -64,26 +78,217 @@ public:
|
||||
uint64_t mSize; // auto calced.
|
||||
|
||||
RsGxsImage mThumbnail;
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mMeta);
|
||||
RS_SERIAL_PROCESS(mOlderVersions);
|
||||
|
||||
RS_SERIAL_PROCESS(mMsg);
|
||||
RS_SERIAL_PROCESS(mFiles);
|
||||
RS_SERIAL_PROCESS(mCount);
|
||||
RS_SERIAL_PROCESS(mSize);
|
||||
RS_SERIAL_PROCESS(mThumbnail);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream& out, const RsGxsChannelPost& post);
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RsGxsChannelGroup &group);
|
||||
std::ostream &operator<<(std::ostream &out, const RsGxsChannelPost &post);
|
||||
|
||||
class RsGxsChannels: public RsGxsIfaceHelper, public RsGxsCommentService
|
||||
{
|
||||
public:
|
||||
|
||||
explicit RsGxsChannels(RsGxsIface *gxs)
|
||||
:RsGxsIfaceHelper(gxs) {}
|
||||
explicit RsGxsChannels(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
|
||||
virtual ~RsGxsChannels() {}
|
||||
|
||||
/* Specific Service Data */
|
||||
/**
|
||||
* @brief Get channels summaries list. Blocking API.
|
||||
* @jsonapi{development}
|
||||
* @param[out] channels list where to store the channels
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool getChannelsSummaries(std::list<RsGroupMetaData>& channels) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get channels information (description, thumbnail...).
|
||||
* Blocking API.
|
||||
* @jsonapi{development}
|
||||
* @param[in] chanIds ids of the channels of which to get the informations
|
||||
* @param[out] channelsInfo storage for the channels informations
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool getChannelsInfo(
|
||||
const std::list<RsGxsGroupId>& chanIds,
|
||||
std::vector<RsGxsChannelGroup>& channelsInfo ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get content of specified channels. Blocking API
|
||||
* @jsonapi{development}
|
||||
* @param[in] chanIds id of the channels of which the content is requested
|
||||
* @param[out] posts storage for the posts
|
||||
* @param[out] comments storage for the comments
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool getChannelsContent(
|
||||
const std::list<RsGxsGroupId>& chanIds,
|
||||
std::vector<RsGxsChannelPost>& posts,
|
||||
std::vector<RsGxsComment>& comments ) = 0;
|
||||
|
||||
/* Specific Service Data
|
||||
* TODO: change the orrible const uint32_t &token to uint32_t token
|
||||
* TODO: create a new typedef for token so code is easier to read
|
||||
*/
|
||||
|
||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsChannelGroup> &groups) = 0;
|
||||
virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &posts, std::vector<RsGxsComment> &cmts) = 0;
|
||||
virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &posts) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* @brief toggle message read status
|
||||
* @jsonapi{development}
|
||||
* @param[out] token GXS token queue token
|
||||
* @param[in] msgId
|
||||
* @param[in] read
|
||||
*/
|
||||
virtual void setMessageReadStatus(
|
||||
uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0;
|
||||
|
||||
/**
|
||||
* @brief Enable or disable auto-download for given channel
|
||||
* @jsonapi{development}
|
||||
* @param[in] groupId channel id
|
||||
* @param[in] enable true to enable, false to disable
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool setChannelAutoDownload(
|
||||
const RsGxsGroupId &groupId, bool enable) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get auto-download option value for given channel
|
||||
* @jsonapi{development}
|
||||
* @param[in] groupId channel id
|
||||
* @param[in] enabled storage for the auto-download option value
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool getChannelAutoDownload(
|
||||
const RsGxsGroupId &groupId, bool& enabled) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set download directory for the given channel
|
||||
* @jsonapi{development}
|
||||
* @param[in] channelId id of the channel
|
||||
* @param[in] directory path
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool setChannelDownloadDirectory(
|
||||
const RsGxsGroupId& channelId, const std::string& directory) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get download directory for the given channel
|
||||
* @jsonapi{development}
|
||||
* @param[in] channelId id of the channel
|
||||
* @param[out] directory reference to string where to store the path
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId,
|
||||
std::string& directory ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Share channel publishing key
|
||||
* This can be used to authorize other peers to post on the channel
|
||||
* @jsonapi{development}
|
||||
* param[in] groupId Channel id
|
||||
* param[in] peers peers to which share the key
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool groupShareKeys(
|
||||
const RsGxsGroupId& groupId, const std::set<RsPeerId>& peers ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Request subscription to a group.
|
||||
* The action is performed asyncronously, so it could fail in a subsequent
|
||||
* phase even after returning true.
|
||||
* @jsonapi{development}
|
||||
* @param[out] token Storage for RsTokenService token to track request
|
||||
* status.
|
||||
* @param[in] groupId Channel id
|
||||
* @param[in] subscribe
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool subscribeToGroup( uint32_t& token, const RsGxsGroupId &groupId,
|
||||
bool subscribe ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Request channel creation.
|
||||
* The action is performed asyncronously, so it could fail in a subsequent
|
||||
* phase even after returning true.
|
||||
* @jsonapi{development}
|
||||
* @param[out] token Storage for RsTokenService token to track request
|
||||
* status.
|
||||
* @param[in] group Channel data (name, description...)
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool createGroup(uint32_t& token, RsGxsChannelGroup& group) = 0;
|
||||
|
||||
/**
|
||||
* @brief Request post creation.
|
||||
* The action is performed asyncronously, so it could fail in a subsequent
|
||||
* phase even after returning true.
|
||||
* @jsonapi{development}
|
||||
* @param[out] token Storage for RsTokenService token to track request
|
||||
* status.
|
||||
* @param[in] post
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool createPost(uint32_t& token, RsGxsChannelPost& post) = 0;
|
||||
|
||||
/**
|
||||
* @brief Request channel change.
|
||||
* The action is performed asyncronously, so it could fail in a subsequent
|
||||
* phase even after returning true.
|
||||
* @jsonapi{development}
|
||||
* @param[out] token Storage for RsTokenService token to track request
|
||||
* status.
|
||||
* @param[in] group Channel data (name, description...) with modifications
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool updateGroup(uint32_t& token, RsGxsChannelGroup& group) = 0;
|
||||
|
||||
/**
|
||||
* @brief Share extra file
|
||||
* Can be used to share extra file attached to a channel post
|
||||
* @jsonapi{development}
|
||||
* @param[in] path file path
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool ExtraFileHash(const std::string& path) = 0;
|
||||
|
||||
/**
|
||||
* @brief Remove extra file from shared files
|
||||
* @jsonapi{development}
|
||||
* @param[in] hash hash of the file to remove
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool ExtraFileRemove(const RsFileHash& hash) = 0;
|
||||
|
||||
/**
|
||||
* @brief Request remote channels search
|
||||
* @jsonapi{development}
|
||||
* @param[in] matchString string to look for in the search
|
||||
* @param multiCallback function that will be called each time a search
|
||||
* result is received
|
||||
* @param[in] maxWait maximum wait time in seconds for search results
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool turtleSearchRequest(
|
||||
const std::string& matchString,
|
||||
const std::function<void (const RsGxsGroupSummary& result)>& multiCallback,
|
||||
std::time_t maxWait = 300 ) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// Distant synchronisation methods ///
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
@ -94,29 +299,4 @@ public:
|
||||
virtual bool retrieveDistantGroup(const RsGxsGroupId& group_id,RsGxsChannelGroup& distant_group)=0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0;
|
||||
|
||||
virtual bool setChannelAutoDownload(const RsGxsGroupId &groupId, bool enabled) = 0;
|
||||
virtual bool getChannelAutoDownload(const RsGxsGroupId &groupid, bool& enabled) = 0;
|
||||
|
||||
virtual bool setChannelDownloadDirectory(const RsGxsGroupId &groupId, const std::string& directory)=0;
|
||||
virtual bool getChannelDownloadDirectory(const RsGxsGroupId &groupId, std::string& directory)=0;
|
||||
|
||||
virtual bool groupShareKeys(const RsGxsGroupId &groupId, std::set<RsPeerId>& peers)=0;
|
||||
|
||||
// Overloaded subscribe fn.
|
||||
virtual bool subscribeToGroup(uint32_t &token, const RsGxsGroupId &groupId, bool subscribe) = 0;
|
||||
|
||||
virtual bool createGroup(uint32_t &token, RsGxsChannelGroup &group) = 0;
|
||||
virtual bool createPost(uint32_t &token, RsGxsChannelPost &post) = 0;
|
||||
|
||||
virtual bool updateGroup(uint32_t &token, RsGxsChannelGroup &group) = 0;
|
||||
|
||||
// File Interface
|
||||
virtual bool ExtraFileHash(const std::string &path, std::string filename) = 0;
|
||||
virtual bool ExtraFileRemove(const RsFileHash &hash) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -122,8 +122,8 @@ class RsGxsCircles: public RsGxsIfaceHelper
|
||||
{
|
||||
public:
|
||||
|
||||
RsGxsCircles(RsGxsIface *gxs) :RsGxsIfaceHelper(gxs) { return; }
|
||||
virtual ~RsGxsCircles() { return; }
|
||||
RsGxsCircles(RsGxsIface& gxs) :RsGxsIfaceHelper(gxs) {}
|
||||
virtual ~RsGxsCircles() {}
|
||||
|
||||
/* External Interface (Cached stuff) */
|
||||
virtual bool getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails &details) = 0;
|
||||
|
@ -31,37 +31,55 @@
|
||||
#include <list>
|
||||
|
||||
#include "rsgxsifacetypes.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
|
||||
class RsGxsFile
|
||||
struct RsGxsFile : RsSerializable
|
||||
{
|
||||
public:
|
||||
RsGxsFile();
|
||||
std::string mName;
|
||||
RsFileHash mHash;
|
||||
uint64_t mSize;
|
||||
//std::string mPath;
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mName);
|
||||
RS_SERIAL_PROCESS(mHash);
|
||||
RS_SERIAL_PROCESS(mSize);
|
||||
}
|
||||
};
|
||||
|
||||
class RsGxsImage
|
||||
struct RsGxsImage : RsSerializable
|
||||
{
|
||||
public:
|
||||
RsGxsImage();
|
||||
RsGxsImage();
|
||||
~RsGxsImage();
|
||||
RsGxsImage(const RsGxsImage& a); // TEMP use copy constructor and duplicate memory.
|
||||
RsGxsImage &operator=(const RsGxsImage &a); // Need this as well?
|
||||
|
||||
//NB: Must make sure that we always use methods - to be consistent about malloc/free for this data.
|
||||
static uint8_t *allocate(uint32_t size);
|
||||
static void release(void *data);
|
||||
/// Use copy constructor and duplicate memory.
|
||||
RsGxsImage(const RsGxsImage& a);
|
||||
|
||||
RsGxsImage &operator=(const RsGxsImage &a); // Need this as well?
|
||||
|
||||
/** NB: Must make sure that we always use methods - to be consistent about
|
||||
* malloc/free for this data. */
|
||||
static uint8_t *allocate(uint32_t size);
|
||||
static void release(void *data);
|
||||
|
||||
void take(uint8_t *data, uint32_t size); // Copies Pointer.
|
||||
void copy(uint8_t *data, uint32_t size); // Allocates and Copies.
|
||||
void clear(); // Frees.
|
||||
void shallowClear(); // Clears Pointer.
|
||||
|
||||
uint8_t *mData;
|
||||
uint32_t mSize;
|
||||
uint8_t* mData;
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RsTypeSerializer::TlvMemBlock_proxy b(mData, mSize);
|
||||
RsTypeSerializer::serial_process(j, ctx, b, "mData");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -84,17 +102,23 @@ namespace GXS_SERV {
|
||||
|
||||
|
||||
|
||||
class RsGxsVote
|
||||
struct RsGxsVote : RsSerializable
|
||||
{
|
||||
public:
|
||||
RsGxsVote();
|
||||
RsMsgMetaData mMeta;
|
||||
uint32_t mVoteType;
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mMeta);
|
||||
RS_SERIAL_PROCESS(mVoteType);
|
||||
}
|
||||
};
|
||||
|
||||
class RsGxsComment
|
||||
struct RsGxsComment : RsSerializable
|
||||
{
|
||||
public:
|
||||
RsGxsComment();
|
||||
RsMsgMetaData mMeta;
|
||||
std::string mComment;
|
||||
@ -109,6 +133,19 @@ class RsGxsComment
|
||||
// This is filled in if detailed Comment Data is called.
|
||||
std::list<RsGxsVote> mVotes;
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mMeta);
|
||||
RS_SERIAL_PROCESS(mComment);
|
||||
RS_SERIAL_PROCESS(mUpVotes);
|
||||
RS_SERIAL_PROCESS(mDownVotes);
|
||||
RS_SERIAL_PROCESS(mScore);
|
||||
RS_SERIAL_PROCESS(mOwnVote);
|
||||
RS_SERIAL_PROCESS(mVotes);
|
||||
}
|
||||
|
||||
const std::ostream &print(std::ostream &out, std::string indent = "", std::string varName = "") const {
|
||||
out << indent << varName << " of RsGxsComment Values ###################" << std::endl;
|
||||
mMeta.print(out, indent + " ", "mMeta");
|
||||
|
@ -59,8 +59,7 @@ class RsGxsForums: public RsGxsIfaceHelper
|
||||
{
|
||||
public:
|
||||
|
||||
explicit RsGxsForums(RsGxsIface *gxs)
|
||||
:RsGxsIfaceHelper(gxs) {}
|
||||
explicit RsGxsForums(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
|
||||
virtual ~RsGxsForums() {}
|
||||
|
||||
/* Specific Service Data */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "gxs/rsgxsdata.h"
|
||||
#include "retroshare/rsgxsifacetypes.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
|
||||
/*!
|
||||
* This structure is used to transport group summary information when a GXS
|
||||
@ -76,9 +77,8 @@ struct RsGxsGroupSummary : RsSerializable
|
||||
/*!
|
||||
* Stores ids of changed gxs groups and messages. It is used to notify the GUI about changes.
|
||||
*/
|
||||
class RsGxsChanges
|
||||
struct RsGxsChanges
|
||||
{
|
||||
public:
|
||||
RsGxsChanges(): mService(0){}
|
||||
RsTokenService *mService;
|
||||
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > mMsgs;
|
||||
@ -91,13 +91,9 @@ public:
|
||||
/*!
|
||||
* All implementations must offer thread safety
|
||||
*/
|
||||
class RsGxsIface
|
||||
struct RsGxsIface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~RsGxsIface(){};
|
||||
|
||||
public:
|
||||
virtual ~RsGxsIface() {}
|
||||
|
||||
/*!
|
||||
* Gxs services should call this for automatic handling of
|
||||
|
@ -7,6 +7,7 @@
|
||||
* RetroShare GXS. Convenience interface implementation
|
||||
*
|
||||
* Copyright 2012 by Christopher Evi-Parker
|
||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@ -26,29 +27,30 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "retroshare/rsgxsiface.h"
|
||||
#include "retroshare/rsreputations.h"
|
||||
#include "rsgxsflags.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
|
||||
/*!
|
||||
* The simple idea of this class is to implement the simple interface functions
|
||||
* of gen exchange.
|
||||
* This class provides convenience implementations of:
|
||||
* - Handle msg and group changes (client class must pass changes sent by RsGenExchange to it)
|
||||
* - subscription to groups
|
||||
* - retrieval of msgs and group ids and meta info
|
||||
* This class only make method of internal members visible tu upper level to
|
||||
* offer a more friendly API.
|
||||
* This is just a workaround to awkward GXS API design, do not take it as an
|
||||
* example for your coding.
|
||||
* To properly fix the API design many changes with the implied chain reactions
|
||||
* are necessary, so at this point this workaround seems acceptable.
|
||||
*/
|
||||
class RsGxsIfaceHelper
|
||||
struct RsGxsIfaceHelper
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
*
|
||||
* @param gxs handle to RsGenExchange instance of service (Usually the service class itself)
|
||||
*/
|
||||
RsGxsIfaceHelper(RsGxsIface* gxs)
|
||||
: mGxs(gxs)
|
||||
{}
|
||||
/*!
|
||||
* @param gxs handle to RsGenExchange instance of service (Usually the
|
||||
* service class itself)
|
||||
*/
|
||||
RsGxsIfaceHelper(RsGxsIface& gxs) :
|
||||
mGxs(gxs), mTokenService(*gxs.getTokenService()) {}
|
||||
|
||||
~RsGxsIfaceHelper(){}
|
||||
|
||||
@ -59,15 +61,7 @@ public:
|
||||
*/
|
||||
void receiveChanges(std::vector<RsGxsNotify *> &changes)
|
||||
{
|
||||
mGxs->receiveChanges(changes);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @return handle to token service for this GXS service
|
||||
*/
|
||||
RsTokenService* getTokenService()
|
||||
{
|
||||
return mGxs->getTokenService();
|
||||
mGxs.receiveChanges(changes);
|
||||
}
|
||||
|
||||
/* Generic Lists */
|
||||
@ -81,7 +75,7 @@ public:
|
||||
bool getGroupList(const uint32_t &token,
|
||||
std::list<RsGxsGroupId> &groupIds)
|
||||
{
|
||||
return mGxs->getGroupList(token, groupIds);
|
||||
return mGxs.getGroupList(token, groupIds);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -93,7 +87,7 @@ public:
|
||||
bool getMsgList(const uint32_t &token,
|
||||
GxsMsgIdResult& msgIds)
|
||||
{
|
||||
return mGxs->getMsgList(token, msgIds);
|
||||
return mGxs.getMsgList(token, msgIds);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -104,7 +98,7 @@ public:
|
||||
*/
|
||||
bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds)
|
||||
{
|
||||
return mGxs->getMsgRelatedList(token, msgIds);
|
||||
return mGxs.getMsgRelatedList(token, msgIds);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -115,7 +109,7 @@ public:
|
||||
bool getGroupSummary(const uint32_t &token,
|
||||
std::list<RsGroupMetaData> &groupInfo)
|
||||
{
|
||||
return mGxs->getGroupMeta(token, groupInfo);
|
||||
return mGxs.getGroupMeta(token, groupInfo);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -126,7 +120,7 @@ public:
|
||||
bool getMsgSummary(const uint32_t &token,
|
||||
GxsMsgMetaMap &msgInfo)
|
||||
{
|
||||
return mGxs->getMsgMeta(token, msgInfo);
|
||||
return mGxs.getMsgMeta(token, msgInfo);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -136,7 +130,7 @@ public:
|
||||
*/
|
||||
bool getMsgRelatedSummary(const uint32_t &token, GxsMsgRelatedMetaMap &msgInfo)
|
||||
{
|
||||
return mGxs->getMsgRelatedMeta(token, msgInfo);
|
||||
return mGxs.getMsgRelatedMeta(token, msgInfo);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -147,7 +141,7 @@ public:
|
||||
*/
|
||||
bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe)
|
||||
{
|
||||
return mGxs->subscribeToGroup(token, grpId, subscribe);
|
||||
return mGxs.subscribeToGroup(token, grpId, subscribe);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -159,7 +153,7 @@ public:
|
||||
*/
|
||||
bool acknowledgeMsg(const uint32_t& token, std::pair<RsGxsGroupId, RsGxsMessageId>& msgId)
|
||||
{
|
||||
return mGxs->acknowledgeTokenMsg(token, msgId);
|
||||
return mGxs.acknowledgeTokenMsg(token, msgId);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -171,7 +165,7 @@ public:
|
||||
*/
|
||||
bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId)
|
||||
{
|
||||
return mGxs->acknowledgeTokenGrp(token, grpId);
|
||||
return mGxs.acknowledgeTokenGrp(token, grpId);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -182,7 +176,7 @@ public:
|
||||
*/
|
||||
bool getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats)
|
||||
{
|
||||
return mGxs->getServiceStatistic(token, stats);
|
||||
return mGxs.getServiceStatistic(token, stats);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -193,7 +187,7 @@ public:
|
||||
*/
|
||||
bool getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats)
|
||||
{
|
||||
return mGxs->getGroupStatistic(token, stats);
|
||||
return mGxs.getGroupStatistic(token, stats);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -206,7 +200,7 @@ public:
|
||||
*/
|
||||
void setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff)
|
||||
{
|
||||
return mGxs->setGroupReputationCutOff(token, grpId, CutOff);
|
||||
return mGxs.setGroupReputationCutOff(token, grpId, CutOff);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -214,36 +208,111 @@ public:
|
||||
*/
|
||||
uint32_t getDefaultStoragePeriod()
|
||||
{
|
||||
return mGxs->getDefaultStoragePeriod();
|
||||
return mGxs.getDefaultStoragePeriod();
|
||||
}
|
||||
uint32_t getStoragePeriod(const RsGxsGroupId& grpId)
|
||||
{
|
||||
return mGxs->getStoragePeriod(grpId);
|
||||
return mGxs.getStoragePeriod(grpId);
|
||||
}
|
||||
void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs)
|
||||
{
|
||||
mGxs->setStoragePeriod(grpId,age_in_secs);
|
||||
mGxs.setStoragePeriod(grpId,age_in_secs);
|
||||
}
|
||||
uint32_t getDefaultSyncPeriod()
|
||||
{
|
||||
return mGxs->getDefaultSyncPeriod();
|
||||
return mGxs.getDefaultSyncPeriod();
|
||||
}
|
||||
uint32_t getSyncPeriod(const RsGxsGroupId& grpId)
|
||||
{
|
||||
return mGxs->getSyncPeriod(grpId);
|
||||
return mGxs.getSyncPeriod(grpId);
|
||||
}
|
||||
void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs)
|
||||
{
|
||||
mGxs->setSyncPeriod(grpId,age_in_secs);
|
||||
mGxs.setSyncPeriod(grpId,age_in_secs);
|
||||
}
|
||||
|
||||
RsReputations::ReputationLevel minReputationForForwardingMessages(uint32_t group_sign_flags,uint32_t identity_flags)
|
||||
{
|
||||
return mGxs->minReputationForForwardingMessages(group_sign_flags,identity_flags);
|
||||
return mGxs.minReputationForForwardingMessages(group_sign_flags,identity_flags);
|
||||
}
|
||||
private:
|
||||
|
||||
RsGxsIface* mGxs;
|
||||
/// @see RsTokenService::requestGroupInfo
|
||||
bool requestGroupInfo( uint32_t& token, const RsTokReqOptions& opts,
|
||||
const std::list<RsGxsGroupId> &groupIds )
|
||||
{ return mTokenService.requestGroupInfo(token, 0, opts, groupIds); }
|
||||
|
||||
/// @see RsTokenService::requestGroupInfo
|
||||
bool requestGroupInfo(uint32_t& token, const RsTokReqOptions& opts)
|
||||
{ return mTokenService.requestGroupInfo(token, 0, opts); }
|
||||
|
||||
/// @see RsTokenService::requestMsgInfo
|
||||
bool requestMsgInfo( uint32_t& token,
|
||||
const RsTokReqOptions& opts, const GxsMsgReq& msgIds )
|
||||
{ return mTokenService.requestMsgInfo(token, 0, opts, msgIds); }
|
||||
|
||||
/// @see RsTokenService::requestMsgInfo
|
||||
bool requestMsgInfo(
|
||||
uint32_t& token, const RsTokReqOptions& opts,
|
||||
const std::list<RsGxsGroupId>& grpIds )
|
||||
{ return mTokenService.requestMsgInfo(token, 0, opts, grpIds); }
|
||||
|
||||
/// @see RsTokenService::requestMsgRelatedInfo
|
||||
bool requestMsgRelatedInfo(
|
||||
uint32_t& token, const RsTokReqOptions& opts,
|
||||
const std::vector<RsGxsGrpMsgIdPair>& msgIds )
|
||||
{ return mTokenService.requestMsgRelatedInfo(token, 0, opts, msgIds); }
|
||||
|
||||
/**
|
||||
* @jsonapi{development}
|
||||
* @param[in] token
|
||||
*/
|
||||
RsTokenService::GxsRequestStatus requestStatus(uint32_t token)
|
||||
{ return mTokenService.requestStatus(token); }
|
||||
|
||||
/// @see RsTokenService::requestServiceStatistic
|
||||
void requestServiceStatistic(uint32_t& token)
|
||||
{ mTokenService.requestServiceStatistic(token); }
|
||||
|
||||
/// @see RsTokenService::requestGroupStatistic
|
||||
void requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId)
|
||||
{ mTokenService.requestGroupStatistic(token, grpId); }
|
||||
|
||||
/// @see RsTokenService::cancelRequest
|
||||
bool cancelRequest(uint32_t token)
|
||||
{ return mTokenService.cancelRequest(token); }
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Token service methods are already exposed by this helper, so you should
|
||||
* not need to get token service pointer directly anymore.
|
||||
*/
|
||||
RS_DEPRECATED RsTokenService* getTokenService() { return &mTokenService; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Block caller while request is being processed.
|
||||
* Useful for blocking API implementation.
|
||||
* @param[in] token token associated to the request caller is waiting for
|
||||
* @param[in] maxWait maximum waiting time in milliseconds
|
||||
*/
|
||||
RsTokenService::GxsRequestStatus waitToken(
|
||||
uint32_t token,
|
||||
std::chrono::milliseconds maxWait = std::chrono::milliseconds(500) )
|
||||
{
|
||||
auto timeout = std::chrono::steady_clock::now() + maxWait;
|
||||
auto st = requestStatus(token);
|
||||
while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE)
|
||||
&& std::chrono::steady_clock::now() < timeout )
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
st = requestStatus(token);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
private:
|
||||
RsGxsIface& mGxs;
|
||||
RsTokenService& mTokenService;
|
||||
};
|
||||
|
||||
#endif // RSGXSIFACEIMPL_H
|
||||
|
@ -119,7 +119,7 @@ struct RsGroupMetaData : RsSerializable
|
||||
|
||||
|
||||
|
||||
struct RsMsgMetaData
|
||||
struct RsMsgMetaData : RsSerializable
|
||||
{
|
||||
RsMsgMetaData() : mPublishTs(0), mMsgFlags(0), mMsgStatus(0), mChildTs(0) {}
|
||||
|
||||
@ -150,6 +150,24 @@ struct RsMsgMetaData
|
||||
time_t mChildTs;
|
||||
std::string mServiceString; // Service Specific Free-Form extra storage.
|
||||
|
||||
/// @see RsSerializable
|
||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mGroupId);
|
||||
RS_SERIAL_PROCESS(mMsgId);
|
||||
RS_SERIAL_PROCESS(mThreadId);
|
||||
RS_SERIAL_PROCESS(mParentId);
|
||||
RS_SERIAL_PROCESS(mOrigMsgId);
|
||||
RS_SERIAL_PROCESS(mAuthorId);
|
||||
RS_SERIAL_PROCESS(mMsgName);
|
||||
RS_SERIAL_PROCESS(mPublishTs);
|
||||
RS_SERIAL_PROCESS(mMsgFlags);
|
||||
RS_SERIAL_PROCESS(mMsgStatus);
|
||||
RS_SERIAL_PROCESS(mChildTs);
|
||||
RS_SERIAL_PROCESS(mServiceString);
|
||||
}
|
||||
|
||||
const std::ostream &print(std::ostream &out, std::string indent = "", std::string varName = "") const {
|
||||
out
|
||||
<< indent << varName << " of RsMsgMetaData Values ###################" << std::endl
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
std::vector<RsGxsTransOutgoingRecord> outgoing_records;
|
||||
};
|
||||
|
||||
RsGxsTrans(RsGxsIface *gxs) : RsGxsIfaceHelper(gxs) {}
|
||||
RsGxsTrans(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
|
||||
|
||||
virtual ~RsGxsTrans() {}
|
||||
|
||||
|
@ -339,7 +339,7 @@ struct RsIdentityDetails : RsSerializable
|
||||
|
||||
struct RsIdentity : RsGxsIfaceHelper
|
||||
{
|
||||
explicit RsIdentity(RsGxsIface *gxs): RsGxsIfaceHelper(gxs) {}
|
||||
explicit RsIdentity(RsGxsIface& gxs): RsGxsIfaceHelper(gxs) {}
|
||||
virtual ~RsIdentity() {}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -43,80 +43,89 @@
|
||||
#include <vector>
|
||||
#include <retroshare/rstypes.h>
|
||||
|
||||
struct RsLoginHelper;
|
||||
|
||||
/**
|
||||
* Pointer to global instance of RsLoginHelper
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
extern RsLoginHelper* rsLoginHelper;
|
||||
|
||||
/*!
|
||||
* Initialisation Class (not publicly disclosed to RsIFace)
|
||||
*/
|
||||
class RsInit
|
||||
{
|
||||
public:
|
||||
/* reorganised RsInit system */
|
||||
public:
|
||||
enum LoadCertificateStatus : uint8_t
|
||||
{
|
||||
OK, /// Everything go as expected, no error occurred
|
||||
ERR_ALREADY_RUNNING, /// Another istance is running already
|
||||
ERR_CANT_ACQUIRE_LOCK, /// Another istance is already running?
|
||||
ERR_UNKOWN /// Unkown error, maybe password is wrong?
|
||||
};
|
||||
|
||||
/*!
|
||||
* PreLogin
|
||||
* Call before init retroshare, initialises rsinitconfig's public attributes
|
||||
*/
|
||||
static void InitRsConfig() ;
|
||||
/* reorganised RsInit system */
|
||||
|
||||
/*!
|
||||
* Should be called to load up ssl cert and private key, and intialises gpg
|
||||
* this must be called before accessing rsserver (e.g. ::startupretroshare)
|
||||
* @param argc passed from executable
|
||||
* @param argv commandline arguments passed to executable
|
||||
* @param strictCheck set to true if you want rs to continue executing if invalid argument passed and vice versa
|
||||
* @return RS_INIT_...
|
||||
*/
|
||||
static int InitRetroShare(int argc, char **argv, bool strictCheck=true);
|
||||
/*!
|
||||
* PreLogin
|
||||
* Call before init retroshare, initialises rsinitconfig's public attributes
|
||||
*/
|
||||
static void InitRsConfig();
|
||||
|
||||
static bool isPortable();
|
||||
static bool isWindowsXP();
|
||||
static bool collectEntropy(uint32_t bytes) ;
|
||||
/*!
|
||||
* Should be called to load up ssl cert and private key, and intialises gpg
|
||||
* this must be called before accessing rsserver (e.g. ::startupretroshare)
|
||||
* @param argc passed from executable
|
||||
* @param argv commandline arguments passed to executable
|
||||
* @param strictCheck set to true if you want rs to continue executing if
|
||||
* invalid argument passed and vice versa
|
||||
* @return RS_INIT_...
|
||||
*/
|
||||
static int InitRetroShare(int argc, char **argv, bool strictCheck=true);
|
||||
|
||||
/*!
|
||||
* Setup Hidden Location;
|
||||
*/
|
||||
static void SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob);
|
||||
static bool isPortable();
|
||||
static bool isWindowsXP();
|
||||
static bool collectEntropy(uint32_t bytes) ;
|
||||
|
||||
static bool LoadPassword(const std::string& passwd) ;
|
||||
/*
|
||||
* Setup Hidden Location;
|
||||
*/
|
||||
static void SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob);
|
||||
|
||||
/*!
|
||||
static bool LoadPassword(const std::string& passwd) ;
|
||||
|
||||
/*
|
||||
* Final Certificate load. This can be called if:
|
||||
* a) InitRetroshare() returns RS_INIT_HAVE_ACCOUNT -> autoLoad/password Set.
|
||||
* b) or LoadPassword()
|
||||
*
|
||||
* This uses the preferredId from RsAccounts.
|
||||
* This wrapper also locks the profile before finalising the login
|
||||
*/
|
||||
static LoadCertificateStatus LockAndLoadCertificates(
|
||||
bool autoLoginNT, std::string& lockFilePath );
|
||||
|
||||
* Final Certificate load. This can be called if:
|
||||
* a) InitRetroshare() returns RS_INIT_HAVE_ACCOUNT -> autoLoad/password Set.
|
||||
* b) or LoadPassword()
|
||||
*
|
||||
* This uses the preferredId from RsAccounts.
|
||||
* This wrapper also locks the profile before finalising the login
|
||||
*/
|
||||
static int LockAndLoadCertificates(bool autoLoginNT, std::string& lockFilePath);
|
||||
// Post Login Options
|
||||
static bool getStartMinimised();
|
||||
|
||||
/*!
|
||||
* Post Login Options
|
||||
*/
|
||||
static int getSslPwdLen();
|
||||
static bool getAutoLogin();
|
||||
static void setAutoLogin(bool autoLogin);
|
||||
static bool RsClearAutoLogin() ;
|
||||
|
||||
static bool getStartMinimised();
|
||||
private:
|
||||
/** @brief Lock profile directory
|
||||
* param[in] accountDir account directory to lock
|
||||
* param[out] lockFilePath path of the created lock-file
|
||||
*/
|
||||
static LoadCertificateStatus LockConfigDirectory(
|
||||
const std::string& accountDir, std::string& lockFilePath);
|
||||
|
||||
static int getSslPwdLen();
|
||||
static bool getAutoLogin();
|
||||
static void setAutoLogin(bool autoLogin);
|
||||
static bool RsClearAutoLogin() ;
|
||||
|
||||
private:
|
||||
|
||||
#if 0
|
||||
/* Auto Login */
|
||||
static bool RsStoreAutoLogin() ;
|
||||
static bool RsTryAutoLogin() ;
|
||||
#endif
|
||||
|
||||
// THESE CAN BE REMOVED FROM THE CLASS TOO.
|
||||
/* Lock/unlock profile directory */
|
||||
static int LockConfigDirectory(const std::string& accountDir, std::string& lockFilePath);
|
||||
static void UnlockConfigDirectory();
|
||||
|
||||
/* The true LoadCertificates() method */
|
||||
static int LoadCertificates(bool autoLoginNT) ;
|
||||
/// @brief Unlock profile directory
|
||||
static void UnlockConfigDirectory();
|
||||
|
||||
static int LoadCertificates(bool autoLoginNT);
|
||||
};
|
||||
|
||||
|
||||
@ -170,7 +179,11 @@ public:
|
||||
|
||||
static bool GetAccountDetails(const RsPeerId &id, RsPgpId &gpgId, std::string &gpgName, std::string &gpgEmail, std::string &location);
|
||||
|
||||
static bool createNewAccount(const RsPgpId& pgp_id, const std::string& org, const std::string& loc, const std::string& country, bool ishiddenloc,bool is_auto_tor, const std::string& passwd, RsPeerId &sslId, std::string &errString);
|
||||
static bool createNewAccount(
|
||||
const RsPgpId& pgp_id, const std::string& org,
|
||||
const std::string& loc, const std::string& country,
|
||||
bool ishiddenloc, bool is_auto_tor, const std::string& passwd,
|
||||
RsPeerId &sslId, std::string &errString );
|
||||
|
||||
static void storeSelectedAccount() ;
|
||||
|
||||
@ -198,6 +211,63 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This helper class have been implemented because there was not reasonable way
|
||||
* to login in the API that could be exposed via JSON API
|
||||
*/
|
||||
struct RsLoginHelper
|
||||
{
|
||||
/**
|
||||
* @brief Normal way to attempt login
|
||||
* @jsonapi{development}
|
||||
* @param[in] account Id of the account to which attempt login
|
||||
* @param[in] password Password for the given account
|
||||
* @return RsInit::OK if login attempt success, error code otherwhise
|
||||
*/
|
||||
RsInit::LoadCertificateStatus attemptLogin(
|
||||
const RsPeerId& account, const std::string& password );
|
||||
|
||||
struct Location : RsSerializable
|
||||
{
|
||||
RsPeerId mLocationId;
|
||||
RsPgpId mPgpId;
|
||||
std::string mLocationName;
|
||||
std::string mPpgName;
|
||||
|
||||
/// @see RsSerializable::serial_process
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx );
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get locations and associated information
|
||||
* @jsonapi{development}
|
||||
* @param[out] locations storage for the retrived locations
|
||||
*/
|
||||
void getLocations(std::vector<RsLoginHelper::Location>& locations);
|
||||
|
||||
/**
|
||||
* @brief Creates a new RetroShare location, and log in once is created
|
||||
* @jsonapi{development}
|
||||
* @param[inout] location provide input information to generate the location
|
||||
* and storage to output the data of the generated location
|
||||
* @param[in] password to protect and unlock the associated PGP key
|
||||
* @param[in] makeHidden pass true to create an hidden location. UNTESTED!
|
||||
* @param[in] makeAutoTor pass true to create an automatically configured
|
||||
* Tor hidden location. UNTESTED!
|
||||
* @param[out] errorMessage if some error occurred human readable error
|
||||
* message
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool createLocation( RsLoginHelper::Location& location,
|
||||
const std::string& password, bool makeHidden,
|
||||
bool makeAutoTor, std::string& errorMessage );
|
||||
|
||||
/**
|
||||
* @brief Close RetroShare session
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
void closeSession();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -92,7 +92,7 @@ const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ( 0x00000010 ) ; // requi
|
||||
|
||||
typedef uint64_t ChatLobbyId ;
|
||||
typedef uint64_t ChatLobbyMsgId ;
|
||||
typedef std::string ChatLobbyNickName ;
|
||||
typedef std::string ChatLobbyNickName ;
|
||||
|
||||
typedef uint64_t MessageId ;
|
||||
|
||||
@ -279,7 +279,7 @@ struct DistantChatPeerInfo
|
||||
|
||||
// Identifier for an chat endpoint like
|
||||
// neighbour peer, distant peer, chatlobby, broadcast
|
||||
class ChatId
|
||||
class ChatId : RsSerializable
|
||||
{
|
||||
public:
|
||||
ChatId();
|
||||
@ -310,17 +310,28 @@ public:
|
||||
// this defines from which peer the status string came from
|
||||
RsPeerId broadcast_status_peer_id;
|
||||
private:
|
||||
enum Type { TYPE_NOT_SET,
|
||||
TYPE_PRIVATE, // private chat with directly connected friend, peer_id is valid
|
||||
TYPE_PRIVATE_DISTANT, // private chat with distant peer, gxs_id is valid
|
||||
TYPE_LOBBY, // chat lobby id, lobby_id is valid
|
||||
TYPE_BROADCAST // message to/from all connected peers
|
||||
};
|
||||
enum Type : uint8_t
|
||||
{ TYPE_NOT_SET,
|
||||
TYPE_PRIVATE, // private chat with directly connected friend, peer_id is valid
|
||||
TYPE_PRIVATE_DISTANT, // private chat with distant peer, gxs_id is valid
|
||||
TYPE_LOBBY, // chat lobby id, lobby_id is valid
|
||||
TYPE_BROADCAST // message to/from all connected peers
|
||||
};
|
||||
|
||||
Type type;
|
||||
RsPeerId peer_id;
|
||||
DistantChatPeerId distant_chat_id;
|
||||
ChatLobbyId lobby_id;
|
||||
|
||||
// RsSerializable interface
|
||||
public:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
|
||||
RS_SERIAL_PROCESS(broadcast_status_peer_id);
|
||||
RS_SERIAL_PROCESS(type);
|
||||
RS_SERIAL_PROCESS(peer_id);
|
||||
RS_SERIAL_PROCESS(distant_chat_id);
|
||||
RS_SERIAL_PROCESS(lobby_id);
|
||||
}
|
||||
};
|
||||
|
||||
class ChatMessage
|
||||
@ -340,49 +351,90 @@ public:
|
||||
//bool system_message;
|
||||
};
|
||||
|
||||
class ChatLobbyInvite
|
||||
class ChatLobbyInvite : RsSerializable
|
||||
{
|
||||
public:
|
||||
ChatLobbyId lobby_id ;
|
||||
RsPeerId peer_id ;
|
||||
std::string lobby_name ;
|
||||
std::string lobby_topic ;
|
||||
ChatLobbyFlags lobby_flags ;
|
||||
public:
|
||||
ChatLobbyId lobby_id ;
|
||||
RsPeerId peer_id ;
|
||||
std::string lobby_name ;
|
||||
std::string lobby_topic ;
|
||||
ChatLobbyFlags lobby_flags ;
|
||||
|
||||
// RsSerializable interface
|
||||
public:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
|
||||
RS_SERIAL_PROCESS(lobby_id);
|
||||
RS_SERIAL_PROCESS(peer_id);
|
||||
RS_SERIAL_PROCESS(lobby_name);
|
||||
RS_SERIAL_PROCESS(lobby_topic);
|
||||
RS_SERIAL_PROCESS(lobby_flags);
|
||||
}
|
||||
};
|
||||
|
||||
class VisibleChatLobbyRecord
|
||||
class VisibleChatLobbyRecord : RsSerializable
|
||||
{
|
||||
public:
|
||||
VisibleChatLobbyRecord(): lobby_id(0), total_number_of_peers(0), last_report_time(0){}
|
||||
|
||||
ChatLobbyId lobby_id ; // unique id of the lobby
|
||||
std::string lobby_name ; // name to use for this lobby
|
||||
std::string lobby_topic ; // topic to use for this lobby
|
||||
std::set<RsPeerId> participating_friends ; // list of direct friend who participate.
|
||||
ChatLobbyId lobby_id ; // unique id of the lobby
|
||||
std::string lobby_name ; // name to use for this lobby
|
||||
std::string lobby_topic ; // topic to use for this lobby
|
||||
std::set<RsPeerId> participating_friends ; // list of direct friend who participate.
|
||||
|
||||
uint32_t total_number_of_peers ; // total number of particpating peers. Might not be
|
||||
time_t last_report_time ; // last time the lobby was reported.
|
||||
ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE
|
||||
uint32_t total_number_of_peers ; // total number of particpating peers. Might not be
|
||||
time_t last_report_time ; // last time the lobby was reported.
|
||||
ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE
|
||||
|
||||
// RsSerializable interface
|
||||
public:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
|
||||
RS_SERIAL_PROCESS(lobby_id);
|
||||
RS_SERIAL_PROCESS(lobby_name);
|
||||
RS_SERIAL_PROCESS(lobby_topic);
|
||||
RS_SERIAL_PROCESS(participating_friends);
|
||||
|
||||
RS_SERIAL_PROCESS(total_number_of_peers);
|
||||
RS_SERIAL_PROCESS(last_report_time);
|
||||
RS_SERIAL_PROCESS(lobby_flags);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ChatLobbyInfo
|
||||
class ChatLobbyInfo : RsSerializable
|
||||
{
|
||||
public:
|
||||
ChatLobbyId lobby_id ; // unique id of the lobby
|
||||
std::string lobby_name ; // name to use for this lobby
|
||||
std::string lobby_topic ; // topic to use for this lobby
|
||||
std::set<RsPeerId> participating_friends ; // list of direct friend who participate. Used to broadcast sent messages.
|
||||
RsGxsId gxs_id ; // ID to sign messages
|
||||
public:
|
||||
ChatLobbyId lobby_id ; // unique id of the lobby
|
||||
std::string lobby_name ; // name to use for this lobby
|
||||
std::string lobby_topic ; // topic to use for this lobby
|
||||
std::set<RsPeerId> participating_friends ; // list of direct friend who participate. Used to broadcast sent messages.
|
||||
RsGxsId gxs_id ; // ID to sign messages
|
||||
|
||||
ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE
|
||||
std::map<RsGxsId,time_t> gxs_ids ; // list of non direct friend who participate. Used to display only.
|
||||
time_t last_activity ; // last recorded activity. Useful for removing dead lobbies.
|
||||
ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE
|
||||
std::map<RsGxsId, time_t> gxs_ids ; // list of non direct friend who participate. Used to display only.
|
||||
time_t last_activity ; // last recorded activity. Useful for removing dead lobbies.
|
||||
|
||||
// RsSerializable interface
|
||||
public:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
|
||||
RS_SERIAL_PROCESS(lobby_id);
|
||||
RS_SERIAL_PROCESS(lobby_name);
|
||||
RS_SERIAL_PROCESS(lobby_topic);
|
||||
RS_SERIAL_PROCESS(participating_friends);
|
||||
RS_SERIAL_PROCESS(gxs_id);
|
||||
|
||||
RS_SERIAL_PROCESS(lobby_flags);
|
||||
RS_SERIAL_PROCESS(gxs_ids);
|
||||
RS_SERIAL_PROCESS(last_activity);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Rs::Msgs::MessageInfo &info);
|
||||
|
||||
class RsMsgs;
|
||||
/**
|
||||
* @brief Pointer to retroshare's message service
|
||||
* @jsonapi{development}
|
||||
*/
|
||||
extern RsMsgs *rsMsgs;
|
||||
|
||||
class RsMsgs
|
||||
@ -438,15 +490,59 @@ virtual bool resetMessageStandardTagTypes(Rs::Msgs::MsgTagType& tags) = 0;
|
||||
// sendChat for broadcast, private, lobby and private distant chat
|
||||
// note: for lobby chat, you first have to subscribe to a lobby
|
||||
// for private distant chat, it is reqired to have an active distant chat session
|
||||
virtual bool sendChat(ChatId id, std::string msg) = 0;
|
||||
virtual uint32_t getMaxMessageSecuritySize(int type) = 0;
|
||||
|
||||
virtual void sendStatusString(const ChatId& id,const std::string& status_string) = 0;
|
||||
virtual void clearChatLobby(const ChatId& id) = 0;
|
||||
/**
|
||||
* @brief sendChat send a chat message to a given id
|
||||
* @jsonapi{development}
|
||||
* @param[in] id id to send the message
|
||||
* @param[in] msg message to send
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool sendChat(ChatId id, std::string msg) = 0;
|
||||
|
||||
virtual void setCustomStateString(const std::string& status_string) = 0 ;
|
||||
virtual std::string getCustomStateString() = 0 ;
|
||||
virtual std::string getCustomStateString(const RsPeerId& peer_id) = 0 ;
|
||||
/**
|
||||
* @brief getMaxMessageSecuritySize get the maximum size of a chta message
|
||||
* @jsonapi{development}
|
||||
* @param[in] type chat type
|
||||
* @return maximum size or zero for infinite
|
||||
*/
|
||||
virtual uint32_t getMaxMessageSecuritySize(int type) = 0;
|
||||
|
||||
/**
|
||||
* @brief sendStatusString send a status string
|
||||
* @jsonapi{development}
|
||||
* @param[in] id chat id to send the status string to
|
||||
* @param[in] status_string status string
|
||||
*/
|
||||
virtual void sendStatusString(const ChatId &id, const std::string &status_string) = 0;
|
||||
|
||||
/**
|
||||
* @brief clearChatLobby clear a chat lobby
|
||||
* @jsonapi{development}
|
||||
* @param[in] id chat lobby id to clear
|
||||
*/
|
||||
virtual void clearChatLobby(const ChatId &id) = 0;
|
||||
|
||||
/**
|
||||
* @brief setCustomStateString set your custom status message
|
||||
* @jsonapi{development}
|
||||
* @param[in] status_string status message
|
||||
*/
|
||||
virtual void setCustomStateString(const std::string &status_string) = 0;
|
||||
|
||||
/**
|
||||
* @brief getCustomStateString get your custom status message
|
||||
* @return status message
|
||||
*/
|
||||
virtual std::string getCustomStateString() = 0;
|
||||
|
||||
/**
|
||||
* @brief getCustomStateString get the custom status message from a peer
|
||||
* @jsonapi{development}
|
||||
* @param[in] peer_id peer id to the peer you want to get the status message from
|
||||
* @return status message
|
||||
*/
|
||||
virtual std::string getCustomStateString(const RsPeerId &peer_id) = 0;
|
||||
|
||||
// get avatar data for peer pid
|
||||
virtual void getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size) = 0 ;
|
||||
@ -454,29 +550,139 @@ virtual void getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size)
|
||||
virtual void setOwnAvatarData(const unsigned char *data,int size) = 0 ;
|
||||
virtual void getOwnAvatarData(unsigned char *& data,int& size) = 0 ;
|
||||
|
||||
/****************************************/
|
||||
/* Chat lobbies */
|
||||
/****************************************/
|
||||
/****************************************/
|
||||
/* Chat lobbies */
|
||||
/****************************************/
|
||||
/**
|
||||
* @brief joinVisibleChatLobby join a lobby that is visible
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_id lobby to join to
|
||||
* @param[in] own_id chat id to use
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool joinVisibleChatLobby(const ChatLobbyId &lobby_id, const RsGxsId &own_id) = 0 ;
|
||||
|
||||
virtual bool joinVisibleChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& own_id) = 0 ;
|
||||
/// get ids of subscribed lobbies
|
||||
virtual void getChatLobbyList(std::list<ChatLobbyId>& cl_list) = 0;
|
||||
/// get lobby info of a subscribed chat lobby. Returns true if lobby id is valid.
|
||||
virtual bool getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& info) = 0 ;
|
||||
/// get info about all lobbies, subscribed and unsubscribed
|
||||
virtual void getListOfNearbyChatLobbies(std::vector<VisibleChatLobbyRecord>& public_lobbies) = 0 ;
|
||||
virtual void invitePeerToLobby(const ChatLobbyId& lobby_id,const RsPeerId& peer_id) = 0;
|
||||
virtual bool acceptLobbyInvite(const ChatLobbyId& id,const RsGxsId& identity) = 0 ;
|
||||
virtual void denyLobbyInvite(const ChatLobbyId& id) = 0 ;
|
||||
virtual void getPendingChatLobbyInvites(std::list<ChatLobbyInvite>& invites) = 0;
|
||||
virtual void unsubscribeChatLobby(const ChatLobbyId& lobby_id) = 0;
|
||||
virtual bool setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& nick) = 0;
|
||||
virtual bool getIdentityForChatLobby(const ChatLobbyId& lobby_id,RsGxsId& nick) = 0 ;
|
||||
virtual bool setDefaultIdentityForChatLobby(const RsGxsId& nick) = 0;
|
||||
virtual void getDefaultIdentityForChatLobby(RsGxsId& id) = 0 ;
|
||||
virtual void setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe) = 0 ;
|
||||
virtual bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id) = 0 ;
|
||||
virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set<RsPeerId>& invited_friends,ChatLobbyFlags lobby_privacy_type) = 0 ;
|
||||
/**
|
||||
* @brief getChatLobbyList get ids of subscribed lobbies
|
||||
* @jsonapi{development}
|
||||
* @param[out] cl_list lobby list
|
||||
*/
|
||||
virtual void getChatLobbyList(std::list<ChatLobbyId> &cl_list) = 0;
|
||||
|
||||
/**
|
||||
* @brief getChatLobbyInfo get lobby info of a subscribed chat lobby. Returns true if lobby id is valid.
|
||||
* @jsonapi{development}
|
||||
* @param[in] id id to get infos from
|
||||
* @param[out] info lobby infos
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool getChatLobbyInfo(const ChatLobbyId &id, ChatLobbyInfo &info) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief getListOfNearbyChatLobbies get info about all lobbies, subscribed and unsubscribed
|
||||
* @jsonapi{development}
|
||||
* @param[out] public_lobbies list of all visible lobbies
|
||||
*/
|
||||
virtual void getListOfNearbyChatLobbies(std::vector<VisibleChatLobbyRecord> &public_lobbies) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief invitePeerToLobby invite a peer to join a lobby
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_id lobby it to invite into
|
||||
* @param[in] peer_id peer to invite
|
||||
*/
|
||||
virtual void invitePeerToLobby(const ChatLobbyId &lobby_id, const RsPeerId &peer_id) = 0;
|
||||
|
||||
/**
|
||||
* @brief acceptLobbyInvite accept a chat invite
|
||||
* @jsonapi{development}
|
||||
* @param[in] id chat lobby id you were invited into and you want to join
|
||||
* @param[in] identity chat identity to use
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool acceptLobbyInvite(const ChatLobbyId &id, const RsGxsId &identity) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief denyLobbyInvite deny a chat lobby invite
|
||||
* @jsonapi{development}
|
||||
* @param[in] id chat lobby id you were invited into
|
||||
*/
|
||||
virtual void denyLobbyInvite(const ChatLobbyId &id) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief getPendingChatLobbyInvites get a list of all pending chat lobby invites
|
||||
* @jsonapi{development}
|
||||
* @param[out] invites list of all pending chat lobby invites
|
||||
*/
|
||||
virtual void getPendingChatLobbyInvites(std::list<ChatLobbyInvite> &invites) = 0;
|
||||
|
||||
/**
|
||||
* @brief unsubscribeChatLobby leave a chat lobby
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_id lobby to leave
|
||||
*/
|
||||
virtual void unsubscribeChatLobby(const ChatLobbyId &lobby_id) = 0;
|
||||
|
||||
/**
|
||||
* @brief setIdentityForChatLobby set the chat identit
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_id lobby to change the chat idnetity for
|
||||
* @param[in] nick new chat identity
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool setIdentityForChatLobby(const ChatLobbyId &lobby_id, const RsGxsId &nick) = 0;
|
||||
|
||||
/**
|
||||
* @brief getIdentityForChatLobby
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_id lobby to get the chat id from
|
||||
* @param[out] nick chat identity
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool getIdentityForChatLobby(const ChatLobbyId &lobby_id, RsGxsId &nick) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief setDefaultIdentityForChatLobby set the default identity used for chat lobbies
|
||||
* @jsonapi{development}
|
||||
* @param[in] nick chat identitiy to use
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool setDefaultIdentityForChatLobby(const RsGxsId &nick) = 0;
|
||||
|
||||
/**
|
||||
* @brief getDefaultIdentityForChatLobby get the default identity used for chat lobbies
|
||||
* @jsonapi{development}
|
||||
* @param[out] id chat identitiy to use
|
||||
*/
|
||||
virtual void getDefaultIdentityForChatLobby(RsGxsId &id) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief setLobbyAutoSubscribe enable or disable auto subscribe for a chat lobby
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_id lobby to auto (un)subscribe
|
||||
* @param[in] autoSubscribe set value for auto subscribe
|
||||
*/
|
||||
virtual void setLobbyAutoSubscribe(const ChatLobbyId &lobby_id, const bool autoSubscribe) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief getLobbyAutoSubscribe get current value of auto subscribe
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_id lobby to get value from
|
||||
* @return wether lobby has auto subscribe enabled or disabled
|
||||
*/
|
||||
virtual bool getLobbyAutoSubscribe(const ChatLobbyId &lobby_id) = 0 ;
|
||||
|
||||
/**
|
||||
* @brief createChatLobby create a new chat lobby
|
||||
* @jsonapi{development}
|
||||
* @param[in] lobby_name lobby name
|
||||
* @param[in] lobby_identity chat id to use for new lobby
|
||||
* @param[in] lobby_topic lobby toppic
|
||||
* @param[in] invited_friends list of friends to invite
|
||||
* @param[in] lobby_privacy_type flag for new chat lobby
|
||||
* @return chat id of new lobby
|
||||
*/
|
||||
virtual ChatLobbyId createChatLobby(const std::string &lobby_name, const RsGxsId &lobby_identity, const std::string &lobby_topic, const std::set<RsPeerId> &invited_friends, ChatLobbyFlags lobby_privacy_type) = 0 ;
|
||||
|
||||
/****************************************/
|
||||
/* Distant chat */
|
||||
|
@ -181,7 +181,7 @@ class RsFeedItem
|
||||
// This mechanism can be used in plugins, new services, etc.
|
||||
//
|
||||
|
||||
class NotifyClient ;
|
||||
class NotifyClient;
|
||||
|
||||
class RsNotify
|
||||
{
|
||||
@ -208,42 +208,41 @@ class RsNotify
|
||||
|
||||
class NotifyClient
|
||||
{
|
||||
public:
|
||||
NotifyClient() {}
|
||||
virtual ~NotifyClient() {}
|
||||
public:
|
||||
NotifyClient() {}
|
||||
virtual ~NotifyClient() {}
|
||||
|
||||
virtual void notifyListPreChange (int /* list */, int /* type */) {}
|
||||
virtual void notifyListChange (int /* list */, int /* type */) {}
|
||||
virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {}
|
||||
virtual void notifyChatMessage (const ChatMessage& /* msg */) {}
|
||||
virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) {}
|
||||
virtual void notifyChatCleared (const ChatId& /* chat_id */) {}
|
||||
virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,const RsGxsId& /* nickname */,const std::string& /* any string */) {}
|
||||
virtual void notifyChatLobbyTimeShift (int /* time_shift*/) {}
|
||||
virtual void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) {}
|
||||
virtual void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) {}
|
||||
virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list<TurtleFileInfo>& /* files */) {}
|
||||
virtual void notifyListPreChange (int /* list */, int /* type */) {}
|
||||
virtual void notifyListChange (int /* list */, int /* type */) {}
|
||||
virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {}
|
||||
virtual void notifyChatMessage (const ChatMessage& /* msg */) {}
|
||||
virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) {}
|
||||
virtual void notifyChatCleared (const ChatId& /* chat_id */) {}
|
||||
virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,const RsGxsId& /* nickname */,const std::string& /* any string */) {}
|
||||
virtual void notifyChatLobbyTimeShift (int /* time_shift*/) {}
|
||||
virtual void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) {}
|
||||
virtual void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) {}
|
||||
virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list<TurtleFileInfo>& /* files */) {}
|
||||
#warning MISSING CODE HERE
|
||||
// virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list<TurtleGxsInfo >& /* groups */) {}
|
||||
virtual void notifyPeerHasNewAvatar (std::string /* peer_id */) {}
|
||||
virtual void notifyOwnAvatarChanged () {}
|
||||
virtual void notifyOwnStatusMessageChanged () {}
|
||||
virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {}
|
||||
virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {}
|
||||
virtual void notifyGxsChange (const RsGxsChanges& /* changes */) {}
|
||||
virtual void notifyConnectionWithoutCert () {}
|
||||
// virtual void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list<TurtleGxsInfo >& /* groups */) {}
|
||||
virtual void notifyPeerHasNewAvatar (std::string /* peer_id */) {}
|
||||
virtual void notifyOwnAvatarChanged () {}
|
||||
virtual void notifyOwnStatusMessageChanged () {}
|
||||
virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {}
|
||||
virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {}
|
||||
virtual void notifyGxsChange (const RsGxsChanges& /* changes */) {}
|
||||
virtual void notifyConnectionWithoutCert () {}
|
||||
|
||||
/* one or more peers has changed the states */
|
||||
virtual void notifyPeerStatusChangedSummary () {}
|
||||
virtual void notifyDiscInfoChanged () {}
|
||||
/* one or more peers has changed the states */
|
||||
virtual void notifyPeerStatusChangedSummary () {}
|
||||
virtual void notifyDiscInfoChanged () {}
|
||||
|
||||
virtual bool askForDeferredSelfSignature (const void * /* data */, const uint32_t /* len */, unsigned char * /* sign */, unsigned int * /* signlen */,int& signature_result , std::string /*reason = ""*/) { signature_result = false ;return true; }
|
||||
virtual void notifyDownloadComplete (const std::string& /* fileHash */) {}
|
||||
virtual void notifyDownloadCompleteCount (uint32_t /* count */) {}
|
||||
virtual void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) {}
|
||||
|
||||
virtual bool askForPassword (const std::string& /* title */, const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */,bool& /* cancelled */ ) { return false ;}
|
||||
virtual bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool /* first_time */) { return false ;}
|
||||
virtual bool askForDeferredSelfSignature (const void * /* data */, const uint32_t /* len */, unsigned char * /* sign */, unsigned int * /* signlen */,int& signature_result , std::string /*reason = ""*/) { signature_result = false ;return true; }
|
||||
virtual void notifyDownloadComplete (const std::string& /* fileHash */) {}
|
||||
virtual void notifyDownloadCompleteCount (uint32_t /* count */) {}
|
||||
virtual void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) {}
|
||||
|
||||
virtual bool askForPassword (const std::string& /* title */, const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */,bool& /* cancelled */ ) { return false ;}
|
||||
virtual bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool /* first_time */) { return false ;}
|
||||
};
|
||||
#endif
|
||||
|
@ -293,16 +293,25 @@ public:
|
||||
std::string cipher_version;
|
||||
};
|
||||
|
||||
class RsGroupInfo
|
||||
class RsGroupInfo : RsSerializable
|
||||
{
|
||||
public:
|
||||
RsGroupInfo();
|
||||
RsGroupInfo();
|
||||
|
||||
RsNodeGroupId id;
|
||||
std::string name;
|
||||
uint32_t flag;
|
||||
RsNodeGroupId id;
|
||||
std::string name;
|
||||
uint32_t flag;
|
||||
|
||||
std::set<RsPgpId> peerIds;
|
||||
std::set<RsPgpId> peerIds;
|
||||
|
||||
// RsSerializable interface
|
||||
public:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
|
||||
RS_SERIAL_PROCESS(id);
|
||||
RS_SERIAL_PROCESS(name);
|
||||
RS_SERIAL_PROCESS(flag);
|
||||
RS_SERIAL_PROCESS(peerIds);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RsPeerDetails &detail);
|
||||
|
@ -74,7 +74,7 @@ class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService
|
||||
//static const uint32_t FLAG_MSGTYPE_POST;
|
||||
//static const uint32_t FLAG_MSGTYPE_MASK;
|
||||
|
||||
explicit RsPosted(RsGxsIface* gxs) : RsGxsIfaceHelper(gxs) {}
|
||||
explicit RsPosted(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
|
||||
virtual ~RsPosted() {}
|
||||
|
||||
/* Specific Service Data */
|
||||
|
@ -119,19 +119,19 @@ class RsTokenService
|
||||
|
||||
public:
|
||||
|
||||
// TODO CLEANUP: This should be an enum
|
||||
static const uint8_t GXS_REQUEST_V2_STATUS_FAILED;
|
||||
static const uint8_t GXS_REQUEST_V2_STATUS_PENDING;
|
||||
static const uint8_t GXS_REQUEST_V2_STATUS_PARTIAL;
|
||||
static const uint8_t GXS_REQUEST_V2_STATUS_FINISHED_INCOMPLETE;
|
||||
static const uint8_t GXS_REQUEST_V2_STATUS_COMPLETE;
|
||||
static const uint8_t GXS_REQUEST_V2_STATUS_DONE; // ONCE ALL DATA RETRIEVED.
|
||||
static const uint8_t GXS_REQUEST_V2_STATUS_CANCELLED;
|
||||
enum GxsRequestStatus : uint8_t
|
||||
{
|
||||
FAILED,
|
||||
PENDING,
|
||||
PARTIAL,
|
||||
COMPLETE,
|
||||
DONE, /// Once all data has been retrived
|
||||
CANCELLED
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
RsTokenService() { return; }
|
||||
virtual ~RsTokenService() { return; }
|
||||
RsTokenService() {}
|
||||
virtual ~RsTokenService() {}
|
||||
|
||||
/* Data Requests */
|
||||
|
||||
@ -195,7 +195,7 @@ public:
|
||||
* @param token value of token to check status for
|
||||
* @return the current status of request
|
||||
*/
|
||||
virtual uint32_t requestStatus(const uint32_t token) = 0;
|
||||
virtual GxsRequestStatus requestStatus(const uint32_t token) = 0;
|
||||
|
||||
/*!
|
||||
* This request statistics on amount of data held
|
||||
@ -216,19 +216,14 @@ public:
|
||||
*/
|
||||
virtual void requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId) = 0;
|
||||
|
||||
|
||||
/* Cancel Request */
|
||||
|
||||
/*!
|
||||
* If this function returns false, it may be that the request has completed
|
||||
* already. Useful for very expensive request. This is a blocking operation
|
||||
* @param token the token of the request to cancel
|
||||
* @return false if unusuccessful in cancelling request, true if successful
|
||||
*/
|
||||
virtual bool cancelRequest(const uint32_t &token) = 0;
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Cancel Request
|
||||
* If this function returns false, it may be that the request has completed
|
||||
* already. Useful for very expensive request.
|
||||
* @param token the token of the request to cancel
|
||||
* @return false if unusuccessful in cancelling request, true if successful
|
||||
*/
|
||||
virtual bool cancelRequest(const uint32_t &token) = 0;
|
||||
};
|
||||
|
||||
#endif // RSTOKENSERVICE_H
|
||||
|
@ -29,24 +29,42 @@
|
||||
#include "serialiser/rstlvbinary.h"
|
||||
#include "retroshare/rstypes.h"
|
||||
#include "retroshare/rsgxsifacetypes.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
|
||||
namespace RsRegularExpression { class LinearizedExpression ; }
|
||||
class RsTurtleClientService ;
|
||||
|
||||
class RsTurtle;
|
||||
extern RsTurtle *rsTurtle ;
|
||||
|
||||
/**
|
||||
* Pointer to global instance of RsTurtle service implementation
|
||||
*/
|
||||
extern RsTurtle* rsTurtle;
|
||||
|
||||
typedef uint32_t TurtleRequestId ;
|
||||
typedef RsPeerId TurtleVirtualPeerId;
|
||||
|
||||
// This is the structure used to send back results of the turtle search
|
||||
// to the notifyBase class, or send info to the GUI.
|
||||
|
||||
struct TurtleFileInfo
|
||||
/**
|
||||
* This is the structure used to send back results of the turtle search,
|
||||
* to other peers, to the notifyBase class, to the search caller or to the GUI.
|
||||
*/
|
||||
struct TurtleFileInfo : RsSerializable
|
||||
{
|
||||
RsFileHash hash ;
|
||||
std::string name ;
|
||||
uint64_t size ;
|
||||
uint64_t size; /// File size
|
||||
RsFileHash hash; /// File hash
|
||||
std::string name; /// File name
|
||||
|
||||
/// @see RsSerializable::serial_process
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(size);
|
||||
RS_SERIAL_PROCESS(hash);
|
||||
|
||||
// Use String TLV serial process for retrocompatibility
|
||||
RsTypeSerializer::serial_process(
|
||||
j, ctx, TLV_TYPE_STR_NAME, name, "name" );
|
||||
}
|
||||
};
|
||||
|
||||
struct TurtleTunnelRequestDisplayInfo
|
||||
@ -90,7 +108,7 @@ class TurtleTrafficStatisticsInfo
|
||||
//
|
||||
class RsTurtle
|
||||
{
|
||||
public:
|
||||
public:
|
||||
RsTurtle() {}
|
||||
virtual ~RsTurtle() {}
|
||||
|
||||
@ -106,7 +124,9 @@ class RsTurtle
|
||||
// the request id, which will be further used by the gui to store results
|
||||
// as they come back.
|
||||
//
|
||||
virtual TurtleRequestId turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service) =0;
|
||||
virtual TurtleRequestId turtleSearch(
|
||||
unsigned char *search_bin_data, uint32_t search_bin_data_len,
|
||||
RsTurtleClientService* client_service ) = 0;
|
||||
|
||||
// Initiates tunnel handling for the given file hash. tunnels. Launches
|
||||
// an exception if an error occurs during the initialization process. The
|
||||
|
@ -65,15 +65,25 @@ const uint32_t RS_CONFIG_DIRECTORY = 0x0002 ;
|
||||
const uint32_t RS_PGP_DIRECTORY = 0x0003 ;
|
||||
const uint32_t RS_DIRECTORY_COUNT = 0x0004 ;
|
||||
|
||||
class TransferInfo
|
||||
struct TransferInfo : RsSerializable
|
||||
{
|
||||
public:
|
||||
/**** Need Some of these Fields ****/
|
||||
RsPeerId peerId;
|
||||
std::string name; /* if has alternative name? */
|
||||
double tfRate; /* kbytes */
|
||||
int status; /* FT_STATE_... */
|
||||
uint64_t transfered ; // used when no chunkmap data is available
|
||||
/**** Need Some of these Fields ****/
|
||||
RsPeerId peerId;
|
||||
std::string name; /* if has alternative name? */
|
||||
double tfRate; /* kbytes */
|
||||
int status; /* FT_STATE_... */
|
||||
uint64_t transfered ; // used when no chunkmap data is available
|
||||
|
||||
/// @see RsSerializable
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RS_SERIAL_PROCESS(peerId);
|
||||
RS_SERIAL_PROCESS(name);
|
||||
RS_SERIAL_PROCESS(tfRate);
|
||||
RS_SERIAL_PROCESS(status);
|
||||
RS_SERIAL_PROCESS(transfered);
|
||||
}
|
||||
};
|
||||
|
||||
enum QueueMove { QUEUE_TOP = 0x00,
|
||||
@ -82,9 +92,11 @@ enum QueueMove { QUEUE_TOP = 0x00,
|
||||
QUEUE_BOTTOM = 0x03
|
||||
};
|
||||
|
||||
enum DwlSpeed { SPEED_LOW = 0x00,
|
||||
SPEED_NORMAL = 0x01,
|
||||
SPEED_HIGH = 0x02
|
||||
enum DwlSpeed : uint8_t
|
||||
{
|
||||
SPEED_LOW = 0x00,
|
||||
SPEED_NORMAL = 0x01,
|
||||
SPEED_HIGH = 0x02
|
||||
};
|
||||
|
||||
|
||||
@ -171,54 +183,76 @@ const FileStorageFlags DIR_FLAGS_PERMISSIONS_MASK ( DIR_FLAGS_ANONYMOUS_DOW
|
||||
const FileStorageFlags DIR_FLAGS_LOCAL ( 0x1000 );
|
||||
const FileStorageFlags DIR_FLAGS_REMOTE ( 0x2000 );
|
||||
|
||||
class FileInfo
|
||||
struct FileInfo : RsSerializable
|
||||
{
|
||||
/* old BaseInfo Entries */
|
||||
public:
|
||||
FileInfo():
|
||||
mId(0), searchId(0), size(0), avail(0), rank(0), age(0),
|
||||
queue_position(0), transfered(0), tfRate(0), downloadStatus(0),
|
||||
priority(SPEED_NORMAL), lastTS(0) {}
|
||||
|
||||
FileInfo() : mId(0), searchId(0), size(0), avail(0), rank(0), age(0), queue_position(0),
|
||||
transfered(0), tfRate(0), downloadStatus(0), priority(SPEED_NORMAL), lastTS(0){}
|
||||
// RsCertId id; /* key for matching everything */
|
||||
/// Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file.
|
||||
FileStorageFlags storage_permission_flags;
|
||||
|
||||
FileStorageFlags storage_permission_flags; // Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file.
|
||||
TransferRequestFlags transfer_info_flags ; // various flags from RS_FILE_HINTS_*
|
||||
/// various flags from RS_FILE_HINTS_*
|
||||
TransferRequestFlags transfer_info_flags;
|
||||
|
||||
/* allow this to be tweaked by the GUI Model */
|
||||
mutable unsigned int mId; /* (GUI) Model Id -> unique number */
|
||||
/** allow this to be tweaked by the GUI Model
|
||||
* (GUI) Model Id -> unique number
|
||||
*/
|
||||
mutable unsigned int mId;
|
||||
|
||||
/* Old FileInfo Entries */
|
||||
public:
|
||||
|
||||
static const int kRsFiStatusNone = 0;
|
||||
static const int kRsFiStatusStall = 1;
|
||||
static const int kRsFiStatusProgress = 2;
|
||||
static const int kRsFiStatusDone = 2;
|
||||
/// 0 if none
|
||||
int searchId;
|
||||
|
||||
/* FileInfo(); */
|
||||
std::string path;
|
||||
std::string fname;
|
||||
RsFileHash hash;
|
||||
std::string ext;
|
||||
|
||||
int searchId; /* 0 if none */
|
||||
std::string path;
|
||||
std::string fname;
|
||||
RsFileHash hash;
|
||||
std::string ext;
|
||||
uint64_t size;
|
||||
uint64_t avail; /// how much we have
|
||||
|
||||
uint64_t size;
|
||||
uint64_t avail; /* how much we have */
|
||||
double rank;
|
||||
int age;
|
||||
uint32_t queue_position;
|
||||
|
||||
double rank;
|
||||
int age;
|
||||
uint32_t queue_position ;
|
||||
/* Transfer Stuff */
|
||||
uint64_t transfered;
|
||||
double tfRate; /// in kbytes
|
||||
uint32_t downloadStatus; /// FT_STATE_DOWNLOADING & co. See rstypes.h
|
||||
std::vector<TransferInfo> peers;
|
||||
|
||||
/* Transfer Stuff */
|
||||
uint64_t transfered;
|
||||
double tfRate; /* in kbytes */
|
||||
uint32_t downloadStatus; // FT_STATE_DOWNLOADING & co. See rstypes.h
|
||||
std::vector<TransferInfo> peers;
|
||||
DwlSpeed priority;
|
||||
time_t lastTS;
|
||||
|
||||
DwlSpeed priority ;
|
||||
time_t lastTS;
|
||||
|
||||
std::list<RsNodeGroupId> parent_groups ;
|
||||
std::list<RsNodeGroupId> parent_groups;
|
||||
|
||||
/// @see RsSerializable
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RS_SERIAL_PROCESS(storage_permission_flags);
|
||||
RS_SERIAL_PROCESS(transfer_info_flags);
|
||||
RS_SERIAL_PROCESS(mId);
|
||||
RS_SERIAL_PROCESS(searchId);
|
||||
RS_SERIAL_PROCESS(path);
|
||||
RS_SERIAL_PROCESS(fname);
|
||||
RS_SERIAL_PROCESS(hash);
|
||||
RS_SERIAL_PROCESS(ext);
|
||||
RS_SERIAL_PROCESS(size);
|
||||
RS_SERIAL_PROCESS(avail);
|
||||
RS_SERIAL_PROCESS(rank);
|
||||
RS_SERIAL_PROCESS(age);
|
||||
RS_SERIAL_PROCESS(queue_position);
|
||||
RS_SERIAL_PROCESS(transfered);
|
||||
RS_SERIAL_PROCESS(tfRate);
|
||||
RS_SERIAL_PROCESS(downloadStatus);
|
||||
RS_SERIAL_PROCESS(peers);
|
||||
RS_SERIAL_PROCESS(priority);
|
||||
RS_SERIAL_PROCESS(lastTS);
|
||||
RS_SERIAL_PROCESS(parent_groups);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const FileInfo& info);
|
||||
@ -268,36 +302,58 @@ class FileDetail
|
||||
|
||||
class CompressedChunkMap ;
|
||||
|
||||
class FileChunksInfo
|
||||
struct FileChunksInfo : RsSerializable
|
||||
{
|
||||
public:
|
||||
enum ChunkState { CHUNK_CHECKING=3, CHUNK_DONE=2, CHUNK_ACTIVE=1, CHUNK_OUTSTANDING=0 } ;
|
||||
enum ChunkStrategy { CHUNK_STRATEGY_STREAMING, CHUNK_STRATEGY_RANDOM, CHUNK_STRATEGY_PROGRESSIVE } ;
|
||||
enum ChunkState : uint8_t
|
||||
{
|
||||
CHUNK_OUTSTANDING = 0,
|
||||
CHUNK_ACTIVE = 1,
|
||||
CHUNK_DONE = 2,
|
||||
CHUNK_CHECKING = 3
|
||||
};
|
||||
|
||||
struct SliceInfo
|
||||
{
|
||||
uint32_t start ;
|
||||
uint32_t size ;
|
||||
RsPeerId peer_id ;
|
||||
};
|
||||
enum ChunkStrategy : uint8_t
|
||||
{
|
||||
CHUNK_STRATEGY_STREAMING,
|
||||
CHUNK_STRATEGY_RANDOM,
|
||||
CHUNK_STRATEGY_PROGRESSIVE
|
||||
};
|
||||
|
||||
uint64_t file_size ; // real size of the file
|
||||
uint32_t chunk_size ; // size of chunks
|
||||
uint32_t strategy ;
|
||||
struct SliceInfo
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
RsPeerId peer_id;
|
||||
};
|
||||
|
||||
// dl state of chunks. Only the last chunk may have size < chunk_size
|
||||
std::vector<ChunkState> chunks ;
|
||||
uint64_t file_size; /// real size of the file
|
||||
uint32_t chunk_size; /// size of chunks
|
||||
ChunkStrategy strategy;
|
||||
|
||||
// For each source peer, gives the compressed bit map of have/don't have sate
|
||||
std::map<RsPeerId, CompressedChunkMap> compressed_peer_availability_maps ;
|
||||
/// dl state of chunks. Only the last chunk may have size < chunk_size
|
||||
std::vector<ChunkState> chunks;
|
||||
|
||||
// For each chunk (by chunk number), gives the completion of the chunk.
|
||||
//
|
||||
std::vector<std::pair<uint32_t,uint32_t> > active_chunks ;
|
||||
/// For each source peer, gives the compressed bit map of have/don't have sate
|
||||
std::map<RsPeerId, CompressedChunkMap> compressed_peer_availability_maps;
|
||||
|
||||
// The list of pending requests, chunk per chunk (by chunk id)
|
||||
//
|
||||
std::map<uint32_t, std::vector<SliceInfo> > pending_slices ;
|
||||
/// For each chunk (by chunk number), gives the completion of the chunk.
|
||||
std::vector<std::pair<uint32_t,uint32_t> > active_chunks;
|
||||
|
||||
/// The list of pending requests, chunk per chunk (by chunk id)
|
||||
std::map<uint32_t, std::vector<SliceInfo> > pending_slices;
|
||||
|
||||
/// @see RsSerializable
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RS_SERIAL_PROCESS(file_size);
|
||||
RS_SERIAL_PROCESS(chunk_size);
|
||||
RS_SERIAL_PROCESS(strategy);
|
||||
RS_SERIAL_PROCESS(chunks);
|
||||
RS_SERIAL_PROCESS(compressed_peer_availability_maps);
|
||||
RS_SERIAL_PROCESS(active_chunks);
|
||||
//RS_SERIAL_PROCESS(pending_slices);
|
||||
}
|
||||
};
|
||||
|
||||
class CompressedChunkMap : public RsSerializable
|
||||
|
@ -111,10 +111,10 @@ std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment);
|
||||
|
||||
class RsWiki: public RsGxsIfaceHelper
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
RsWiki(RsGxsIface *gxs): RsGxsIfaceHelper(gxs) { return; }
|
||||
virtual ~RsWiki() { return; }
|
||||
RsWiki(RsGxsIface& gxs): RsGxsIfaceHelper(gxs) {}
|
||||
virtual ~RsWiki() {}
|
||||
|
||||
/* Specific Service Data */
|
||||
virtual bool getCollections(const uint32_t &token, std::vector<RsWikiCollection> &collections) = 0;
|
||||
|
@ -104,7 +104,7 @@ class RsWire: public RsGxsIfaceHelper
|
||||
{
|
||||
public:
|
||||
|
||||
explicit RsWire(RsGxsIface *gxs): RsGxsIfaceHelper(gxs) {}
|
||||
explicit RsWire(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
|
||||
virtual ~RsWire() {}
|
||||
|
||||
/* Specific Service Data */
|
||||
|
@ -77,7 +77,7 @@ struct RsItem : RsMemoryManagement::SmallObject, RsSerializable
|
||||
inline uint8_t priority_level() const { return _priority_level ;}
|
||||
inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}
|
||||
|
||||
/**
|
||||
/*
|
||||
* TODO: This default implementation should be removed and childs structs
|
||||
* implement ::serial_process(...) as soon as all the codebase is ported to
|
||||
* the new serialization system
|
||||
|
@ -1410,7 +1410,10 @@ bool RsAccounts::GetAccountDetails(const RsPeerId &id,
|
||||
return rsAccounts->getCurrentAccountDetails(id, pgpId, pgpName, pgpEmail, location);
|
||||
}
|
||||
|
||||
bool RsAccounts::createNewAccount(const RsPgpId& pgp_id, const std::string& org, const std::string& loc, const std::string& country, bool ishiddenloc, bool isautotor, const std::string& passwd, RsPeerId &sslId, std::string &errString)
|
||||
bool RsAccounts::createNewAccount(
|
||||
const RsPgpId& pgp_id, const std::string& org, const std::string& loc,
|
||||
const std::string& country, bool ishiddenloc, bool isautotor,
|
||||
const std::string& passwd, RsPeerId &sslId, std::string &errString )
|
||||
{
|
||||
return rsAccounts->GenerateSSLCertificate(pgp_id, org, loc, country, ishiddenloc, isautotor, passwd, sslId, errString);
|
||||
}
|
||||
|
@ -101,7 +101,9 @@ RsDht *rsDht = NULL ;
|
||||
|
||||
//std::map<std::string,std::vector<std::string> > RsInit::unsupported_keys ;
|
||||
|
||||
class RsInitConfig
|
||||
RsLoginHelper* rsLoginHelper;
|
||||
|
||||
class RsInitConfig
|
||||
{
|
||||
public:
|
||||
|
||||
@ -431,7 +433,9 @@ int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
|
||||
AuthSSL::AuthSSLInit();
|
||||
AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL, "");
|
||||
|
||||
int error_code ;
|
||||
rsLoginHelper = new RsLoginHelper;
|
||||
|
||||
int error_code ;
|
||||
|
||||
if(!RsAccounts::init(opt_base_dir,error_code))
|
||||
return error_code ;
|
||||
@ -485,12 +489,21 @@ int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
|
||||
* 1 : Another instance already has the lock
|
||||
* 2 : Unexpected error
|
||||
*/
|
||||
int RsInit::LockConfigDirectory(const std::string& accountDir, std::string& lockFilePath)
|
||||
RsInit::LoadCertificateStatus RsInit::LockConfigDirectory(
|
||||
const std::string& accountDir, std::string& lockFilePath )
|
||||
{
|
||||
const std::string lockFile = accountDir + "/" + "lock";
|
||||
lockFilePath = lockFile;
|
||||
|
||||
return RsDirUtil::createLockFile(lockFile,rsInitConfig->lockHandle) ;
|
||||
int rt = RsDirUtil::createLockFile(lockFile,rsInitConfig->lockHandle);
|
||||
|
||||
switch (rt)
|
||||
{
|
||||
case 0: return RsInit::OK;
|
||||
case 1: return RsInit::ERR_ALREADY_RUNNING;
|
||||
case 2: return RsInit::ERR_CANT_ACQUIRE_LOCK;
|
||||
default: return RsInit::ERR_UNKOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -522,38 +535,30 @@ bool RsInit::LoadPassword(const std::string& inPwd)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Locks the profile directory and tries to finalize the login procedure
|
||||
*
|
||||
* Return value:
|
||||
* 0 : success
|
||||
* 1 : another instance is already running
|
||||
* 2 : unexpected error while locking
|
||||
* 3 : unexpected error while loading certificates
|
||||
*/
|
||||
int RsInit::LockAndLoadCertificates(bool autoLoginNT, std::string& lockFilePath)
|
||||
RsInit::LoadCertificateStatus RsInit::LockAndLoadCertificates(
|
||||
bool autoLoginNT, std::string& lockFilePath )
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!RsAccounts::lockPreferredAccount())
|
||||
throw 3; // invalid PreferredAccount.
|
||||
throw RsInit::ERR_UNKOWN; // invalid PreferredAccount.
|
||||
|
||||
// Logic that used to be external to RsInit...
|
||||
RsPeerId accountId;
|
||||
if (!RsAccounts::GetPreferredAccountId(accountId))
|
||||
throw 3; // invalid PreferredAccount;
|
||||
throw RsInit::ERR_UNKOWN; // invalid PreferredAccount;
|
||||
|
||||
RsPgpId pgpId;
|
||||
std::string pgpName, pgpEmail, location;
|
||||
|
||||
if(!RsAccounts::GetAccountDetails(accountId, pgpId, pgpName, pgpEmail, location))
|
||||
throw 3; // invalid PreferredAccount;
|
||||
throw RsInit::ERR_UNKOWN; // invalid PreferredAccount;
|
||||
|
||||
if(0 == AuthGPG::getAuthGPG() -> GPGInit(pgpId))
|
||||
throw 3; // PGP Error.
|
||||
throw RsInit::ERR_UNKOWN; // PGP Error.
|
||||
|
||||
int retVal = LockConfigDirectory(RsAccounts::AccountDirectory(), lockFilePath);
|
||||
LoadCertificateStatus retVal =
|
||||
LockConfigDirectory(RsAccounts::AccountDirectory(), lockFilePath);
|
||||
|
||||
if(retVal > 0)
|
||||
throw retVal ;
|
||||
@ -561,12 +566,12 @@ int RsInit::LockAndLoadCertificates(bool autoLoginNT, std::string& lockFilePath
|
||||
if(LoadCertificates(autoLoginNT) != 1)
|
||||
{
|
||||
UnlockConfigDirectory();
|
||||
throw 3;
|
||||
throw RsInit::ERR_UNKOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return RsInit::OK;
|
||||
}
|
||||
catch(int retVal)
|
||||
catch(LoadCertificateStatus retVal)
|
||||
{
|
||||
RsAccounts::unlockPreferredAccount();
|
||||
return retVal ;
|
||||
@ -1929,3 +1934,89 @@ int RsServer::StartupRetroShare()
|
||||
return 1;
|
||||
}
|
||||
|
||||
RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin(
|
||||
const RsPeerId& account, const std::string& password)
|
||||
{
|
||||
if(!rsNotify->cachePgpPassphrase(password)) return RsInit::ERR_UNKOWN;
|
||||
if(!rsNotify->setDisableAskPassword(true)) return RsInit::ERR_UNKOWN;
|
||||
if(!RsAccounts::SelectAccount(account)) return RsInit::ERR_UNKOWN;
|
||||
std::string _ignore_lockFilePath;
|
||||
RsInit::LoadCertificateStatus ret =
|
||||
RsInit::LockAndLoadCertificates(false, _ignore_lockFilePath);
|
||||
if(!rsNotify->setDisableAskPassword(false)) return RsInit::ERR_UNKOWN;
|
||||
if(!rsNotify->clearPgpPassphrase()) return RsInit::ERR_UNKOWN;
|
||||
if(ret != RsInit::OK) return ret;
|
||||
if(RsControl::instance()->StartupRetroShare() == 1) return RsInit::OK;
|
||||
return RsInit::ERR_UNKOWN;
|
||||
}
|
||||
|
||||
void RsLoginHelper::getLocations(std::vector<RsLoginHelper::Location>& store)
|
||||
{
|
||||
std::list<RsPeerId> locIds;
|
||||
RsAccounts::GetAccountIds(locIds);
|
||||
store.clear();
|
||||
|
||||
for(const RsPeerId& locId : locIds )
|
||||
{
|
||||
Location l; l.mLocationId = locId;
|
||||
std::string discardPgpMail;
|
||||
RsAccounts::GetAccountDetails( locId, l.mPgpId, l.mPpgName,
|
||||
discardPgpMail, l.mLocationName );
|
||||
store.push_back(l);
|
||||
}
|
||||
}
|
||||
|
||||
bool RsLoginHelper::createLocation(
|
||||
RsLoginHelper::Location& l, const std::string& password,
|
||||
bool makeHidden, bool makeAutoTor, std::string& errorMessage )
|
||||
{
|
||||
if(l.mLocationName.empty())
|
||||
{
|
||||
errorMessage = "Location name is needed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(l.mPgpId.isNull() && l.mPpgName.empty())
|
||||
{
|
||||
errorMessage = "Either PGP name or PGP id is needed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(l.mPgpId.isNull() && !RsAccounts::GeneratePGPCertificate(
|
||||
l.mPpgName, "", password, l.mPgpId, 4096, errorMessage) )
|
||||
{
|
||||
errorMessage = "Failure creating PGP key: " + errorMessage;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sslPassword =
|
||||
RSRandom::random_alphaNumericString(RsInit::getSslPwdLen());
|
||||
|
||||
if(!rsNotify->cachePgpPassphrase(password)) return false;
|
||||
if(!rsNotify->setDisableAskPassword(true)) return false;
|
||||
|
||||
bool ret = RsAccounts::createNewAccount(
|
||||
l.mPgpId, "", l.mLocationName, "", makeHidden, makeAutoTor,
|
||||
sslPassword, l.mLocationId, errorMessage );
|
||||
|
||||
ret = ret && RsInit::LoadPassword(sslPassword);
|
||||
ret = ret && RsInit::OK == attemptLogin(l.mLocationId, password);
|
||||
|
||||
rsNotify->setDisableAskPassword(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RsLoginHelper::closeSession()
|
||||
{
|
||||
RsControl::instance()->rsGlobalShutDown();
|
||||
}
|
||||
|
||||
void RsLoginHelper::Location::serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RS_SERIAL_PROCESS(mLocationId);
|
||||
RS_SERIAL_PROCESS(mPgpId);
|
||||
RS_SERIAL_PROCESS(mLocationName);
|
||||
RS_SERIAL_PROCESS(mPpgName);
|
||||
}
|
||||
|
@ -244,9 +244,10 @@ bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string
|
||||
}
|
||||
|
||||
/* check there is space for string */
|
||||
if(len > size || size-len < *offset) // better than if(size < *offset + len) because it avoids integer overflow
|
||||
if(len > size || size-len < *offset) // better than if(size < *offset + len) because it avoids integer overflow
|
||||
{
|
||||
std::cerr << "getRawString() not enough size" << std::endl;
|
||||
std::cerr << "getRawString() not enough size" << std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
uint8_t *buf = &(((uint8_t *) data)[*offset]);
|
||||
|
@ -26,11 +26,13 @@
|
||||
#include "util/rsprint.h"
|
||||
#include "serialiser/rsserializer.h"
|
||||
#include "serialiser/rstypeserializer.h"
|
||||
#include "util/stacktrace.h"
|
||||
|
||||
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_NONE ( 0x0000 );
|
||||
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_CONFIG ( 0x0001 );
|
||||
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE ( 0x0002 );
|
||||
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER ( 0x0004 );
|
||||
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_YIELDING ( 0x0008 );
|
||||
|
||||
RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
|
||||
{
|
||||
@ -240,3 +242,31 @@ RsItem *RsRawSerialiser::deserialise(void *data, uint32_t *pktsize)
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
RsGenericSerializer::SerializeContext::SerializeContext(
|
||||
uint8_t* data, uint32_t size, SerializationFlags flags,
|
||||
RsJson::AllocatorType* allocator ) :
|
||||
mData(data), mSize(size), mOffset(0), mOk(true), mFlags(flags),
|
||||
mJson(rapidjson::kObjectType, allocator)
|
||||
{
|
||||
if(data)
|
||||
{
|
||||
if(size == 0)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " data passed without "
|
||||
<< "size! This make no sense report to developers!"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
}
|
||||
|
||||
if(flags & SERIALIZATION_FLAG_YIELDING)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Attempt to create a "
|
||||
<< "binary serialization context with "
|
||||
<< "SERIALIZATION_FLAG_YIELDING! "
|
||||
<< "This make no sense report to developers!"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,20 +151,14 @@
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#ifdef HAS_RAPIDJSON
|
||||
#include <rapidjson/document.h>
|
||||
#else
|
||||
#include <rapid_json/document.h>
|
||||
#endif // HAS_RAPIDJSON
|
||||
|
||||
#include "retroshare/rsflags.h"
|
||||
#include "serialiser/rsserial.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
#include "util/rsjson.h"
|
||||
|
||||
struct RsItem;
|
||||
|
||||
#define SERIALIZE_ERROR() std::cerr << __PRETTY_FUNCTION__ << " : "
|
||||
|
||||
// This is the base class for serializers.
|
||||
|
||||
class RsSerialType
|
||||
@ -198,8 +192,6 @@ class RsRawSerialiser: public RsSerialType
|
||||
virtual RsItem * deserialise(void *data, uint32_t *size);
|
||||
};
|
||||
|
||||
typedef rapidjson::Document RsJson;
|
||||
|
||||
/// Top class for all services and config serializers.
|
||||
struct RsGenericSerializer : RsSerialType
|
||||
{
|
||||
@ -226,11 +218,9 @@ struct RsGenericSerializer : RsSerialType
|
||||
/** Allow shared allocator usage to avoid costly JSON deepcopy for
|
||||
* nested RsSerializable */
|
||||
SerializeContext(
|
||||
uint8_t *data, uint32_t size,
|
||||
uint8_t* data = nullptr, uint32_t size = 0,
|
||||
SerializationFlags flags = SERIALIZATION_FLAG_NONE,
|
||||
RsJson::AllocatorType* allocator = nullptr) :
|
||||
mData(data), mSize(size), mOffset(0), mOk(true), mFlags(flags),
|
||||
mJson(rapidjson::kObjectType, allocator) {}
|
||||
RsJson::AllocatorType* allocator = nullptr);
|
||||
|
||||
RS_DEPRECATED SerializeContext(
|
||||
uint8_t *data, uint32_t size, SerializationFormat format,
|
||||
@ -261,6 +251,12 @@ struct RsGenericSerializer : RsSerialType
|
||||
static const SerializationFlags SERIALIZATION_FLAG_SIGNATURE; // 0x0002
|
||||
static const SerializationFlags SERIALIZATION_FLAG_SKIP_HEADER; // 0x0004
|
||||
|
||||
/** Used for JSON deserialization in JSON API, it causes the deserialization
|
||||
* to continue even if some field is missing (or incorrect), this way the
|
||||
* API is more user friendly as some methods need just part of the structs
|
||||
* they take as parameters. */
|
||||
static const SerializationFlags SERIALIZATION_FLAG_YIELDING; // 0x0008
|
||||
|
||||
/**
|
||||
* The following functions overload RsSerialType.
|
||||
* They *should not* need to be further overloaded.
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
#include "serialiser/rstlvkeys.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
|
||||
#include "util/radix64.h"
|
||||
#include "util/rsprint.h"
|
||||
|
||||
#include <iomanip>
|
||||
@ -42,7 +42,8 @@
|
||||
//static const uint32_t MAX_SERIALIZED_ARRAY_SIZE = 500 ;
|
||||
static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
|
||||
|
||||
#define SAFE_GET_JSON_V() \
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
# define SAFE_GET_JSON_V() \
|
||||
const char* mName = memberName.c_str(); \
|
||||
bool ret = jDoc.HasMember(mName); \
|
||||
if(!ret) \
|
||||
@ -50,10 +51,16 @@ static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
|
||||
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName \
|
||||
<< "\" not found in JSON:" << std::endl \
|
||||
<< jDoc << std::endl << std::endl; \
|
||||
print_stacktrace(); \
|
||||
return false; \
|
||||
} \
|
||||
rapidjson::Value& v = jDoc[mName]
|
||||
#else // ifdef RSSERIAL_DEBUG
|
||||
# define SAFE_GET_JSON_V() \
|
||||
const char* mName = memberName.c_str(); \
|
||||
bool ret = jDoc.HasMember(mName); \
|
||||
if(!ret) return false; \
|
||||
rapidjson::Value& v = jDoc[mName]
|
||||
#endif // ifdef RSSERIAL_DEBUG
|
||||
|
||||
|
||||
//============================================================================//
|
||||
@ -162,23 +169,23 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const bool &
|
||||
}
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const int32_t& V)
|
||||
{
|
||||
std::cerr << " [int32_t ] " << n << ": " << V << std::endl;
|
||||
std::cerr << " [int32_t ] " << n << ": " << std::to_string(V) << std::endl;
|
||||
}
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const uint8_t & V)
|
||||
{
|
||||
std::cerr << " [uint8_t ] " << n << ": " << V << std::endl;
|
||||
std::cerr << " [uint8_t ] " << n << ": " << std::to_string(V) << std::endl;
|
||||
}
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const uint16_t& V)
|
||||
{
|
||||
std::cerr << " [uint16_t ] " << n << ": " << V << std::endl;
|
||||
std::cerr << " [uint16_t ] " << n << ": " << std::to_string(V) << std::endl;
|
||||
}
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const uint32_t& V)
|
||||
{
|
||||
std::cerr << " [uint32_t ] " << n << ": " << V << std::endl;
|
||||
std::cerr << " [uint32_t ] " << n << ": " << std::to_string(V) << std::endl;
|
||||
}
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const uint64_t& V)
|
||||
{
|
||||
std::cerr << " [uint64_t ] " << n << ": " << V << std::endl;
|
||||
std::cerr << " [uint64_t ] " << n << ": " << std::to_string(V) << std::endl;
|
||||
}
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const time_t& V)
|
||||
{
|
||||
@ -328,6 +335,49 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
uint32_t RsTypeSerializer::serial_size(const double&)
|
||||
{
|
||||
std::cerr << "Binary [de]serialization not implemented yet for double"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::serialize(uint8_t[], uint32_t, uint32_t&, const double&)
|
||||
{
|
||||
std::cerr << "Binary [de]serialization not implemented yet for double"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::deserialize(const uint8_t[], uint32_t, uint32_t&, double&)
|
||||
{
|
||||
std::cerr << "Binary [de]serialization not implemented yet for double"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
void RsTypeSerializer::print_data(const std::string& n, const double& V)
|
||||
{ std::cerr << " [double ] " << n << ": " << V << std::endl; }
|
||||
|
||||
SIMPLE_TO_JSON_DEF(double)
|
||||
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||
double& member, RsJson& jDoc )
|
||||
{
|
||||
SAFE_GET_JSON_V();
|
||||
ret = ret && v.IsDouble();
|
||||
if(ret) member = v.GetDouble();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================//
|
||||
// std::string //
|
||||
@ -596,9 +646,12 @@ bool RsTypeSerializer::to_JSON(
|
||||
rapidjson::Value key;
|
||||
key.SetString(memberName.c_str(), memberName.length(), allocator);
|
||||
|
||||
std::string encodedValue;
|
||||
Radix64::encode( reinterpret_cast<uint8_t*>(member.first),
|
||||
member.second, encodedValue );
|
||||
|
||||
rapidjson::Value value;
|
||||
const char* tName = typeid(member).name();
|
||||
value.SetString(tName, allocator);
|
||||
value.SetString(encodedValue.data(), allocator);
|
||||
|
||||
jDoc.AddMember(key, value, allocator);
|
||||
|
||||
@ -606,20 +659,27 @@ bool RsTypeSerializer::to_JSON(
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/,
|
||||
RsTypeSerializer::TlvMemBlock_proxy&,
|
||||
RsJson& /*jDoc*/)
|
||||
{ return true; }
|
||||
|
||||
|
||||
//============================================================================//
|
||||
// RsJson std:ostream support //
|
||||
//============================================================================//
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RsJson &jDoc)
|
||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||
RsTypeSerializer::TlvMemBlock_proxy& member,
|
||||
RsJson& jDoc)
|
||||
{
|
||||
rapidjson::StringBuffer buffer; buffer.Clear();
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
|
||||
jDoc.Accept(writer);
|
||||
return out << buffer.GetString();
|
||||
SAFE_GET_JSON_V();
|
||||
ret = ret && v.IsString();
|
||||
if(ret)
|
||||
{
|
||||
std::string encodedValue = v.GetString();
|
||||
std::vector<uint8_t> decodedValue = Radix64::decode(encodedValue);
|
||||
member.second = decodedValue.size();
|
||||
|
||||
if(member.second == 0)
|
||||
{
|
||||
member.first = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
member.first = rs_malloc(member.second);
|
||||
ret = ret && member.first &&
|
||||
memcpy(member.first, decodedValue.data(), member.second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -31,18 +31,14 @@
|
||||
|
||||
#include "serialiser/rsserializer.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "util/rsjson.h"
|
||||
|
||||
#ifdef HAS_RAPIDJSON
|
||||
#include <rapidjson/document.h>
|
||||
#else
|
||||
#include <rapid_json/document.h>
|
||||
#endif // HAS_RAPIDJSON
|
||||
#include <typeinfo> // for typeid
|
||||
#include <type_traits>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
|
||||
/* INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
|
||||
* Can't use a template function because T is needed for const_cast */
|
||||
#define RsTypeSerializer_PRIVATE_TO_JSON_ARRAY() do \
|
||||
{ \
|
||||
@ -58,9 +54,7 @@
|
||||
{ \
|
||||
/* Use same allocator to avoid deep copy */\
|
||||
RsGenericSerializer::SerializeContext elCtx(\
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,\
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,\
|
||||
&allocator );\
|
||||
nullptr, 0, ctx.mFlags, &allocator );\
|
||||
\
|
||||
/* If el is const the default serial_process template is matched */ \
|
||||
/* also when specialization is necessary so the compilation break */ \
|
||||
@ -78,7 +72,7 @@
|
||||
ctx.mJson.AddMember(arrKey, arr, allocator);\
|
||||
} while (false)
|
||||
|
||||
/** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
|
||||
/* INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
|
||||
* Can't use a template function because std::{vector,list,set}<T> has different
|
||||
* name for insert/push_back function
|
||||
*/
|
||||
@ -86,7 +80,7 @@
|
||||
{\
|
||||
using namespace rapidjson;\
|
||||
\
|
||||
bool& ok(ctx.mOk);\
|
||||
bool ok = ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;\
|
||||
Document& jDoc(ctx.mJson);\
|
||||
Document::AllocatorType& allocator = jDoc.GetAllocator();\
|
||||
\
|
||||
@ -100,23 +94,28 @@
|
||||
{\
|
||||
for (auto&& arrEl : jDoc[arrKey].GetArray())\
|
||||
{\
|
||||
Value arrKeyT;\
|
||||
arrKeyT.SetString(memberName.c_str(), memberName.length());\
|
||||
\
|
||||
RsGenericSerializer::SerializeContext elCtx(\
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,\
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,\
|
||||
&allocator );\
|
||||
elCtx.mJson.AddMember(arrKey, arrEl, allocator);\
|
||||
nullptr, 0, ctx.mFlags, &allocator );\
|
||||
elCtx.mJson.AddMember(arrKeyT, arrEl, allocator);\
|
||||
\
|
||||
T el;\
|
||||
serial_process(j, elCtx, el, memberName); \
|
||||
ok = ok && elCtx.mOk;\
|
||||
\
|
||||
ctx.mOk &= ok;\
|
||||
if(ok) v.INSERT_FUN(el);\
|
||||
else break;\
|
||||
}\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
ctx.mOk = false;\
|
||||
}\
|
||||
\
|
||||
} while(false)
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RsJson &jDoc);
|
||||
|
||||
struct RsTypeSerializer
|
||||
{
|
||||
@ -134,8 +133,8 @@ struct RsTypeSerializer
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_same<RsTlvItem,T>::value || !(std::is_base_of<RsSerializable,T>::value || std::is_enum<T>::value || std::is_base_of<RsTlvItem,T>::value)>::type
|
||||
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
T& member, const std::string& member_name)
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
T& member, const std::string& member_name )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
@ -157,7 +156,8 @@ struct RsTypeSerializer
|
||||
ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson);
|
||||
break;
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
ctx.mOk = ctx.mOk && from_JSON(member_name, member, ctx.mJson);
|
||||
ctx.mOk &= (ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
|
||||
&& from_JSON(member_name, member, ctx.mJson);
|
||||
break;
|
||||
default:
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
||||
@ -195,8 +195,9 @@ struct RsTypeSerializer
|
||||
to_JSON(member_name, type_id, member, ctx.mJson);
|
||||
break;
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
ctx.mOk = ctx.mOk &&
|
||||
from_JSON(member_name, type_id, member, ctx.mJson);
|
||||
ctx.mOk &=
|
||||
(ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
|
||||
&& from_JSON(member_name, type_id, member, ctx.mJson);
|
||||
break;
|
||||
default:
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
||||
@ -288,15 +289,11 @@ struct RsTypeSerializer
|
||||
{
|
||||
// Use same allocator to avoid deep copy
|
||||
RsGenericSerializer::SerializeContext kCtx(
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
|
||||
&allocator );
|
||||
nullptr, 0, ctx.mFlags, &allocator );
|
||||
serial_process<T>(j, kCtx, const_cast<T&>(kv.first), "key");
|
||||
|
||||
RsGenericSerializer::SerializeContext vCtx(
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
|
||||
&allocator );
|
||||
nullptr, 0, ctx.mFlags, &allocator );
|
||||
serial_process<U>(j, vCtx, const_cast<U&>(kv.second), "value");
|
||||
|
||||
if(kCtx.mOk && vCtx.mOk)
|
||||
@ -317,7 +314,7 @@ struct RsTypeSerializer
|
||||
{
|
||||
using namespace rapidjson;
|
||||
|
||||
bool& ok(ctx.mOk);
|
||||
bool ok = ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;
|
||||
Document& jDoc(ctx.mJson);
|
||||
Document::AllocatorType& allocator = jDoc.GetAllocator();
|
||||
|
||||
@ -337,9 +334,7 @@ struct RsTypeSerializer
|
||||
if (!ok) break;
|
||||
|
||||
RsGenericSerializer::SerializeContext kCtx(
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
|
||||
&allocator );
|
||||
nullptr, 0, ctx.mFlags, &allocator );
|
||||
if(ok)
|
||||
kCtx.mJson.AddMember("key", kvEl["key"], allocator);
|
||||
|
||||
@ -347,9 +342,7 @@ struct RsTypeSerializer
|
||||
ok = ok && (serial_process(j, kCtx, key, "key"), kCtx.mOk);
|
||||
|
||||
RsGenericSerializer::SerializeContext vCtx(
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
|
||||
&allocator );
|
||||
nullptr, 0, ctx.mFlags, &allocator );
|
||||
if(ok)
|
||||
vCtx.mJson.AddMember("value", kvEl["value"], allocator);
|
||||
|
||||
@ -357,14 +350,102 @@ struct RsTypeSerializer
|
||||
ok = ok && ( serial_process(j, vCtx, value, "value"),
|
||||
vCtx.mOk );
|
||||
|
||||
ctx.mOk &= ok;
|
||||
if(ok) v.insert(std::pair<T,U>(key,value));
|
||||
else break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.mOk = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
||||
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
|
||||
<< std::endl;
|
||||
exit(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/// std::pair<T,U>
|
||||
template<typename T, typename U>
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
std::pair<T,U>& p,
|
||||
const std::string& memberName )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough
|
||||
case RsGenericSerializer::DESERIALIZE: // fallthrough
|
||||
case RsGenericSerializer::SERIALIZE: // fallthrough
|
||||
case RsGenericSerializer::PRINT:
|
||||
serial_process(j, ctx, p.first, "pair::first");
|
||||
serial_process(j, ctx, p.second, "pair::second");
|
||||
break;
|
||||
case RsGenericSerializer::TO_JSON:
|
||||
{
|
||||
RsJson& jDoc(ctx.mJson);
|
||||
RsJson::AllocatorType& allocator = jDoc.GetAllocator();
|
||||
|
||||
// Reuse allocator to avoid deep copy later
|
||||
RsGenericSerializer::SerializeContext lCtx(
|
||||
nullptr, 0, ctx.mFlags, &allocator );
|
||||
|
||||
serial_process(j, ctx, p.first, "first");
|
||||
serial_process(j, ctx, p.second, "second");
|
||||
|
||||
rapidjson::Value key;
|
||||
key.SetString(memberName.c_str(), memberName.length(), allocator);
|
||||
|
||||
/* Because the passed allocator is reused it doesn't go out of scope
|
||||
* and there is no need of deep copy and we can take advantage of
|
||||
* the much faster rapidjson move semantic */
|
||||
jDoc.AddMember(key, lCtx.mJson, allocator);
|
||||
|
||||
ctx.mOk = ctx.mOk && lCtx.mOk;
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
{
|
||||
RsJson& jDoc(ctx.mJson);
|
||||
const char* mName = memberName.c_str();
|
||||
bool hasMember = jDoc.HasMember(mName);
|
||||
bool yielding = ctx.mFlags &
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;
|
||||
|
||||
if(!hasMember)
|
||||
{
|
||||
if(!yielding)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName
|
||||
<< "\" not found in JSON:" << std::endl
|
||||
<< jDoc << std::endl << std::endl;
|
||||
print_stacktrace();
|
||||
}
|
||||
ctx.mOk = false;
|
||||
break;
|
||||
}
|
||||
|
||||
rapidjson::Value& v = jDoc[mName];
|
||||
|
||||
RsGenericSerializer::SerializeContext lCtx(nullptr, 0, ctx.mFlags);
|
||||
lCtx.mJson.SetObject() = v; // Beware of move semantic!!
|
||||
|
||||
serial_process(j, ctx, p.first, "first");
|
||||
serial_process(j, ctx, p.second, "second");
|
||||
ctx.mOk &= lCtx.mOk;
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
||||
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
|
||||
<< std::endl;
|
||||
exit(EINVAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,10 +485,12 @@ struct RsTypeSerializer
|
||||
case RsGenericSerializer::PRINT:
|
||||
{
|
||||
if(v.empty())
|
||||
std::cerr << " Empty array"<< std::endl;
|
||||
else
|
||||
std::cerr << " Array of " << v.size() << " elements:"
|
||||
std::cerr << " Empty vector \"" << memberName << "\""
|
||||
<< std::endl;
|
||||
else
|
||||
std::cerr << " Vector of " << v.size() << " elements: \""
|
||||
<< memberName << "\"" << std::endl;
|
||||
|
||||
for(uint32_t i=0;i<v.size();++i)
|
||||
{
|
||||
std::cerr << " " ;
|
||||
@ -466,9 +549,12 @@ struct RsTypeSerializer
|
||||
}
|
||||
case RsGenericSerializer::PRINT:
|
||||
{
|
||||
if(v.empty()) std::cerr << " Empty set"<< std::endl;
|
||||
else std::cerr << " Set of " << v.size() << " elements:"
|
||||
<< std::endl;
|
||||
if(v.empty())
|
||||
std::cerr << " Empty set \"" << memberName << "\""
|
||||
<< std::endl;
|
||||
else
|
||||
std::cerr << " Set of " << v.size() << " elements: \""
|
||||
<< memberName << "\"" << std::endl;
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::TO_JSON:
|
||||
@ -519,9 +605,12 @@ struct RsTypeSerializer
|
||||
}
|
||||
case RsGenericSerializer::PRINT:
|
||||
{
|
||||
if(v.empty()) std::cerr << " Empty list"<< std::endl;
|
||||
else std::cerr << " List of " << v.size() << " elements:"
|
||||
<< std::endl;
|
||||
if(v.empty())
|
||||
std::cerr << " Empty list \"" << memberName << "\""
|
||||
<< std::endl;
|
||||
else
|
||||
std::cerr << " List of " << v.size() << " elements: \""
|
||||
<< memberName << "\"" << std::endl;
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::TO_JSON:
|
||||
@ -567,7 +656,9 @@ struct RsTypeSerializer
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
{
|
||||
uint32_t f;
|
||||
ctx.mOk = from_JSON(memberName, f, ctx.mJson);
|
||||
ctx.mOk &=
|
||||
(ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
|
||||
&& from_JSON(memberName, f, ctx.mJson);
|
||||
v = t_RsFlags32<N>(f);
|
||||
break;
|
||||
}
|
||||
@ -624,9 +715,7 @@ struct RsTypeSerializer
|
||||
|
||||
// Reuse allocator to avoid deep copy later
|
||||
RsGenericSerializer::SerializeContext lCtx(
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
|
||||
&allocator );
|
||||
nullptr, 0, ctx.mFlags, &allocator );
|
||||
|
||||
member.serial_process(j, lCtx);
|
||||
|
||||
@ -643,28 +732,32 @@ struct RsTypeSerializer
|
||||
}
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
{
|
||||
rapidjson::Document& jDoc(ctx.mJson);
|
||||
RsJson& jDoc(ctx.mJson);
|
||||
const char* mName = memberName.c_str();
|
||||
ctx.mOk = ctx.mOk && jDoc.HasMember(mName);
|
||||
bool hasMember = jDoc.HasMember(mName);
|
||||
bool yielding = ctx.mFlags &
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;
|
||||
|
||||
if(!ctx.mOk)
|
||||
if(!hasMember)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName
|
||||
<< "\" not found in JSON:" << std::endl
|
||||
<< jDoc << std::endl << std::endl;
|
||||
print_stacktrace();
|
||||
if(!yielding)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName
|
||||
<< "\" not found in JSON:" << std::endl
|
||||
<< jDoc << std::endl << std::endl;
|
||||
print_stacktrace();
|
||||
}
|
||||
ctx.mOk = false;
|
||||
break;
|
||||
}
|
||||
|
||||
rapidjson::Value& v = jDoc[mName];
|
||||
|
||||
RsGenericSerializer::SerializeContext lCtx(
|
||||
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
|
||||
RsGenericSerializer::SerializeContext lCtx(nullptr, 0, ctx.mFlags);
|
||||
lCtx.mJson.SetObject() = v; // Beware of move semantic!!
|
||||
|
||||
member.serial_process(j, lCtx);
|
||||
ctx.mOk = ctx.mOk && lCtx.mOk;
|
||||
ctx.mOk &= lCtx.mOk;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -64,8 +64,13 @@ RsGxsChannels *rsGxsChannels = NULL;
|
||||
/******************* Startup / Tick ******************************************/
|
||||
/********************************************************************************/
|
||||
|
||||
p3GxsChannels::p3GxsChannels(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs)
|
||||
: RsGenExchange(gds, nes, new RsGxsChannelSerialiser(), RS_SERVICE_GXS_TYPE_CHANNELS, gixs, channelsAuthenPolicy()), RsGxsChannels(this), GxsTokenQueue(this)
|
||||
p3GxsChannels::p3GxsChannels(
|
||||
RsGeneralDataService *gds, RsNetworkExchangeService *nes,
|
||||
RsGixs* gixs ) :
|
||||
RsGenExchange( gds, nes, new RsGxsChannelSerialiser(),
|
||||
RS_SERVICE_GXS_TYPE_CHANNELS, gixs, channelsAuthenPolicy() ),
|
||||
RsGxsChannels(static_cast<RsGxsIface&>(*this)), GxsTokenQueue(this),
|
||||
mSearchCallbacksMapMutex("GXS channels search")
|
||||
{
|
||||
// For Dummy Msgs.
|
||||
mGenActive = false;
|
||||
@ -347,8 +352,6 @@ static time_t last_dummy_tick = 0;
|
||||
GxsTokenQueue::checkRequests();
|
||||
|
||||
mCommentService->comment_tick();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::getGroupData(const uint32_t &token, std::vector<RsGxsChannelGroup> &groups)
|
||||
@ -392,10 +395,11 @@ bool p3GxsChannels::getGroupData(const uint32_t &token, std::vector<RsGxsChannel
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::groupShareKeys(const RsGxsGroupId &groupId, std::set<RsPeerId>& peers)
|
||||
bool p3GxsChannels::groupShareKeys(
|
||||
const RsGxsGroupId &groupId, const std::set<RsPeerId>& peers )
|
||||
{
|
||||
RsGenExchange::shareGroupPublishKey(groupId,peers) ;
|
||||
return true ;
|
||||
RsGenExchange::shareGroupPublishKey(groupId,peers);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -992,6 +996,50 @@ void p3GxsChannels::handleResponse(uint32_t token, uint32_t req_type)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Blocking API implementation begin
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool p3GxsChannels::getChannelsSummaries(
|
||||
std::list<RsGroupMetaData>& channels )
|
||||
{
|
||||
uint32_t token;
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_META;
|
||||
if( !requestGroupInfo(token, opts)
|
||||
|| waitToken(token) != RsTokenService::COMPLETE ) return false;
|
||||
return getGroupSummary(token, channels);
|
||||
}
|
||||
|
||||
bool p3GxsChannels::getChannelsInfo(
|
||||
const std::list<RsGxsGroupId>& chanIds,
|
||||
std::vector<RsGxsChannelGroup>& channelsInfo )
|
||||
{
|
||||
uint32_t token;
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
if( !requestGroupInfo(token, opts, chanIds)
|
||||
|| waitToken(token) != RsTokenService::COMPLETE ) return false;
|
||||
return getGroupData(token, channelsInfo);
|
||||
}
|
||||
|
||||
bool p3GxsChannels::getChannelsContent(
|
||||
const std::list<RsGxsGroupId>& chanIds,
|
||||
std::vector<RsGxsChannelPost>& posts,
|
||||
std::vector<RsGxsComment>& comments )
|
||||
{
|
||||
uint32_t token;
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||
if( !requestMsgInfo(token, opts, chanIds)
|
||||
|| waitToken(token) != RsTokenService::COMPLETE ) return false;
|
||||
return getPostData(token, posts, comments);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Blocking API implementation end
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
@ -1234,17 +1282,10 @@ bool p3GxsChannels::createPost(uint32_t &token, RsGxsChannelPost &msg)
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
bool p3GxsChannels::ExtraFileHash(const std::string &path, std::string filename)
|
||||
bool p3GxsChannels::ExtraFileHash(const std::string& path)
|
||||
{
|
||||
/* extract filename */
|
||||
filename = RsDirUtil::getTopDir(path);
|
||||
|
||||
|
||||
TransferRequestFlags flags = RS_FILE_REQ_ANONYMOUS_ROUTING;
|
||||
if(!rsFiles->ExtraFileHash(path, GXSCHANNEL_STOREPERIOD, flags))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return rsFiles->ExtraFileHash(path, GXSCHANNEL_STOREPERIOD, flags);
|
||||
}
|
||||
|
||||
|
||||
@ -1312,14 +1353,14 @@ void p3GxsChannels::dummy_tick()
|
||||
#endif
|
||||
|
||||
uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken);
|
||||
if (status != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if (status != RsTokenService::COMPLETE)
|
||||
{
|
||||
#ifdef GXSCHANNELS_DEBUG
|
||||
std::cerr << "p3GxsChannels::dummy_tick() Status: " << status;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
if (status == RsTokenService::FAILED)
|
||||
{
|
||||
#ifdef GXSCHANNELS_DEBUG
|
||||
std::cerr << "p3GxsChannels::dummy_tick() generateDummyMsgs() FAILED";
|
||||
@ -1518,6 +1559,8 @@ void p3GxsChannels::dummy_tick()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cleanTimedOutSearches();
|
||||
}
|
||||
|
||||
|
||||
@ -1733,4 +1776,60 @@ bool p3GxsChannels::retrieveDistantGroup(const RsGxsGroupId& group_id,RsGxsChann
|
||||
return false ;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::turtleSearchRequest(
|
||||
const std::string& matchString,
|
||||
const std::function<void (const RsGxsGroupSummary&)>& multiCallback,
|
||||
std::time_t maxWait )
|
||||
{
|
||||
if(matchString.empty())
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " match string can't be empty!"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
TurtleRequestId sId = turtleSearchRequest(matchString);
|
||||
|
||||
RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
mSearchCallbacksMap.emplace(
|
||||
sId,
|
||||
std::make_pair(
|
||||
multiCallback,
|
||||
std::chrono::system_clock::now() +
|
||||
std::chrono::seconds(maxWait) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void p3GxsChannels::receiveDistantSearchResults(
|
||||
TurtleRequestId id, const RsGxsGroupId& grpId )
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "(" << id << ", " << grpId << ")"
|
||||
<< std::endl;
|
||||
|
||||
RsGenExchange::receiveDistantSearchResults(id, grpId);
|
||||
RsGxsGroupSummary gs;
|
||||
gs.mGroupId = grpId;
|
||||
netService()->retrieveDistantGroupSummary(grpId, gs);
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
auto cbpt = mSearchCallbacksMap.find(id);
|
||||
if(cbpt != mSearchCallbacksMap.end())
|
||||
cbpt->second.first(gs);
|
||||
} // end RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
}
|
||||
|
||||
void p3GxsChannels::cleanTimedOutSearches()
|
||||
{
|
||||
RS_STACK_MUTEX(mSearchCallbacksMapMutex);
|
||||
auto now = std::chrono::system_clock::now();
|
||||
for( auto cbpt = mSearchCallbacksMap.begin();
|
||||
cbpt != mSearchCallbacksMap.end(); )
|
||||
if(cbpt->second.second <= now)
|
||||
{
|
||||
clearDistantSearchResults(cbpt->first);
|
||||
cbpt = mSearchCallbacksMap.erase(cbpt);
|
||||
}
|
||||
else ++cbpt;
|
||||
}
|
||||
|
@ -54,14 +54,14 @@ class p3GxsChannels: public RsGenExchange, public RsGxsChannels,
|
||||
public GxsTokenQueue, public p3Config,
|
||||
public RsTickEvent /* only needed for testing - remove after */
|
||||
{
|
||||
public:
|
||||
public:
|
||||
p3GxsChannels( RsGeneralDataService* gds, RsNetworkExchangeService* nes,
|
||||
RsGixs* gixs );
|
||||
virtual RsServiceInfo getServiceInfo();
|
||||
|
||||
p3GxsChannels(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs);
|
||||
virtual RsServiceInfo getServiceInfo();
|
||||
virtual void service_tick();
|
||||
|
||||
virtual void service_tick();
|
||||
|
||||
protected:
|
||||
protected:
|
||||
|
||||
|
||||
virtual RsSerialiser* setupSerialiser(); // @see p3Config::setupSerialiser()
|
||||
@ -82,7 +82,7 @@ virtual void notifyChanges(std::vector<RsGxsNotify*>& changes);
|
||||
// Overloaded from RsTickEvent.
|
||||
virtual void handle_event(uint32_t event_type, const std::string &elabel);
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsChannelGroup> &groups);
|
||||
virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &posts, std::vector<RsGxsComment> &cmts);
|
||||
@ -96,7 +96,8 @@ virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &p
|
||||
//virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask);
|
||||
|
||||
//virtual bool groupRestoreKeys(const std::string &groupId);
|
||||
virtual bool groupShareKeys(const RsGxsGroupId &groupId, std::set<RsPeerId>& peers) ;
|
||||
virtual bool groupShareKeys(
|
||||
const RsGxsGroupId &groupId, const std::set<RsPeerId>& peers);
|
||||
|
||||
virtual bool createGroup(uint32_t &token, RsGxsChannelGroup &group);
|
||||
virtual bool createPost(uint32_t &token, RsGxsChannelPost &post);
|
||||
@ -109,6 +110,18 @@ virtual bool getChannelAutoDownload(const RsGxsGroupId &groupid, bool& enabled);
|
||||
virtual bool setChannelDownloadDirectory(const RsGxsGroupId &groupId, const std::string& directory);
|
||||
virtual bool getChannelDownloadDirectory(const RsGxsGroupId &groupId, std::string& directory);
|
||||
|
||||
/// @see RsGxsChannels::turtleSearchRequest
|
||||
virtual bool turtleSearchRequest(const std::string& matchString,
|
||||
const std::function<void (const RsGxsGroupSummary&)>& multiCallback,
|
||||
std::time_t maxWait = 300 );
|
||||
|
||||
/**
|
||||
* Receive results from turtle search @see RsGenExchange @see RsNxsObserver
|
||||
* @see p3turtle::handleSearchResult
|
||||
*/
|
||||
void receiveDistantSearchResults( TurtleRequestId id,
|
||||
const RsGxsGroupId& grpId );
|
||||
|
||||
/* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */
|
||||
virtual bool getCommentData(uint32_t token, std::vector<RsGxsComment> &msgs)
|
||||
{ return mCommentService->getGxsCommentData(token, msgs); }
|
||||
@ -151,15 +164,30 @@ virtual void setMessageProcessedStatus(uint32_t& token, const RsGxsGrpMsgIdPair&
|
||||
virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read);
|
||||
|
||||
// File Interface
|
||||
virtual bool ExtraFileHash(const std::string &path, std::string filename);
|
||||
virtual bool ExtraFileHash(const std::string& path);
|
||||
virtual bool ExtraFileRemove(const RsFileHash &hash);
|
||||
|
||||
protected:
|
||||
|
||||
/// Implementation of @see RsGxsChannels::getChannelsSummaries
|
||||
virtual bool getChannelsSummaries(std::list<RsGroupMetaData>& channels);
|
||||
|
||||
/// Implementation of @see RsGxsChannels::getChannelsInfo
|
||||
virtual bool getChannelsInfo(
|
||||
const std::list<RsGxsGroupId>& chanIds,
|
||||
std::vector<RsGxsChannelGroup>& channelsInfo );
|
||||
|
||||
/// Implementation of @see RsGxsChannels::getChannelContent
|
||||
virtual bool getChannelsContent(
|
||||
const std::list<RsGxsGroupId>& chanIds,
|
||||
std::vector<RsGxsChannelPost>& posts,
|
||||
std::vector<RsGxsComment>& comments );
|
||||
|
||||
protected:
|
||||
// Overloaded from GxsTokenQueue for Request callbacks.
|
||||
virtual void handleResponse(uint32_t token, uint32_t req_type);
|
||||
virtual void handleResponse(uint32_t token, uint32_t req_type);
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
|
||||
static uint32_t channelsAuthenPolicy();
|
||||
|
||||
@ -220,8 +248,20 @@ bool generateGroup(uint32_t &token, std::string groupName);
|
||||
std::vector<ChannelDummyRef> mGenRefs;
|
||||
RsGxsMessageId mGenThreadId;
|
||||
|
||||
p3GxsCommentService *mCommentService;
|
||||
p3GxsCommentService *mCommentService;
|
||||
std::map<RsGxsGroupId,time_t> mKnownChannels;
|
||||
|
||||
/** Store search callbacks with timeout*/
|
||||
std::map<
|
||||
TurtleRequestId,
|
||||
std::pair<
|
||||
std::function<void (const RsGxsGroupSummary&)>,
|
||||
std::chrono::system_clock::time_point >
|
||||
> mSearchCallbacksMap;
|
||||
RsMutex mSearchCallbacksMapMutex;
|
||||
|
||||
/// Cleanup mSearchCallbacksMap
|
||||
void cleanTimedOutSearches();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -107,16 +107,16 @@ RsGxsCircles *rsGxsCircles = NULL;
|
||||
/******************* Startup / Tick ******************************************/
|
||||
/********************************************************************************/
|
||||
|
||||
p3GxsCircles::p3GxsCircles(RsGeneralDataService *gds, RsNetworkExchangeService *nes,
|
||||
p3IdService *identities, PgpAuxUtils *pgpUtils)
|
||||
: RsGxsCircleExchange(gds, nes, new RsGxsCircleSerialiser(),
|
||||
RS_SERVICE_GXS_TYPE_GXSCIRCLE, identities, circleAuthenPolicy()),
|
||||
RsGxsCircles(this), GxsTokenQueue(this), RsTickEvent(),
|
||||
mIdentities(identities),
|
||||
mPgpUtils(pgpUtils),
|
||||
mCircleMtx("p3GxsCircles"),
|
||||
mCircleCache(DEFAULT_MEM_CACHE_SIZE, "GxsCircleCache")
|
||||
|
||||
p3GxsCircles::p3GxsCircles(
|
||||
RsGeneralDataService *gds, RsNetworkExchangeService *nes,
|
||||
p3IdService *identities, PgpAuxUtils *pgpUtils) :
|
||||
RsGxsCircleExchange(
|
||||
gds, nes, new RsGxsCircleSerialiser(), RS_SERVICE_GXS_TYPE_GXSCIRCLE,
|
||||
identities, circleAuthenPolicy() ),
|
||||
RsGxsCircles(static_cast<RsGxsIface&>(*this)), GxsTokenQueue(this),
|
||||
RsTickEvent(), mIdentities(identities), mPgpUtils(pgpUtils),
|
||||
mCircleMtx("p3GxsCircles"),
|
||||
mCircleCache(DEFAULT_MEM_CACHE_SIZE, "GxsCircleCache" )
|
||||
{
|
||||
// Kick off Cache Testing, + Others.
|
||||
//RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD);
|
||||
@ -1653,8 +1653,8 @@ void p3GxsCircles::checkDummyIdData()
|
||||
|
||||
// check the token.
|
||||
uint32_t status = rsIdentity->getTokenService()->requestStatus(mDummyIdToken);
|
||||
if ( (RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == status) ||
|
||||
(RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == status) )
|
||||
if ( (RsTokenService::FAILED == status) ||
|
||||
(RsTokenService::COMPLETE == status) )
|
||||
{
|
||||
std::vector<RsGxsIdGroup> ids;
|
||||
if (!rsIdentity->getGroupData(mDummyIdToken, ids))
|
||||
|
@ -552,24 +552,22 @@ void p3GxsCommentService::load_PendingVoteParent(const uint32_t &token)
|
||||
pit = mPendingVotes.find(parentId);
|
||||
if (pit == mPendingVotes.end())
|
||||
{
|
||||
std::cerr << "p3GxsCommentService::load_PendingVoteParent() ERROR Finding Pending Vote";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << __PRETTY_FUNCTION__
|
||||
<< " ERROR Finding Pending Vote" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
RsGxsVote vote = pit->second.mVote;
|
||||
if (meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK)
|
||||
{
|
||||
std::cerr << "p3GxsCommentService::load_PendingVoteParent() ERROR Already Voted";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "mGroupId: " << meta.mGroupId;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "mMsgId: " << meta.mMsgId;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << __PRETTY_FUNCTION__ << " ERROR Already Voted"
|
||||
<< std::endl
|
||||
<< "mGroupId: " << meta.mGroupId << std::endl
|
||||
<< "mMsgId: " << meta.mMsgId << std::endl;
|
||||
|
||||
pit->second.mStatus = VoteHolder::VOTE_ERROR;
|
||||
uint32_t status = RsTokenService::GXS_REQUEST_V2_STATUS_FAILED;
|
||||
mExchange->updatePublicRequestStatus(pit->second.mReqToken, status);
|
||||
mExchange->updatePublicRequestStatus(
|
||||
pit->second.mReqToken, RsTokenService::FAILED );
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -613,8 +611,8 @@ void p3GxsCommentService::completeInternalVote(uint32_t &token)
|
||||
{
|
||||
if (it->second.mVoteToken == token)
|
||||
{
|
||||
|
||||
uint32_t status = mExchange->getTokenService()->requestStatus(token);
|
||||
RsTokenService::GxsRequestStatus status =
|
||||
mExchange->getTokenService()->requestStatus(token);
|
||||
mExchange->updatePublicRequestStatus(it->second.mReqToken, status);
|
||||
|
||||
#ifdef DEBUG_GXSCOMMON
|
||||
|
@ -51,7 +51,8 @@ p3GxsForums::p3GxsForums( RsGeneralDataService *gds,
|
||||
RsNetworkExchangeService *nes, RsGixs* gixs ) :
|
||||
RsGenExchange( gds, nes, new RsGxsForumSerialiser(),
|
||||
RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy()),
|
||||
RsGxsForums(this), mGenToken(0), mGenActive(false), mGenCount(0)
|
||||
RsGxsForums(static_cast<RsGxsIface&>(*this)), mGenToken(0),
|
||||
mGenActive(false), mGenCount(0)
|
||||
{
|
||||
// Test Data disabled in Repo.
|
||||
//RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD);
|
||||
@ -486,12 +487,12 @@ void p3GxsForums::dummy_tick()
|
||||
std::cerr << std::endl;
|
||||
|
||||
uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken);
|
||||
if (status != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if (status != RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << "p3GxsForums::dummy_tick() Status: " << status;
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
|
||||
if (status == RsTokenService::FAILED)
|
||||
{
|
||||
std::cerr << "p3GxsForums::dummy_tick() generateDummyMsgs() FAILED";
|
||||
std::cerr << std::endl;
|
||||
|
@ -152,12 +152,14 @@ RsIdentity *rsIdentity = NULL;
|
||||
/******************* Startup / Tick ******************************************/
|
||||
/********************************************************************************/
|
||||
|
||||
p3IdService::p3IdService(RsGeneralDataService *gds, RsNetworkExchangeService *nes, PgpAuxUtils *pgpUtils)
|
||||
: RsGxsIdExchange(gds, nes, new RsGxsIdSerialiser(), RS_SERVICE_GXS_TYPE_GXSID, idAuthenPolicy()),
|
||||
RsIdentity(this), GxsTokenQueue(this), RsTickEvent(),
|
||||
mKeyCache(GXSID_MAX_CACHE_SIZE, "GxsIdKeyCache"),
|
||||
mIdMtx("p3IdService"), mNes(nes),
|
||||
mPgpUtils(pgpUtils)
|
||||
p3IdService::p3IdService(
|
||||
RsGeneralDataService *gds, RsNetworkExchangeService *nes,
|
||||
PgpAuxUtils *pgpUtils ) :
|
||||
RsGxsIdExchange( gds, nes, new RsGxsIdSerialiser(),
|
||||
RS_SERVICE_GXS_TYPE_GXSID, idAuthenPolicy() ),
|
||||
RsIdentity(static_cast<RsGxsIface&>(*this)), GxsTokenQueue(this),
|
||||
RsTickEvent(), mKeyCache(GXSID_MAX_CACHE_SIZE, "GxsIdKeyCache"),
|
||||
mIdMtx("p3IdService"), mNes(nes), mPgpUtils(pgpUtils)
|
||||
{
|
||||
mBgSchedule_Mode = 0;
|
||||
mBgSchedule_Active = false;
|
||||
@ -1532,7 +1534,7 @@ bool p3IdService::opinion_handlerequest(uint32_t token)
|
||||
std::cerr << "p3IdService::opinion_handlerequest() ERROR getGroupMeta()";
|
||||
std::cerr << std::endl;
|
||||
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::FAILED);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1542,7 +1544,7 @@ bool p3IdService::opinion_handlerequest(uint32_t token)
|
||||
std::cerr << std::endl;
|
||||
|
||||
// error.
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::FAILED);
|
||||
return false;
|
||||
}
|
||||
RsGroupMetaData &meta = *(groups.begin());
|
||||
@ -1553,7 +1555,7 @@ bool p3IdService::opinion_handlerequest(uint32_t token)
|
||||
std::cerr << std::endl;
|
||||
|
||||
// error.
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED);
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::FAILED);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1588,7 +1590,7 @@ bool p3IdService::opinion_handlerequest(uint32_t token)
|
||||
setGroupServiceString(dummyToken, meta.mGroupId, serviceString);
|
||||
cache_update_if_cached(RsGxsId(meta.mGroupId), serviceString);
|
||||
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE);
|
||||
updatePublicRequestStatus(req.mToken, RsTokenService::COMPLETE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -36,13 +36,12 @@ RsPosted *rsPosted = NULL;
|
||||
/******************* Startup / Tick ******************************************/
|
||||
/********************************************************************************/
|
||||
|
||||
p3Posted::p3Posted(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs)
|
||||
:p3PostBase(gds, nes, gixs, new RsGxsPostedSerialiser(), RS_SERVICE_GXS_TYPE_POSTED),
|
||||
RsPosted(this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p3Posted::p3Posted(
|
||||
RsGeneralDataService *gds, RsNetworkExchangeService *nes,
|
||||
RsGixs* gixs ) :
|
||||
p3PostBase( gds, nes, gixs, new RsGxsPostedSerialiser(),
|
||||
RS_SERVICE_GXS_TYPE_POSTED ),
|
||||
RsPosted(static_cast<RsGxsIface&>(*this)) {}
|
||||
|
||||
const std::string GXS_POSTED_APP_NAME = "gxsposted";
|
||||
const uint16_t GXS_POSTED_APP_MAJOR_VERSION = 1;
|
||||
|
@ -534,7 +534,7 @@ void p3Wiki::dummyTick()
|
||||
|
||||
uint32_t status = RsGenExchange::getTokenService()->requestStatus(mAboutToken);
|
||||
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if (status == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << "p3Wiki::dummyTick() AboutActive, Lines: " << mAboutLines;
|
||||
std::cerr << std::endl;
|
||||
@ -601,7 +601,7 @@ void p3Wiki::dummyTick()
|
||||
|
||||
uint32_t status = RsGenExchange::getTokenService()->requestStatus(mImprovToken);
|
||||
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if (status == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << "p3Wiki::dummyTick() ImprovActive, Lines: " << mImprovLines;
|
||||
std::cerr << std::endl;
|
||||
@ -669,7 +669,7 @@ void p3Wiki::dummyTick()
|
||||
|
||||
uint32_t status = RsGenExchange::getTokenService()->requestStatus(mMarkdownToken);
|
||||
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
if (status == RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << "p3Wiki::dummyTick() MarkdownActive, Lines: " << mMarkdownLines;
|
||||
std::cerr << std::endl;
|
||||
|
@ -1111,7 +1111,7 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item)
|
||||
std::list<std::pair<RsTurtleSearchResultItem*,RsTurtleClientService*> > results_to_notify_off_mutex ;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
||||
RS_STACK_MUTEX(mTurtleMtx);
|
||||
// Find who actually sent the corresponding request.
|
||||
//
|
||||
std::map<TurtleRequestId,TurtleSearchRequestInfo>::iterator it = _search_requests_origins.find(item->request_id) ;
|
||||
@ -1176,7 +1176,7 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item)
|
||||
|
||||
sendItem(fwd_item) ;
|
||||
}
|
||||
}
|
||||
} // mTurtleMtx end
|
||||
|
||||
// now we notify clients off-mutex.
|
||||
|
||||
|
@ -222,55 +222,6 @@ RsTurtleSearchResultItem *RsTurtleGenericSearchResultItem::duplicate() const
|
||||
return sr ;
|
||||
}
|
||||
|
||||
template<> uint32_t RsTypeSerializer::serial_size(const TurtleFileInfo& i)
|
||||
{
|
||||
uint32_t s = 0 ;
|
||||
|
||||
s += 8 ; // size
|
||||
s += i.hash.SIZE_IN_BYTES ;
|
||||
s += GetTlvStringSize(i.name) ;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<> bool RsTypeSerializer::deserialize(const uint8_t data[],uint32_t size,uint32_t& offset,TurtleFileInfo& i)
|
||||
{
|
||||
uint32_t saved_offset = offset ;
|
||||
bool ok = true ;
|
||||
|
||||
ok &= getRawUInt64(data, size, &offset, &i.size); // file size
|
||||
ok &= i.hash.deserialise(data, size, offset); // file hash
|
||||
ok &= GetTlvString(data, size, &offset, TLV_TYPE_STR_NAME, i.name); // file name
|
||||
|
||||
if(!ok)
|
||||
offset = saved_offset ;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
template<> bool RsTypeSerializer::serialize(uint8_t data[],uint32_t size,uint32_t& offset,const TurtleFileInfo& i)
|
||||
{
|
||||
uint32_t saved_offset = offset ;
|
||||
bool ok = true ;
|
||||
|
||||
ok &= setRawUInt64(data, size, &offset, i.size); // file size
|
||||
ok &= i.hash.serialise(data, size, offset); // file hash
|
||||
ok &= SetTlvString(data, size, &offset, TLV_TYPE_STR_NAME, i.name); // file name
|
||||
|
||||
if(!ok)
|
||||
offset = saved_offset ;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const TurtleFileInfo& i)
|
||||
{
|
||||
std::cerr << " [FileInfo ] " << n << " size=" << i.size << " hash=" << i.hash << ", name=" << i.name << std::endl;
|
||||
}
|
||||
|
||||
RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(TurtleFileInfo)
|
||||
RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(TurtleFileInfo)
|
||||
|
||||
void RsTurtleOpenTunnelItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process (j,ctx,file_hash ,"file_hash") ;
|
||||
|
@ -47,6 +47,18 @@ sLibs =
|
||||
mLibs = $$RS_SQL_LIB ssl crypto $$RS_THREAD_LIB $$RS_UPNP_LIB
|
||||
dLibs =
|
||||
|
||||
rs_jsonapi {
|
||||
RS_SRC_PATH=$$system_path($$clean_path($${PWD}/../../))
|
||||
RS_BUILD_PATH=$$system_path($$clean_path($${OUT_PWD}/../../))
|
||||
RESTBED_SRC_PATH=$$system_path($$clean_path($${RS_SRC_PATH}/supportlibs/restbed))
|
||||
RESTBED_BUILD_PATH=$$system_path($$clean_path($${RS_BUILD_PATH}/supportlibs/restbed))
|
||||
|
||||
INCLUDEPATH *= $$system_path($$clean_path($${RESTBED_BUILD_PATH}/include/))
|
||||
QMAKE_LIBDIR *= $$system_path($$clean_path($${RESTBED_BUILD_PATH}/library/))
|
||||
# Using sLibs would fail as librestbed.a is generated at compile-time
|
||||
LIBS *= -L$$system_path($$clean_path($${RESTBED_BUILD_PATH}/library/)) -lrestbed
|
||||
}
|
||||
|
||||
linux-* {
|
||||
mLibs += dl
|
||||
}
|
||||
|
68
libretroshare/src/util/rsjson.cc
Normal file
68
libretroshare/src/util/rsjson.cc
Normal file
@ -0,0 +1,68 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* 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 Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include "util/rsjson.h"
|
||||
|
||||
#ifdef HAS_RAPIDJSON
|
||||
# include <rapidjson/writer.h>
|
||||
# include <rapidjson/stringbuffer.h>
|
||||
# include <rapidjson/prettywriter.h>
|
||||
#else
|
||||
# include <rapid_json/writer.h>
|
||||
# include <rapid_json/stringbuffer.h>
|
||||
# include <rapid_json/prettywriter.h>
|
||||
#endif // HAS_RAPIDJSON
|
||||
|
||||
|
||||
inline int getJsonManipulatorStatePosition()
|
||||
{
|
||||
static int p = std::ios_base::xalloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
std::ostream& compactJSON(std::ostream &out)
|
||||
{
|
||||
out.iword(getJsonManipulatorStatePosition()) = 1;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& prettyJSON(std::ostream &out)
|
||||
{
|
||||
out.iword(getJsonManipulatorStatePosition()) = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &out, const RsJson &jDoc)
|
||||
{
|
||||
rapidjson::StringBuffer buffer; buffer.Clear();
|
||||
if(out.iword(getJsonManipulatorStatePosition()))
|
||||
{
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
jDoc.Accept(writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
|
||||
jDoc.Accept(writer);
|
||||
}
|
||||
|
||||
return out << buffer.GetString();
|
||||
}
|
56
libretroshare/src/util/rsjson.h
Normal file
56
libretroshare/src/util/rsjson.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* 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 Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef HAS_RAPIDJSON
|
||||
# include <rapidjson/document.h>
|
||||
#else
|
||||
# include <rapid_json/document.h>
|
||||
#endif // HAS_RAPIDJSON
|
||||
|
||||
/**
|
||||
* Use this type for JSON documents representations in RetroShare code
|
||||
*/
|
||||
typedef rapidjson::Document RsJson;
|
||||
|
||||
/**
|
||||
* Print out RsJson to a stream, use std::stringstream to get the string
|
||||
* @param[out] out output stream
|
||||
* @param[in] jDoc JSON document to print
|
||||
* @return same output stream passed as out parameter
|
||||
*/
|
||||
std::ostream &operator<<(std::ostream &out, const RsJson &jDoc);
|
||||
|
||||
/**
|
||||
* Stream manipulator to print RsJson in compact format
|
||||
* @param[out] out output stream
|
||||
* @return same output stream passed as out parameter
|
||||
*/
|
||||
std::ostream& compactJSON(std::ostream &out);
|
||||
|
||||
/**
|
||||
* Stream manipulator to print RsJson in human readable format
|
||||
* @param[out] out output stream
|
||||
* @return same output stream passed as out parameter
|
||||
*/
|
||||
std::ostream& prettyJSON(std::ostream &out);
|
@ -2229,11 +2229,11 @@ bool p3FeedReader::waitForToken(uint32_t token)
|
||||
|
||||
while (!mStopped) {
|
||||
uint32_t status = service->requestStatus(token);
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) {
|
||||
if (status == RsTokenService::FAILED) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) {
|
||||
if (status == RsTokenService::COMPLETE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,22 @@
|
||||
#include "api/ApiServerLocal.h"
|
||||
#include "api/RsControlModule.h"
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
# include "jsonapi/jsonapi.h"
|
||||
# include "retroshare/rsiface.h"
|
||||
|
||||
JsonApiServer jas(9092, [](int ec)
|
||||
{
|
||||
RsControl::instance()->rsGlobalShutDown();
|
||||
QCoreApplication::exit(ec);
|
||||
});
|
||||
|
||||
void exitGracefully(int ec) { jas.shutdown(ec); }
|
||||
|
||||
#else // ifdef RS_JSONAPI
|
||||
void exitGracefully(int ec) { QCoreApplication::exit(ec); }
|
||||
#endif // ifdef RS_JSONAPI
|
||||
|
||||
using namespace resource_api;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -40,12 +56,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
signal(SIGINT, &QCoreApplication::exit);
|
||||
signal(SIGTERM, &QCoreApplication::exit);
|
||||
signal(SIGINT, exitGracefully);
|
||||
signal(SIGTERM, exitGracefully);
|
||||
#ifdef SIGBREAK
|
||||
signal(SIGBREAK, &QCoreApplication::exit);
|
||||
#endif // def SIGBREAK
|
||||
signal(SIGBREAK, exitGracefully);
|
||||
#endif // ifdef SIGBREAK
|
||||
|
||||
#ifdef LIBRESAPI_LOCAL_SERVER
|
||||
ApiServer api;
|
||||
RsControlModule ctrl_mod(argc, argv, api.getStateTokenServer(), &api, true);
|
||||
api.addResourceHandler(
|
||||
@ -53,7 +70,6 @@ int main(int argc, char *argv[])
|
||||
dynamic_cast<resource_api::ResourceRouter*>(&ctrl_mod),
|
||||
&resource_api::RsControlModule::handleRequest);
|
||||
|
||||
|
||||
QString sockPath = QDir::homePath() + "/.retroshare";
|
||||
sockPath.append("/libresapi.sock");
|
||||
qDebug() << "Listening on:" << sockPath;
|
||||
@ -64,9 +80,16 @@ int main(int argc, char *argv[])
|
||||
QTimer shouldExitTimer;
|
||||
shouldExitTimer.setTimerType(Qt::VeryCoarseTimer);
|
||||
shouldExitTimer.setInterval(1000);
|
||||
QObject::connect( &shouldExitTimer, &QTimer::timeout, [&](){
|
||||
if(ctrl_mod.processShouldExit()) app.quit(); } );
|
||||
QObject::connect( &shouldExitTimer, &QTimer::timeout, [&]()
|
||||
{ if(ctrl_mod.processShouldExit()) exitGracefully(0); } );
|
||||
shouldExitTimer.start();
|
||||
#else
|
||||
# error retroshare-android-service need CONFIG+=libresapilocalserver to build
|
||||
#endif
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
jas.start();
|
||||
#endif
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "util/HandleRichText.h"
|
||||
#include "util/misc.h"
|
||||
#include "util/rsdir.h"
|
||||
|
||||
#include <retroshare/rsfiles.h>
|
||||
|
||||
@ -449,11 +450,10 @@ void CreateGxsChannelMsg::addAttachment(const std::string &path)
|
||||
}
|
||||
|
||||
FileInfo fInfo;
|
||||
std::string filename;
|
||||
std::string filename = RsDirUtil::getTopDir(path);
|
||||
uint64_t size = 0;
|
||||
RsFileHash hash ;
|
||||
|
||||
rsGxsChannels->ExtraFileHash(path, filename);
|
||||
rsGxsChannels->ExtraFileHash(path);
|
||||
|
||||
// Only path and filename are valid.
|
||||
// Destroyed when fileFrame (this subfileitem) is destroyed
|
||||
|
@ -112,11 +112,11 @@ void GxsForumsFillThread::run()
|
||||
service->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds);
|
||||
|
||||
/* wait for the answer */
|
||||
uint32_t requestStatus = RsTokenService::GXS_REQUEST_V2_STATUS_PENDING;
|
||||
uint32_t requestStatus = RsTokenService::PENDING;
|
||||
while (!wasStopped()) {
|
||||
requestStatus = service->requestStatus(token);
|
||||
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED ||
|
||||
requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) {
|
||||
if (requestStatus == RsTokenService::FAILED ||
|
||||
requestStatus == RsTokenService::COMPLETE) {
|
||||
break;
|
||||
}
|
||||
msleep(100);
|
||||
@ -132,7 +132,7 @@ void GxsForumsFillThread::run()
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) {
|
||||
if (requestStatus == RsTokenService::FAILED) {
|
||||
//#TODO
|
||||
return;
|
||||
}
|
||||
|
@ -22,6 +22,9 @@ resource_api::ApiServerMHD* WebuiPage::apiServerMHD = 0;
|
||||
resource_api::ApiServerLocal* WebuiPage::apiServerLocal = 0;
|
||||
#endif
|
||||
resource_api::RsControlModule* WebuiPage::controlModule = 0;
|
||||
#ifdef RS_JSONAPI
|
||||
JsonApiServer* WebuiPage::jsonApiServer = nullptr;
|
||||
#endif
|
||||
|
||||
WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/)
|
||||
{
|
||||
@ -105,6 +108,11 @@ QString WebuiPage::helpText() const
|
||||
// TODO: LIBRESAPI_LOCAL_SERVER Move in appropriate place
|
||||
#ifdef LIBRESAPI_LOCAL_SERVER
|
||||
apiServerLocal = new resource_api::ApiServerLocal(apiServer, resource_api::ApiServerLocal::serverPath());
|
||||
#endif
|
||||
#ifdef RS_JSONAPI
|
||||
// Use same port of libresapi + 2
|
||||
jsonApiServer = new JsonApiServer(Settings->getWebinterfacePort() + 2);
|
||||
jsonApiServer->start("WebuiPage::jsonApiServer");
|
||||
#endif
|
||||
return ok;
|
||||
}
|
||||
@ -126,6 +134,10 @@ QString WebuiPage::helpText() const
|
||||
delete controlModule;
|
||||
controlModule = 0;
|
||||
}
|
||||
#ifdef RS_JSONAPI
|
||||
delete jsonApiServer;
|
||||
jsonApiServer = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ void WebuiPage::showWebui()
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include <retroshare-gui/configpage.h>
|
||||
#include "ui_WebuiPage.h"
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
# include "jsonapi/jsonapi.h"
|
||||
#endif
|
||||
|
||||
namespace resource_api{
|
||||
class ApiServer;
|
||||
class ApiServerMHD;
|
||||
@ -55,4 +59,7 @@ private:
|
||||
static resource_api::ApiServerLocal* apiServerLocal;
|
||||
#endif
|
||||
static resource_api::RsControlModule* controlModule;
|
||||
#ifdef RS_JSONAPI
|
||||
static JsonApiServer* jsonApiServer;
|
||||
#endif
|
||||
};
|
||||
|
@ -164,8 +164,8 @@ bool TokenQueue::checkForRequest(uint32_t token)
|
||||
{
|
||||
/* check token */
|
||||
uint32_t status = mService->requestStatus(token);
|
||||
return ( (RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == status) ||
|
||||
(RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == status) );
|
||||
return ( (RsTokenService::FAILED == status) ||
|
||||
(RsTokenService::COMPLETE == status) );
|
||||
}
|
||||
|
||||
bool TokenQueue::activeRequestExist(const uint32_t& userType) const
|
||||
|
@ -48,6 +48,11 @@
|
||||
#include "TerminalApiClient.h"
|
||||
#endif
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
# include <csignal>
|
||||
# include "jsonapi/jsonapi.h"
|
||||
#endif // RS_JSONAPI
|
||||
|
||||
/* Basic instructions for running libretroshare as background thread.
|
||||
* ******************************************************************* *
|
||||
* This allows your program to communicate with authenticated peers.
|
||||
@ -60,6 +65,32 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef RS_JSONAPI
|
||||
JsonApiServer* jsonApiServer = nullptr;
|
||||
uint16_t jsonApiPort = 0;
|
||||
|
||||
{
|
||||
argstream jsonApiArgs(argc, argv);
|
||||
jsonApiArgs >> parameter(
|
||||
"jsonApiPort", jsonApiPort, "jsonApiPort",
|
||||
"Enable JSON API on the specified port", false );
|
||||
jsonApiArgs >> help('h', "help", "Display this Help");
|
||||
|
||||
if (jsonApiArgs.helpRequested())
|
||||
std::cerr << jsonApiArgs.usage() << std::endl;
|
||||
}
|
||||
|
||||
if(jsonApiPort)
|
||||
{
|
||||
jsonApiServer = new JsonApiServer( jsonApiPort, [](int /*ec*/)
|
||||
{
|
||||
std::raise(SIGTERM);
|
||||
} );
|
||||
|
||||
jsonApiServer->start("JSON API Server");
|
||||
}
|
||||
#endif // RS_JSONAPI
|
||||
|
||||
#ifdef ENABLE_WEBUI
|
||||
|
||||
std::string docroot = resource_api::getDefaultDocroot();
|
||||
|
@ -134,6 +134,11 @@ rs_macos10.9:CONFIG -= rs_macos10.11
|
||||
rs_macos10.10:CONFIG -= rs_macos10.11
|
||||
rs_macos10.12:CONFIG -= rs_macos10.11
|
||||
|
||||
# To enable JSON API append the following assignation to qmake command line
|
||||
# "CONFIG+=rs_jsonapi"
|
||||
CONFIG *= no_rs_jsonapi
|
||||
rs_jsonapi:CONFIG -= no_rs_jsonapi
|
||||
|
||||
# To disable deep search append the following assignation to qmake command line
|
||||
CONFIG+=no_rs_deep_search
|
||||
CONFIG *= rs_deep_search
|
||||
@ -181,7 +186,7 @@ rs_v07_changes {
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## RetroShare qmake functions goes here as all the rest may use them ###########
|
||||
## RetroShare qmake functions goes here as all the rest may use them. ##########
|
||||
################################################################################
|
||||
|
||||
## Qt versions older the 5 are not supported anymore, check if the user is
|
||||
@ -298,7 +303,12 @@ no_sqlcipher {
|
||||
|
||||
rs_autologin {
|
||||
DEFINES *= RS_AUTOLOGIN
|
||||
warning("You have enabled RetroShare auto-login, this is discouraged. The usage of auto-login on some linux distributions may allow someone having access to your session to steal the SSL keys of your node location and therefore compromise your security")
|
||||
RS_AUTOLOGIN_WARNING_MSG = \
|
||||
You have enabled RetroShare auto-login, this is discouraged. The usage \
|
||||
of auto-login on some linux distributions may allow someone having \
|
||||
access to your session to steal the SSL keys of your node location and \
|
||||
therefore compromise your security
|
||||
warning("$${RS_AUTOLOGIN_WARNING_MSG}")
|
||||
}
|
||||
|
||||
rs_onlyhiddennode {
|
||||
@ -338,6 +348,10 @@ rs_chatserver {
|
||||
DEFINES *= RS_CHATSERVER
|
||||
}
|
||||
|
||||
rs_jsonapi {
|
||||
DEFINES *= RS_JSONAPI
|
||||
}
|
||||
|
||||
rs_deep_search {
|
||||
DEFINES *= RS_DEEP_SEARCH
|
||||
|
||||
|
1
supportlibs/restbed
Submodule
1
supportlibs/restbed
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c27c6726d28c42e2e1b7537ba63eeb23e944789d
|
@ -42,7 +42,7 @@ void GenExchangeTest::pollForToken(uint32_t token, const RsTokReqOptions &opts,
|
||||
Sleep((int) (timeDelta * 1000));
|
||||
#endif
|
||||
|
||||
if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token)))
|
||||
if((RsTokenService::COMPLETE == mTokenService->requestStatus(token)))
|
||||
{
|
||||
switch(opts.mReqType)
|
||||
{
|
||||
@ -81,7 +81,7 @@ void GenExchangeTest::pollForToken(uint32_t token, const RsTokReqOptions &opts,
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token))
|
||||
else if(RsTokenService::FAILED == mTokenService->requestStatus(token))
|
||||
{
|
||||
mTokenService->cancelRequest(token);
|
||||
break;
|
||||
@ -108,12 +108,12 @@ bool GenExchangeTest::pollForMsgAcknowledgement(uint32_t token,
|
||||
Sleep((int) (timeDelta * 1000));
|
||||
#endif
|
||||
|
||||
if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token)))
|
||||
if((RsTokenService::COMPLETE == mTokenService->requestStatus(token)))
|
||||
{
|
||||
mTestService->acknowledgeTokenMsg(token, msgId);
|
||||
return true;
|
||||
}
|
||||
else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token))
|
||||
else if(RsTokenService::FAILED == mTokenService->requestStatus(token))
|
||||
{
|
||||
mTokenService->cancelRequest(token);
|
||||
return false;
|
||||
@ -146,12 +146,12 @@ bool GenExchangeTest::pollForGrpAcknowledgement(uint32_t token,
|
||||
Sleep((int) (timeDelta * 1000));
|
||||
#endif
|
||||
|
||||
if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token)))
|
||||
if((RsTokenService::COMPLETE == mTokenService->requestStatus(token)))
|
||||
{
|
||||
mTestService->acknowledgeTokenGrp(token, grpId);
|
||||
return true;
|
||||
}
|
||||
else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token))
|
||||
else if(RsTokenService::FAILED == mTokenService->requestStatus(token))
|
||||
{
|
||||
mTokenService->cancelRequest(token);
|
||||
return false;
|
||||
|
@ -242,7 +242,7 @@ bool GxsPeerNode::createIdentity(const std::string &name,
|
||||
return false;
|
||||
}
|
||||
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -316,7 +316,7 @@ bool GxsPeerNode::createCircle(const std::string &name,
|
||||
uint32_t token;
|
||||
mGxsCircles->createGroup(token, grp1) ;
|
||||
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -371,7 +371,7 @@ bool GxsPeerNode::createGroup(const std::string &name,
|
||||
return false;
|
||||
}
|
||||
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -402,7 +402,7 @@ bool GxsPeerNode::createMsg(const std::string &msgstr,
|
||||
return false;
|
||||
}
|
||||
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -430,7 +430,7 @@ bool GxsPeerNode::subscribeToGroup(const RsGxsGroupId &groupId, bool subscribe)
|
||||
return false;
|
||||
}
|
||||
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -453,7 +453,7 @@ bool GxsPeerNode::getGroups(std::vector<RsTestGroup> &groups)
|
||||
|
||||
uint32_t token;
|
||||
tokenService->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts);
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -475,7 +475,7 @@ bool GxsPeerNode::getGroupList(std::list<RsGxsGroupId> &groups)
|
||||
|
||||
uint32_t token;
|
||||
tokenService->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts);
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -500,7 +500,7 @@ bool GxsPeerNode::getMsgList(const RsGxsGroupId &id, std::list<RsGxsMessageId> &
|
||||
grpIds.push_back(id);
|
||||
|
||||
tokenService->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, grpIds);
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -533,7 +533,7 @@ bool GxsPeerNode::getIdentities(std::vector<RsGxsIdGroup> &groups)
|
||||
|
||||
uint32_t token;
|
||||
tokenService->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts);
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -553,7 +553,7 @@ bool GxsPeerNode::getIdentitiesList(std::list<RsGxsGroupId> &groups)
|
||||
|
||||
uint32_t token;
|
||||
tokenService->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts);
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -575,7 +575,7 @@ bool GxsPeerNode::getCircles(std::vector<RsGxsCircleGroup> &groups)
|
||||
|
||||
uint32_t token;
|
||||
tokenService->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts);
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
@ -595,7 +595,7 @@ bool GxsPeerNode::getCirclesList(std::list<RsGxsGroupId> &groups)
|
||||
|
||||
uint32_t token;
|
||||
tokenService->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts);
|
||||
while(tokenService->requestStatus(token) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tick();
|
||||
sleep(1);
|
||||
|
@ -118,14 +118,14 @@ TEST(libretroshare_services, DISABLED_GXS_nxs_basic2)
|
||||
uint32_t token2;
|
||||
|
||||
ASSERT_TRUE(testService->submitTestGroup(token1, grp1));
|
||||
while(tokenService->requestStatus(token1) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token1) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tester.tick();
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(testService->submitTestGroup(token2, grp2));
|
||||
while(tokenService->requestStatus(token2) != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE)
|
||||
while(tokenService->requestStatus(token2) != RsTokenService::COMPLETE)
|
||||
{
|
||||
tester.tick();
|
||||
sleep(1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user