Complete GxsChannels JSON API with blocking methods

RsGxsIfaceHelper::requestStatus expose it to JSON API
Implemented RsGxsIfaceHelper::waitToken to wait for GXS operations
RsItem::serial_process fix doxygen warning as it's a comment not documentation
RsTypeSerializer add JSON conversion methods for double [de]serialization not
	implemented yet
RsTypeSerializer_PRIVATE_{FROM,TO}_JSON_ARRAY fix doxygen warning as it's a
	comment not documentation
make GxsChannels::ExtraFileHash a bit more reasonable
jsonapi-generator fix unused variable warning if there is no input or output
	paramethers
jsonapi-generator fix generation for inerithed jsonapi methods
Convert to RsSerializable some Gxs structs for the JSON API
This commit is contained in:
Gioacchino Mazzurco 2018-06-26 13:20:24 +02:00
parent d731b665db
commit 15f39129f1
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
13 changed files with 316 additions and 82 deletions

View File

@ -1,6 +1,5 @@
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "libretroshare"
#OUTPUT_DIRECTORY =
ALIASES += jsonapi{1}="\xmlonly<jsonapi minversion=\"\1\"/>\endxmlonly"

View File

@ -115,9 +115,12 @@ int main(int argc, char *argv[])
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;
QString defFilePath(doxPrefix + refid.split('_')[0] + ".xml");
QFile defFile(defFilePath);
if ( !defFile.open(QIODevice::ReadOnly) ||
!defDoc.setContent(&defFile, &parseError, &line, &column) )
@ -128,7 +131,7 @@ int main(int argc, char *argv[])
}
QDomElement memberdef;
QDomNodeList memberdefs = typeDoc.elementsByTagName("memberdef");
QDomNodeList memberdefs = defDoc.elementsByTagName("memberdef");
for (int k = 0; k < memberdefs.size(); ++k)
{
QDomElement tmpMBD = memberdefs.item(k).toElement();
@ -148,6 +151,8 @@ int main(int argc, char *argv[])
QString retvalType = memberdef.firstChildElement("type").text();
QMap<QString,MethodParam> paramsMap;
QStringList orderedParamNames;
uint hasInput = false;
uint hasOutput = false;
QDomNodeList params = memberdef.elementsByTagName("param");
for (int k = 0; k < params.size(); ++k)
@ -171,10 +176,20 @@ int main(int argc, char *argv[])
QDomElement tmpPN = parameternames.item(k).toElement();
MethodParam& tmpParam = paramsMap[tmpPN.text()];
QString tmpD = tmpPN.attributes().namedItem("direction").nodeValue();
tmpParam.in = tmpD.contains("in");
tmpParam.out = tmpD.contains("out");
if(tmpD.contains("in"))
{
tmpParam.in = true;
hasInput = true;
}
if(tmpD.contains("out"))
{
tmpParam.out = true;
hasOutput = true;
}
}
if(retvalType != "void") hasOutput = true;
qDebug() << instanceName << apiPath << retvalType << typeName
<< methodName;
for (const QString& pn : orderedParamNames)
@ -183,13 +198,25 @@ int main(int argc, char *argv[])
qDebug() << "\t" << mp.type << mp.name << mp.in << mp.out;
}
QString retvalSerialization;
if(retvalType != "void")
retvalSerialization = "\t\t\tRS_SERIAL_PROCESS(retval);";
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;
QString inputParamsDeserialization;
QString outputParamsSerialization;
for (const QString& pn : orderedParamNames)
{
const MethodParam& mp(paramsMap[pn]);
@ -202,13 +229,18 @@ int main(int argc, char *argv[])
+ 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";
QMap<QString,QString> substitutionsMap;
substitutionsMap.insert("instanceName", instanceName);
substitutionsMap.insert("methodName", methodName);
substitutionsMap.insert("paramsDeclaration", paramsDeclaration);
substitutionsMap.insert("inputParamsDeserialization", inputParamsDeserialization);
substitutionsMap.insert("outputParamsSerialization", outputParamsSerialization);
substitutionsMap.insert("retvalSerialization", retvalSerialization);
substitutionsMap.insert("retvalType", retvalType);
substitutionsMap.insert("callParamsList", orderedParamNames.join(", "));
substitutionsMap.insert("wrapperName", wrapperName);

View File

@ -47,22 +47,13 @@ void $%wrapperName%$(const std::shared_ptr<rb::Session> session)
$%paramsDeclaration%$
// deserialize input parameters from JSON
{
RsGenericSerializer::SerializeContext& ctx(cReq);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);
$%inputParamsDeserialization%$
}
// call retroshare C++ API
$%retvalType%$ retval = $%instanceName%$->$%methodName%$($%callParamsList%$);
// serialize out parameters and return value to JSON
{
RsGenericSerializer::SerializeContext& ctx(cAns);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
$%retvalSerialization%$
$%outputParamsSerialization%$
}
// return them to the API caller
std::stringstream ss;

