mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 00:19:25 -05:00
Implement GXS group base64 public data export
Link to GXS group is a concept that is useful for almost all GXS based services, gen exchange now provides method to facilitate the implementation of group links at service layer. Move waitToken in token service interface.
This commit is contained in:
parent
a9510da61b
commit
6f3d842d30
@ -21,6 +21,7 @@
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "pqi/pqihash.h"
|
||||
#include "rsgenexchange.h"
|
||||
@ -38,8 +39,7 @@
|
||||
#include "rsgxsutil.h"
|
||||
#include "rsserver/p3face.h"
|
||||
#include "retroshare/rsevents.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "util/radix64.h"
|
||||
|
||||
#define PUB_GRP_MASK 0x000f
|
||||
#define RESTR_GRP_MASK 0x00f0
|
||||
@ -3445,6 +3445,71 @@ bool RsGenExchange::localSearch( const std::string& matchString,
|
||||
return mNetService->search(matchString, results);
|
||||
}
|
||||
|
||||
bool RsGenExchange::exportGroupBase64(
|
||||
std::string& radix, const RsGxsGroupId& groupId, std::string& errMsg )
|
||||
{
|
||||
constexpr auto fname = __PRETTY_FUNCTION__;
|
||||
const auto failure = [&](const std::string& err)
|
||||
{
|
||||
errMsg = err;
|
||||
RsErr() << fname << " " << err << std::endl;
|
||||
return false;
|
||||
};
|
||||
|
||||
if(groupId.isNull()) return failure("groupId cannot be null");
|
||||
|
||||
const std::list<RsGxsGroupId> groupIds({groupId});
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
uint32_t token;
|
||||
mDataAccess->requestGroupInfo(
|
||||
token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds);
|
||||
RsTokenService::GxsRequestStatus wtStatus = mDataAccess->waitToken(token);
|
||||
if(wtStatus != RsTokenService::COMPLETE)
|
||||
return failure( "waitToken(...) failed with: " +
|
||||
std::to_string(wtStatus) );
|
||||
|
||||
uint8_t* buf = nullptr;
|
||||
uint32_t size;
|
||||
RsGxsGroupId grpId;
|
||||
if(!getSerializedGroupData(token, grpId, buf, size))
|
||||
return failure("failed retrieving GXS data");
|
||||
|
||||
Radix64::encode(buf, static_cast<int>(size), radix);
|
||||
free(buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsGenExchange::importGroupBase64(
|
||||
const std::string& radix, RsGxsGroupId& groupId,
|
||||
std::string& errMsg )
|
||||
{
|
||||
constexpr auto fname = __PRETTY_FUNCTION__;
|
||||
const auto failure = [&](const std::string& err)
|
||||
{
|
||||
errMsg = err;
|
||||
RsErr() << fname << " " << err << std::endl;
|
||||
return false;
|
||||
};
|
||||
|
||||
if(radix.empty()) return failure("radix is empty");
|
||||
|
||||
std::vector<uint8_t> mem = Radix64::decode(radix);
|
||||
if(mem.empty()) return failure("radix seems corrupted");
|
||||
|
||||
// On success this also import the group as pending validation
|
||||
if(!deserializeGroupData(
|
||||
mem.data(), static_cast<uint32_t>(mem.size()),
|
||||
reinterpret_cast<RsGxsGroupId*>(&groupId) ))
|
||||
return failure("failed deserializing group");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RsGxsChanges::RsGxsChanges() :
|
||||
RsEvent(RsEventType::GXS_CHANGES), mServiceType(RsServiceType::NONE),
|
||||
mService(nullptr) {}
|
||||
|
||||
RsGxsIface::~RsGxsIface() = default;
|
||||
RsGxsGroupSummary::~RsGxsGroupSummary() = default;
|
||||
|
@ -95,7 +95,8 @@ typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsGxsMsgItem*> > GxsMsgRelatedDa
|
||||
|
||||
class RsGixs;
|
||||
|
||||
class RsGenExchange : public RsNxsObserver, public RsTickingThread, public RsGxsIface
|
||||
class RsGenExchange : public RsNxsObserver, public RsTickingThread,
|
||||
public RsGxsIface
|
||||
{
|
||||
public:
|
||||
|
||||
@ -325,6 +326,19 @@ public:
|
||||
bool localSearch( const std::string& matchString,
|
||||
std::list<RsGxsGroupSummary>& results );
|
||||
|
||||
/// @see RsGxsIface
|
||||
bool exportGroupBase64(
|
||||
std::string& radix, const RsGxsGroupId& groupId,
|
||||
std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) override;
|
||||
|
||||
/// @see RsGxsIface
|
||||
bool importGroupBase64(
|
||||
const std::string& radix,
|
||||
RsGxsGroupId& groupId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId),
|
||||
std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) override;
|
||||
|
||||
protected:
|
||||
|
||||
bool messagePublicationTest(const RsGxsMsgMetaData&) ;
|
||||
|
@ -68,6 +68,8 @@ struct RsGxsGroupSummary : RsSerializable
|
||||
RS_SERIAL_PROCESS(mPopularity);
|
||||
RS_SERIAL_PROCESS(mSearchContext);
|
||||
}
|
||||
|
||||
~RsGxsGroupSummary();
|
||||
};
|
||||
|
||||
|
||||
@ -108,8 +110,6 @@ struct RsGxsChanges : RsEvent
|
||||
*/
|
||||
struct RsGxsIface
|
||||
{
|
||||
virtual ~RsGxsIface() {}
|
||||
|
||||
/*!
|
||||
* Gxs services should call this for automatic handling of
|
||||
* changes, send
|
||||
@ -238,4 +238,32 @@ struct RsGxsIface
|
||||
|
||||
virtual RsReputationLevel minReputationForForwardingMessages(
|
||||
uint32_t group_sign_flags,uint32_t identity_flags ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Export group public data in base64 format
|
||||
* @jsonapi{development}
|
||||
* @param[out] radix storage for the generated base64 data
|
||||
* @param[in] groupId Id of the group of which to output the data
|
||||
* @param[out] errMsg optional storage for error message, meaningful only in
|
||||
* case of failure
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool exportGroupBase64(
|
||||
std::string& radix, const RsGxsGroupId& groupId,
|
||||
std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Import group public data from base64 string
|
||||
* @param[in] radix group invite in radix format
|
||||
* @param[out] groupId optional storage for imported group id
|
||||
* @param[out] errMsg optional storage for error message, meaningful only in
|
||||
* case of failure
|
||||
* @return false if some error occurred, true otherwise
|
||||
*/
|
||||
virtual bool importGroupBase64(
|
||||
const std::string& radix,
|
||||
RsGxsGroupId& groupId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId),
|
||||
std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0;
|
||||
|
||||
virtual ~RsGxsIface();
|
||||
};
|
||||
|
@ -296,47 +296,7 @@ protected:
|
||||
uint32_t token,
|
||||
std::chrono::milliseconds maxWait = std::chrono::milliseconds(500),
|
||||
std::chrono::milliseconds checkEvery = std::chrono::milliseconds(2))
|
||||
{
|
||||
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
|
||||
auto wkStartime = std::chrono::steady_clock::now();
|
||||
int maxWorkAroundCnt = 10;
|
||||
LLwaitTokenBeginLabel:
|
||||
#endif
|
||||
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(checkEvery);
|
||||
st = requestStatus(token);
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
|
||||
/* Work around for very slow/old android devices, we don't expect this
|
||||
* to be necessary on newer devices. If it take unreasonably long
|
||||
* something worser is already happening elsewere and we return anyway.
|
||||
*/
|
||||
if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE
|
||||
&& maxWorkAroundCnt-- > 0 )
|
||||
{
|
||||
maxWait *= 10;
|
||||
checkEvery *= 3;
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Slow Android device "
|
||||
<< " workaround st: " << st
|
||||
<< " maxWorkAroundCnt: " << maxWorkAroundCnt
|
||||
<< " maxWait: " << maxWait.count()
|
||||
<< " checkEvery: " << checkEvery.count() << std::endl;
|
||||
goto LLwaitTokenBeginLabel;
|
||||
}
|
||||
std::cerr << __PRETTY_FUNCTION__ << " lasted: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - wkStartime ).count()
|
||||
<< "ms" << std::endl;
|
||||
|
||||
#endif
|
||||
|
||||
return st;
|
||||
}
|
||||
{ return mTokenService.waitToken(token, maxWait, checkEvery); }
|
||||
|
||||
private:
|
||||
RsGxsIface& mGxs;
|
||||
|
@ -3,7 +3,9 @@
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2012-2012 by Robert Fernie, Chris Evi-Parker *
|
||||
* Copyright (C) 2012 Chris Evi-Parker *
|
||||
* Copyright (C) 2012 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -19,8 +21,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef RSTOKENSERVICE_H
|
||||
#define RSTOKENSERVICE_H
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
@ -28,6 +29,7 @@
|
||||
|
||||
#include "retroshare/rsgxsifacetypes.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
#include "util/rsdebug.h"
|
||||
|
||||
// TODO CLEANUP: GXS_REQUEST_TYPE_* should be an inner enum of RsTokReqOptions
|
||||
#define GXS_REQUEST_TYPE_GROUP_DATA 0x00010000
|
||||
@ -113,7 +115,6 @@ struct RsTokReqOptions
|
||||
*/
|
||||
class RsTokenService
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum GxsRequestStatus : uint8_t
|
||||
@ -220,6 +221,59 @@ public:
|
||||
* @return false if unusuccessful in cancelling request, true if successful
|
||||
*/
|
||||
virtual bool cancelRequest(const uint32_t &token) = 0;
|
||||
};
|
||||
|
||||
#endif // RSTOKENSERVICE_H
|
||||
/**
|
||||
* 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
|
||||
* @param[in] checkEvery time in millisecond between status checks
|
||||
*/
|
||||
RsTokenService::GxsRequestStatus waitToken(
|
||||
uint32_t token,
|
||||
std::chrono::milliseconds maxWait = std::chrono::milliseconds(500),
|
||||
std::chrono::milliseconds checkEvery = std::chrono::milliseconds(2))
|
||||
{
|
||||
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
|
||||
auto wkStartime = std::chrono::steady_clock::now();
|
||||
int maxWorkAroundCnt = 10;
|
||||
LLwaitTokenBeginLabel:
|
||||
#endif
|
||||
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(checkEvery);
|
||||
st = requestStatus(token);
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
|
||||
/* Work around for very slow/old android devices, we don't expect this
|
||||
* to be necessary on newer devices. If it take unreasonably long
|
||||
* something worser is already happening elsewere and we return anyway.
|
||||
*/
|
||||
if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE
|
||||
&& maxWorkAroundCnt-- > 0 )
|
||||
{
|
||||
maxWait *= 10;
|
||||
checkEvery *= 3;
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Slow Android device "
|
||||
<< " workaround st: " << st
|
||||
<< " maxWorkAroundCnt: " << maxWorkAroundCnt
|
||||
<< " maxWait: " << maxWait.count()
|
||||
<< " checkEvery: " << checkEvery.count() << std::endl;
|
||||
goto LLwaitTokenBeginLabel;
|
||||
}
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " lasted: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - wkStartime ).count()
|
||||
<< "ms" << std::endl;
|
||||
|
||||
#endif
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(2)
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user