View File

@ -853,7 +853,7 @@ 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}/retroshare/))
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_DEF_FILE=$$system_path($$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-wrappers.cpp))

View File

@ -108,29 +108,83 @@ public:
explicit RsGxsChannels(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
virtual ~RsGxsChannels() {}
/* Specific Service Data */
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;
//Not currently used
//virtual bool getRelatedPosts(const uint32_t &token, std::vector<RsGxsChannelPost> &posts) = 0;
/* From RsGxsCommentService */
//virtual bool getCommentData(const uint32_t &token, std::vector<RsGxsComment> &comments) = 0;
//virtual bool getRelatedComments(const uint32_t &token, std::vector<RsGxsComment> &comments) = 0;
//virtual bool createComment(uint32_t &token, RsGxsComment &comment) = 0;
//virtual bool createVote(uint32_t &token, RsGxsVote &vote) = 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;
/**
* @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;
/**
* Get download directory for the given channel
* @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;
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
@ -139,13 +193,16 @@ virtual bool setChannelDownloadDirectory(const RsGxsGroupId &groupId, const std:
virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId,
std::string& directory ) = 0;
//virtual void setChannelAutoDownload(uint32_t& token, const RsGxsGroupId& groupId, bool autoDownload) = 0;
//virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask);
//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)=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.
@ -197,11 +254,22 @@ virtual bool setChannelDownloadDirectory(const RsGxsGroupId &groupId, const std:
*/
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;
/**
* @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;
};
#endif

View File

@ -94,17 +94,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;
@ -119,6 +125,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");

View File

@ -27,6 +27,9 @@
*
*/
#include <chrono>
#include <thread>
#include "retroshare/rsgxsiface.h"
#include "retroshare/rsreputations.h"
#include "rsgxsflags.h"
@ -259,7 +262,10 @@ struct RsGxsIfaceHelper
const std::vector<RsGxsGrpMsgIdPair>& msgIds )
{ return mTokenService.requestMsgRelatedInfo(token, 0, opts, msgIds); }
/// @see RsTokenService::requestStatus
/**
* @jsonapi{development}
* @param[in] token
*/
RsTokenService::GxsRequestStatus requestStatus(uint32_t token)
{ return mTokenService.requestStatus(token); }
@ -282,6 +288,28 @@ struct RsGxsIfaceHelper
*/
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;

View File

@ -73,7 +73,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

View File

@ -335,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 //

View File

@ -41,7 +41,7 @@
#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 \
{ \
@ -75,7 +75,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
*/

View File

@ -399,10 +399,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;
}
@ -999,6 +1000,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
////////////////////////////////////////////////////////////////////////////////
/********************************************************************************************/
/********************************************************************************************/
@ -1241,17 +1286,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);
}

View File

@ -94,7 +94,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);
@ -149,15 +150,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();

View File

@ -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