This commit is contained in:
RetroPooh 2017-01-15 11:48:35 +03:00
commit ed4de4ecda
35 changed files with 785 additions and 460 deletions

View File

@ -78,9 +78,28 @@ WARNING: SQLCipher is not supported yet on RetroShare for Android. This poses a
WARNING: Some versions of QtCreator try to find the Android SDK in +/opt/android/sdk+. A workaround to this is to make a symbolic link there pointing to your SDK installation path, like +mkdir -p /opt/android/sdk && ln -s /home/user/android-sdk-linux /opt/android/sdk+
== Quircks
On some Android devices like +Huawei ALE-L21+ background applications are
killed when screen is turned off unless they are in the _protected app_ list.
At moment seems apps developers don't have a way to have the application
_protected_ by default, unless the phone vendor decide the app is _popular_ so
the user have to enable _protection_ for RetroShare manually on those mobile
phones. +
{empty} +
To enable enable _protection_: +Android menu -> Settings -> Privacy & security
-> Protected apps -> RetroShare+ +
{empty} +
Other devices may offer similar _features_ please report them.
== Furter Readings
- link:http://doc.qt.io/qt-5/android-support.html[]
- link:https://developer.android.com/ndk/guides/libs.html[]
- link:retroshare://forum?name=Compiling%20nogui%20for%20android&id=8fd22bd8f99754461e7ba1ca8a727995&msgid=4e0f92330600bba9cf978f384f4b7b2f2ca64eff[]
- link:retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136[]
- link:https://groups.google.com/forum/#!topic/android-developers/srATPaL0aRU[]
- link:https://stackoverflow.com/questions/31638986/protected-apps-setting-on-huawei-phones-and-how-to-handle-it[]

View File

@ -138,7 +138,7 @@ bool DistributedChatService::handleRecvChatLobbyMsgItem(RsChatMsgItem *ci)
return false ;
}
if(rsIdentity->overallReputationLevel(cli->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
if(rsReputations->overallReputationLevel(cli->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
std::cerr << "(WW) Received lobby msg/item from banned identity " << cli->signature.keyId << ". Dropping it." << std::endl;
return false ;
@ -648,7 +648,7 @@ void DistributedChatService::handleRecvChatLobbyEventItem(RsChatLobbyEventItem *
#endif
time_t now = time(NULL) ;
if(rsIdentity->overallReputationLevel(item->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
if(rsReputations->overallReputationLevel(item->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
std::cerr << "(WW) Received lobby msg/item from banned identity " << item->signature.keyId << ". Dropping it." << std::endl;
return ;

View File

@ -1984,7 +1984,7 @@ bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item,const RsIden
{
try
{
if(rsIdentity->overallReputationLevel(item->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
if(rsReputations->overallReputationLevel(item->signature.keyId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
std::cerr << "(WW) received global router message from banned identity " << item->signature.keyId << ". Rejecting the message." << std::endl;
return false ;

View File

@ -238,11 +238,12 @@ void RsGenExchange::tick()
bool RsGenExchange::messagePublicationTest(const RsGxsMsgMetaData& meta)
{
time_t now = time(NULL) ;
time_t st = MESSAGE_STORE_PERIOD;
if(mNetService) st = mNetService->getKeepAge(meta.mGroupId, st);
time_t storageTimeLimit = meta.mPublishTs + st;
uint32_t store_limit = (mNetService == NULL)?MESSAGE_STORE_PERIOD:mNetService->getKeepAge(meta.mGroupId,MESSAGE_STORE_PERIOD) ;
return meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP || store_limit == 0 || meta.mPublishTs + store_limit >= now ;
return meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP ||
storageTimeLimit == 0 || storageTimeLimit >= time(NULL);
}
bool RsGenExchange::acknowledgeTokenMsg(const uint32_t& token,

View File

@ -428,11 +428,10 @@ protected:
public:
/*!
* Assigns a token value to passed integer
* The status of the token can still be queried from request status feature
* @warning the token space is shared with RsGenExchange backend, so do not
* modify tokens except does you have created by calling generatePublicToken()
* @return token
* Generate a new token, the status of the token can be queried from request
* status feature.
* @attention the token space is shared with RsGenExchange backend.
* @return Generated token
*/
uint32_t generatePublicToken();
@ -486,7 +485,7 @@ public:
* This allows the client service to acknowledge that their grps has \n
* been created/modified and retrieve the create/modified grp ids
* @param token the token related to modification/create request
* @param msgIds vector of ids of groups created/modified
* @param grpId ids of created/modified group
* @return true if token exists false otherwise
*/
bool acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId);

View File

@ -166,26 +166,24 @@ public:
class GixsReputation
{
public:
GixsReputation() : score(0) {}
public:
GixsReputation() {}
RsGxsId id;
int score;
uint32_t reputation_level ;
};
class RsGixsReputation
{
public:
// get Reputation.
virtual bool haveReputation(const RsGxsId &id) = 0;
virtual bool loadReputation(const RsGxsId &id, const std::list<RsPeerId>& peers) = 0;
virtual bool getReputation(const RsGxsId &id, GixsReputation &rep) = 0;
virtual RsReputations::ReputationLevel overallReputationLevel(const RsGxsId& id) = 0;
};
/*** This Class pulls all the GXS Interfaces together ****/
class RsGxsIdExchange:
public RsGenExchange,
public RsGixsReputation,
public RsGixs
{
public:

View File

@ -28,31 +28,7 @@
#include "rsgxsdataaccess.h"
#include "retroshare/rsgxsflags.h"
// This bit will be filled out over time.
#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId.
#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group.
#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs.
#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group.
#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs.
#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId
// Status Filtering... should it be a different Option Field.
#define RS_TOKREQOPT_GROUP_UPDATED 0x0100 // GROUPLIST: Groups that have been updated.
#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups.
#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups.
// Read Status.
#define RS_TOKREQOPT_READ 0x0001
#define RS_TOKREQOPT_UNREAD 0x0002
#define RS_TOKREQ_ANSTYPE_LIST 0x0001
#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002
#define RS_TOKREQ_ANSTYPE_DATA 0x0003
// 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;
@ -65,10 +41,8 @@
* #define DATA_DEBUG 1
**********/
RsGxsDataAccess::RsGxsDataAccess(RsGeneralDataService* ds)
: mDataStore(ds), mDataMutex("RsGxsDataAccess"), mNextToken(0)
{
}
RsGxsDataAccess::RsGxsDataAccess(RsGeneralDataService* ds) :
mDataStore(ds), mDataMutex("RsGxsDataAccess"), mNextToken(0) {}
bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts,

View File

@ -2740,9 +2740,11 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
return ;
}
#ifdef TO_REMOVE
int cutoff = 0;
if(grpMeta != NULL)
cutoff = grpMeta->mReputationCutOff;
#endif
GxsMsgReq reqIds;
reqIds[grpId] = std::vector<RsGxsMessageId>();
@ -2829,7 +2831,7 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
// - if author is locally banned, do not download.
// - if author is not locally banned, download, whatever friends' opinion might be.
if(rsIdentity && rsIdentity->overallReputationLevel(syncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
if(mReputations->overallReputationLevel(syncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
#ifdef NXS_NET_DEBUG_1
GXSNETDEBUG_PG(item->PeerId(),grpId) << ", Identity " << syncItem->authorId << " is banned. Not requesting message!" << std::endl;
@ -3019,7 +3021,7 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr)
// FIXTESTS global variable rsReputations not available in unittests!
#warning Update the code below to correctly send/recv dependign on reputation
if(!grpSyncItem->authorId.isNull() && rsIdentity && rsIdentity->overallReputationLevel(grpSyncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
if(!grpSyncItem->authorId.isNull() && mReputations->overallReputationLevel(grpSyncItem->authorId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
{
#ifdef NXS_NET_DEBUG_0
GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpSyncItem->authorId << " is banned. Not syncing group." << std::endl;
@ -3139,6 +3141,9 @@ void RsGxsNetService::runVetting()
RS_STACK_MUTEX(mNxsMutex) ;
#ifdef TO_BE_REMOVED
// Author response vetting is disabled since not used, as the reputations are currently not async-ed anymore.
std::vector<AuthorPending*>::iterator vit = mPendingResp.begin();
for(; vit != mPendingResp.end(); )
@ -3169,6 +3174,7 @@ void RsGxsNetService::runVetting()
}
}
#endif
// now lets do circle vetting

View File

@ -27,20 +27,13 @@
#include "pqi/p3servicecontrol.h"
#include "pgp/pgpauxutils.h"
const time_t AuthorPending::EXPIRY_PERIOD_OFFSET = 30; // 30 seconds
const int AuthorPending::MSG_PEND = 1;
const int AuthorPending::GRP_PEND = 2;
AuthorPending::AuthorPending(RsGixsReputation* rep, time_t timeStamp) : mRep(rep), mTimeStamp(timeStamp) {}
AuthorPending::AuthorPending(RsGixsReputation* rep, time_t timeStamp)
: mRep(rep), mTimeStamp(timeStamp) {
}
AuthorPending::~AuthorPending()
{
}
AuthorPending::~AuthorPending() {}
bool AuthorPending::expired() const
{
@ -49,7 +42,12 @@ bool AuthorPending::expired() const
bool AuthorPending::getAuthorRep(GixsReputation& rep, const RsGxsId& authorId, const RsPeerId& peerId)
{
if(mRep->haveReputation(authorId))
rep.id = authorId ;
rep.reputation_level = mRep->overallReputationLevel(authorId);
#warning can it happen that reputations do not have the info yet?
return true ;
#ifdef TO_BE_REMOVED
{
return mRep->getReputation(authorId, rep);
}
@ -58,7 +56,7 @@ bool AuthorPending::getAuthorRep(GixsReputation& rep, const RsGxsId& authorId, c
peers.push_back(peerId);
mRep->loadReputation(authorId, peers);
return false;
#endif
}
MsgAuthEntry::MsgAuthEntry()
@ -98,7 +96,7 @@ bool MsgRespPending::accepted()
GixsReputation rep;
if(getAuthorRep(rep, entry.mAuthorId, mPeerId))
{
if(rep.score >= mCutOff)
if(rep.reputation_level >= mCutOff)
{
entry.mPassedVetting = true;
count++;
@ -133,7 +131,7 @@ bool GrpRespPending::accepted()
if(getAuthorRep(rep, entry.mAuthorId, mPeerId))
{
if(rep.score >= mCutOff)
if(rep.reputation_level >= mCutOff)
{
entry.mPassedVetting = true;
count++;
@ -156,9 +154,9 @@ bool GrpRespPending::accepted()
const uint8_t NxsTransaction::FLAG_STATE_STARTING = 0x0001; // when
const uint8_t NxsTransaction::FLAG_STATE_RECEIVING = 0x0002; // begin receiving items for incoming trans
const uint8_t NxsTransaction::FLAG_STATE_SENDING = 0x0004; // begin sending items for outgoing trans
const uint8_t NxsTransaction::FLAG_STATE_COMPLETED = 0x008;
const uint8_t NxsTransaction::FLAG_STATE_FAILED = 0x0010;
const uint8_t NxsTransaction::FLAG_STATE_WAITING_CONFIRM = 0x0020;
const uint8_t NxsTransaction::FLAG_STATE_COMPLETED = 0x0080; // originaly 0x008, but probably a typo, but we cannot change it since it would break backward compatibility.
NxsTransaction::NxsTransaction()

View File

@ -171,7 +171,7 @@ bool RsGxsIntegrityCheck::check()
GXSUTIL_DEBUG() << "TimeStamping group authors' key ID " << grp->metaData->mAuthorId << " in group ID " << grp->grpId << std::endl;
#endif
if(rsIdentity!=NULL && rsIdentity->overallReputationLevel(grp->metaData->mAuthorId) > RsReputations::REPUTATION_LOCALLY_NEGATIVE)
if(rsReputations!=NULL && rsReputations->overallReputationLevel(grp->metaData->mAuthorId) > RsReputations::REPUTATION_LOCALLY_NEGATIVE)
used_gxs_ids.insert(std::make_pair(grp->metaData->mAuthorId,RsIdentityUsage(mGenExchangeClient->serviceType(),RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE,grp->grpId))) ;
}
}
@ -269,7 +269,7 @@ bool RsGxsIntegrityCheck::check()
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << "TimeStamping message authors' key ID " << msg->metaData->mAuthorId << " in message " << msg->msgId << ", group ID " << msg->grpId<< std::endl;
#endif
if(rsIdentity!=NULL && rsIdentity->overallReputationLevel(msg->metaData->mAuthorId) > RsReputations::REPUTATION_LOCALLY_NEGATIVE)
if(rsReputations!=NULL && rsReputations->overallReputationLevel(msg->metaData->mAuthorId) > RsReputations::REPUTATION_LOCALLY_NEGATIVE)
used_gxs_ids.insert(std::make_pair(msg->metaData->mAuthorId,RsIdentityUsage(mGenExchangeClient->serviceType(),RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE,msg->metaData->mGroupId,msg->metaData->mMsgId))) ;
}

View File

@ -34,26 +34,11 @@ class RsGxsGrpMetaData;
class RsGxsMsgMetaData;
class RsGroupMetaData
struct RsGroupMetaData
{
public:
RsGroupMetaData()
{
mGroupFlags = 0;
mSignFlags = 0;
mSubscribeFlags = 0;
mPop = 0;
mVisibleMsgCount = 0;
mLastPost = 0;
mGroupStatus = 0;
mCircleType = 0;
mAuthenFlags = 0;
mPublishTs = 0;
}
RsGroupMetaData() : mGroupFlags(0), mSignFlags(0), mPublishTs(0),
mCircleType(0), mAuthenFlags(0), mSubscribeFlags(0), mPop(0),
mVisibleMsgCount(0), mLastPost(0), mGroupStatus(0) {}
void operator =(const RsGxsGrpMetaData& rGxsMeta);
@ -90,19 +75,9 @@ public:
class RsMsgMetaData
struct RsMsgMetaData
{
public:
RsMsgMetaData()
{
mPublishTs = 0;
mMsgFlags = 0;
mMsgStatus = 0;
mChildTs = 0;
}
RsMsgMetaData() : mPublishTs(0), mMsgFlags(0), mMsgStatus(0), mChildTs(0) {}
void operator =(const RsGxsMsgMetaData& rGxsMeta);

View File

@ -11,22 +11,17 @@ typedef std::map<RsGxsGroupId, std::vector<RsMsgMetaData> > GxsMsgMetaMap;
typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsMsgMetaData> > GxsMsgRelatedMetaMap;
/*!
* The aim of this class is to abstract
* how changes are represented so
* they can be determined outside the
* client API without explcitly
* enumerating all possible changes
* at the interface
* The aim of this class is to abstract how changes are represented so they can
* be determined outside the client API without explcitly enumerating all
* possible changes at the interface
*/
class RsGxsNotify
struct RsGxsNotify
{
public:
enum NotifyType
{ TYPE_PUBLISH, TYPE_RECEIVE, TYPE_PROCESSED, TYPE_PUBLISHKEY };
enum NotifyType { TYPE_PUBLISH, TYPE_RECEIVE, TYPE_PROCESSED, TYPE_PUBLISHKEY };
virtual ~RsGxsNotify() {return; }
virtual ~RsGxsNotify() {}
virtual NotifyType getType() = 0;
};
/*!

View File

@ -289,6 +289,9 @@ public:
virtual bool updateIdentity(uint32_t& token, RsGxsIdGroup &group) = 0;
virtual bool deleteIdentity(uint32_t& token, RsGxsIdGroup &group) = 0;
virtual void setDeleteBannedNodesThreshold(uint32_t days) =0;
virtual uint32_t deleteBannedNodesThreshold() =0;
virtual bool parseRecognTag(const RsGxsId &id, const std::string &nickname,
const std::string &tag, RsRecognTagDetails &details) = 0;
virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment,
@ -303,7 +306,6 @@ public:
* \param id
* \return
*/
virtual RsReputations::ReputationLevel overallReputationLevel(const RsGxsId& id)=0;
virtual time_t getLastUsageTS(const RsGxsId &id) =0;
// Specific RsIdentity Functions....

View File

@ -61,7 +61,9 @@ public:
};
virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) =0;
virtual bool getReputationInfo(const RsGxsId& id, const RsPgpId &ownerNode, ReputationInfo& info) =0;
virtual bool getOwnOpinion(const RsGxsId& key_id, Opinion& op) =0;
virtual bool getReputationInfo(const RsGxsId& id, const RsPgpId &ownerNode, ReputationInfo& info,bool stamp=true) =0;
virtual ReputationLevel overallReputationLevel(const RsGxsId& id)=0;
// parameters
@ -73,6 +75,9 @@ public:
virtual void setThresholdForRemotelyNegativeReputation(uint32_t thresh)=0;
virtual void setThresholdForRemotelyPositiveReputation(uint32_t thresh)=0;
virtual void setRememberDeletedNodesThreshold(uint32_t days) =0;
virtual uint32_t rememberDeletedNodesThreshold() =0;
// This one is a proxy designed to allow fast checking of a GXS id.
// it basically returns true if assessment is not ASSESSMENT_OK

View File

@ -30,9 +30,9 @@
#include <string>
#include <list>
//#include "gxs/rsgxs.h"
#include "retroshare/rsgxsifacetypes.h"
// TODO CLEANUP: GXS_REQUEST_TYPE_* should be an inner enum of RsTokReqOptions
#define GXS_REQUEST_TYPE_GROUP_DATA 0x00010000
#define GXS_REQUEST_TYPE_GROUP_META 0x00020000
#define GXS_REQUEST_TYPE_GROUP_IDS 0x00040000
@ -48,20 +48,18 @@
#define GXS_REQUEST_TYPE_SERVICE_STATS 0x03200000
// This bit will be filled out over time.
// TODO CLEANUP: RS_TOKREQOPT_MSG_* should be an inner enum of RsTokReqOptions
#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId.
#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group.
#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs.
#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group.
#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs.
#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId
// Read Status.
#define RS_TOKREQOPT_READ 0x0001
#define RS_TOKREQOPT_UNREAD 0x0002
/* TODO CLEANUP: RS_TOKREQ_ANSTYPE_* values are not used by RsTokenService or
* its implementation, and may be arbitrarly defined by each GXS client, should
* be removed from here */
#define RS_TOKREQ_ANSTYPE_LIST 0x0001
#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002
#define RS_TOKREQ_ANSTYPE_DATA 0x0003
@ -72,17 +70,11 @@
* This class provides useful generic support for GXS style services.
* I expect much of this will be incorporated into the base GXS.
*/
class RsTokReqOptions
struct RsTokReqOptions
{
public:
RsTokReqOptions()
{
mOptions = 0;
mStatusFilter = 0; mStatusMask = 0; mSubscribeFilter = 0;
mSubscribeMask = 0;
mMsgFlagMask = 0; mMsgFlagFilter = 0;
mBefore = 0; mAfter = 0; mReqType = 0;
}
RsTokReqOptions() : mOptions(0), mStatusFilter(0), mStatusMask(0),
mMsgFlagMask(0), mMsgFlagFilter(0), mReqType(0), mSubscribeFilter(0),
mSubscribeMask(0), mBefore(0), mAfter(0) {}
uint32_t mOptions;
@ -115,6 +107,7 @@ 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;

View File

@ -1346,7 +1346,7 @@ int RsServer::StartupRetroShare()
RsGxsNetService* gxsid_ns = new RsGxsNetService(
RS_SERVICE_GXS_TYPE_GXSID, gxsid_ds, nxsMgr,
mGxsIdService, mGxsIdService->getServiceInfo(),
mGxsIdService, mGxsCircles,mGxsIdService,
mReputations, mGxsCircles,mGxsIdService,
pgpAuxUtils,
false,false); // don't synchronise group automatic (need explicit group request)
// don't sync messages at all.
@ -1365,7 +1365,7 @@ int RsServer::StartupRetroShare()
RsGxsNetService* gxscircles_ns = new RsGxsNetService(
RS_SERVICE_GXS_TYPE_GXSCIRCLE, gxscircles_ds, nxsMgr,
mGxsCircles, mGxsCircles->getServiceInfo(),
mGxsIdService, mGxsCircles,mGxsIdService,
mReputations, mGxsCircles,mGxsIdService,
pgpAuxUtils,
true, // synchronise group automatic
true); // sync messages automatic, since they contain subscription requests.
@ -1384,7 +1384,7 @@ int RsServer::StartupRetroShare()
RsGxsNetService* posted_ns = new RsGxsNetService(
RS_SERVICE_GXS_TYPE_POSTED, posted_ds, nxsMgr,
mPosted, mPosted->getServiceInfo(),
mGxsIdService, mGxsCircles,mGxsIdService,
mReputations, mGxsCircles,mGxsIdService,
pgpAuxUtils);
mPosted->setNetworkExchangeService(posted_ns) ;
@ -1420,7 +1420,7 @@ int RsServer::StartupRetroShare()
RsGxsNetService* gxsforums_ns = new RsGxsNetService(
RS_SERVICE_GXS_TYPE_FORUMS, gxsforums_ds, nxsMgr,
mGxsForums, mGxsForums->getServiceInfo(),
mGxsIdService, mGxsCircles,mGxsIdService,
mReputations, mGxsCircles,mGxsIdService,
pgpAuxUtils);
mGxsForums->setNetworkExchangeService(gxsforums_ns) ;
@ -1436,7 +1436,7 @@ int RsServer::StartupRetroShare()
RsGxsNetService* gxschannels_ns = new RsGxsNetService(
RS_SERVICE_GXS_TYPE_CHANNELS, gxschannels_ds, nxsMgr,
mGxsChannels, mGxsChannels->getServiceInfo(),
mGxsIdService, mGxsCircles,mGxsIdService,
mReputations, mGxsCircles,mGxsIdService,
pgpAuxUtils);
mGxsChannels->setNetworkExchangeService(gxschannels_ns) ;

View File

@ -165,6 +165,7 @@ uint32_t RsGxsReputationSetItem::serial_size() const
s += 4 ; // mOwnOpinion
s += 4 ; // mOwnOpinionTS
s += 4 ; // mIdentityFlags
s += 4 ; // mLastUsedTS
s += mOwnerNodeId.serial_size() ;
s += 4 ; // mOpinions.size()
@ -245,6 +246,7 @@ bool RsGxsReputationSetItem::serialise(void *data, uint32_t& pktsize) const
ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinion);
ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinionTS);
ok &= setRawUInt32(data, tlvsize, &offset, mIdentityFlags) ;
ok &= setRawUInt32(data, tlvsize, &offset, mLastUsedTS) ;
ok &= mOwnerNodeId.serialise(data,tlvsize,offset) ;
ok &= setRawUInt32(data, tlvsize, &offset, mOpinions.size());
@ -421,13 +423,13 @@ RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem_
return item;
}
RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem(void *data,uint32_t tlvsize)
RsGxsReputationSetItem_deprecated3 *RsGxsReputationSerialiser::deserialiseReputationSetItem_deprecated3(void *data,uint32_t tlvsize)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
bool ok = true ;
RsGxsReputationSetItem *item = new RsGxsReputationSetItem() ;
RsGxsReputationSetItem_deprecated3 *item = new RsGxsReputationSetItem_deprecated3() ;
/* add mandatory parts first */
ok &= item->mGxsId.deserialise(data, tlvsize, offset) ;
@ -460,7 +462,46 @@ RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem(
return item;
}
RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem(void *data,uint32_t tlvsize)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
bool ok = true ;
RsGxsReputationSetItem *item = new RsGxsReputationSetItem() ;
/* add mandatory parts first */
ok &= item->mGxsId.deserialise(data, tlvsize, offset) ;
ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinion);
ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinionTS);
ok &= getRawUInt32(data, tlvsize, &offset, &item->mIdentityFlags);
ok &= getRawUInt32(data, tlvsize, &offset, &item->mLastUsedTS);
ok &= item->mOwnerNodeId.deserialise(data, tlvsize, offset) ;
uint32_t S ;
ok &= getRawUInt32(data, tlvsize, &offset, &S);
for(uint32_t i = 0; ok && (i < S); ++i)
{
RsPeerId pid ;
uint32_t op ;
ok &= pid.deserialise(data, tlvsize, offset) ;
ok &= getRawUInt32(data, tlvsize, &offset, &op);
if(ok)
item->mOpinions[pid] = op ;
}
if (offset != rssize || !ok)
{
std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl;
delete item;
return NULL ;
}
return item;
}
RsGxsReputationUpdateItem *RsGxsReputationSerialiser::deserialiseReputationUpdateItem(void *data,uint32_t tlvsize)
{
uint32_t offset = 8; // skip the header
@ -534,8 +575,8 @@ RsItem *RsGxsReputationSerialiser::deserialise(void *data, uint32_t *pktsize)
switch(getRsItemSubType(rstype))
{
case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM : return deserialiseReputationSetItem (data, *pktsize);
case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated : return deserialiseReputationSetItem_deprecated(data, *pktsize);
case RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM: return deserialiseReputationBannedNodeSetItem(data, *pktsize);
case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated3: return deserialiseReputationSetItem_deprecated3(data, *pktsize);
case RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM: return deserialiseReputationBannedNodeSetItem (data, *pktsize);
case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM : return deserialiseReputationUpdateItem (data, *pktsize);
case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM : return deserialiseReputationRequestItem (data, *pktsize);
case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM : return deserialiseReputationConfigItem (data, *pktsize);

View File

@ -32,14 +32,16 @@
#include "serialiser/rsserial.h"
#include "serialiser/rstlvidset.h"
#include "retroshare/rsgxsifacetypes.h"
#include "retroshare/rsreputations.h"
#define RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM 0x01
#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated2 0x02
#define RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM 0x03
#define RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM 0x04
#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated 0x05
#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM 0x06
#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated1 0x05
#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated3 0x06
#define RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM 0x07
#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM 0x08
/**************************************************************************/
class RsReputationItem: public RsItem
@ -79,32 +81,38 @@ public:
uint32_t mLastQuery; // when we sent out.
};
// This class should disappear. Deprecated since Aug 1, 2016. The class definition is actually not needed,
// This class should disappear. Deprecated since Jan 7, 2017. The class definition is actually not needed,
// that is why it's commented out. Kept here in order to explains how the deserialisation works.
//
// class RsGxsReputationSetItem_deprecated: public RsReputationItem
// {
// public:
// RsGxsReputationSetItem_deprecated() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated) {}
//
// virtual ~RsGxsReputationSetItem_deprecated() {}
// virtual void clear() {}
// std::ostream &print(std::ostream &out, uint16_t indent = 0) { return out;}
//
// virtual bool serialise(void *data,uint32_t& size) const { std::cerr << "(EE) serialise attempt for a deprecated reputation item. This should not happen" << std::endl; return false ; }
// virtual uint32_t serial_size() const ;
//
// RsGxsId mGxsId;
// uint32_t mOwnOpinion;
// uint32_t mOwnOpinionTS;
// uint32_t mIdentityFlags;
// std::map<RsPeerId, uint32_t> mOpinions; // RsPeerId -> Opinion.
// };
class RsGxsReputationSetItem_deprecated3: public RsReputationItem
{
public:
RsGxsReputationSetItem_deprecated3() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated3) {}
virtual ~RsGxsReputationSetItem_deprecated3() {}
virtual void clear() {}
std::ostream &print(std::ostream &out, uint16_t indent = 0) { return out;}
virtual bool serialise(void *data,uint32_t& size) const { return false ;}
virtual uint32_t serial_size() const { return 0;}
RsGxsId mGxsId;
uint32_t mOwnOpinion;
uint32_t mOwnOpinionTS;
uint32_t mIdentityFlags ;
RsPgpId mOwnerNodeId;
std::map<RsPeerId, uint32_t> mOpinions; // RsPeerId -> Opinion.
};
class RsGxsReputationSetItem: public RsReputationItem
{
public:
RsGxsReputationSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM) {}
RsGxsReputationSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM)
{
mOwnOpinion = RsReputations::OPINION_NEUTRAL ;
mOwnOpinionTS = 0;
mIdentityFlags = 0;
mLastUsedTS = 0;
}
virtual ~RsGxsReputationSetItem() {}
virtual void clear();
@ -116,11 +124,11 @@ public:
RsGxsId mGxsId;
uint32_t mOwnOpinion;
uint32_t mOwnOpinionTS;
uint32_t mIdentityFlags ;
uint32_t mIdentityFlags;
uint32_t mLastUsedTS;
RsPgpId mOwnerNodeId;
std::map<RsPeerId, uint32_t> mOpinions; // RsPeerId -> Opinion.
};
class RsGxsReputationBannedNodeSetItem: public RsReputationItem
{
public:
@ -191,6 +199,7 @@ private:
static RsGxsReputationConfigItem *deserialiseReputationConfigItem (void *data, uint32_t size);
static RsGxsReputationSetItem *deserialiseReputationSetItem (void *data, uint32_t size);
static RsGxsReputationSetItem *deserialiseReputationSetItem_deprecated (void *data, uint32_t size);
static RsGxsReputationSetItem_deprecated3 *deserialiseReputationSetItem_deprecated3 (void *data, uint32_t size);
static RsGxsReputationUpdateItem *deserialiseReputationUpdateItem (void *data, uint32_t size);
static RsGxsReputationRequestItem *deserialiseReputationRequestItem (void *data, uint32_t size);
static RsGxsReputationBannedNodeSetItem *deserialiseReputationBannedNodeSetItem (void *data, uint32_t size);

View File

@ -53,17 +53,15 @@ const uint32_t GXSFORUMS_MSG_STORE_PERIOD = 60*60*24*31*12; // 12 months / 1 yea
/******************* Startup / Tick ******************************************/
/********************************************************************************/
p3GxsForums::p3GxsForums(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs)
: RsGenExchange(gds, nes, new RsGxsForumSerialiser(), RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy(), GXSFORUMS_MSG_STORE_PERIOD), RsGxsForums(this)
p3GxsForums::p3GxsForums( RsGeneralDataService *gds,
RsNetworkExchangeService *nes, RsGixs* gixs ) :
RsGenExchange( gds, nes, new RsGxsForumSerialiser(),
RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy(),
GXSFORUMS_MSG_STORE_PERIOD),
RsGxsForums(this), mGenToken(0), mGenActive(false), mGenCount(0)
{
// For Dummy Msgs.
mGenActive = false;
mGenCount = 0;
mGenToken = 0;
// Test Data disabled in Repo.
//RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD);
}

View File

@ -130,7 +130,7 @@ static const uint32_t LOWER_LIMIT = 0; // used to
static const uint32_t UPPER_LIMIT = 2; // used to filter valid Opinion values from serialized data
static const int kMaximumPeerAge = 180; // half a year.
static const int kMaximumSetSize = 100; // max set of updates to send at once.
static const int ACTIVE_FRIENDS_UPDATE_PERIOD = 600 ; // 10 minutes
static const int CLEANUP_PERIOD = 600 ; // 10 minutes
static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week.
static const int kReputationRequestPeriod = 600; // 10 mins
static const int kReputationStoreWait = 180; // 3 minutes.
@ -138,11 +138,12 @@ static const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; // reputat
static const uint32_t PGP_AUTO_BAN_THRESHOLD_DEFAULT = 2 ; // above this, auto ban any GXS id signed by this node
static const uint32_t IDENTITY_FLAGS_UPDATE_DELAY = 100 ; //
static const uint32_t BANNED_NODES_UPDATE_DELAY = 313 ; // update approx every 5 mins. Chosen to not be a multiple of IDENTITY_FLAGS_UPDATE_DELAY
static const uint32_t REPUTATION_INFO_KEEP_DELAY = 86400*35; // remove old reputation info 5 days after last usage limit, in case the ID would come back..
static const uint32_t BANNED_NODES_INACTIVITY_KEEP = 86400*60; // remove all info about banned nodes after 2 months of inactivity
static const uint32_t REPUTATION_INFO_KEEP_DELAY_DEFAULT = 86400*35; // remove old reputation info 5 days after last usage limit, in case the ID would come back..
static const uint32_t BANNED_NODES_INACTIVITY_KEEP_DEFAULT = 86400*60; // remove all info about banned nodes after 2 months of inactivity
static const uint32_t REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_POSITIVE = 1; // min difference in votes that makes friends opinion globally positive
static const uint32_t REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_NEGATIVE = 1; // min difference in votes that makes friends opinion globally negative
static const uint32_t MIN_DELAY_BETWEEN_REPUTATION_CONFIG_SAVE = 61 ; // never save more often than once a minute.
p3GxsReputation::p3GxsReputation(p3LinkMgr *lm)
:p3Service(), p3Config(),
@ -154,15 +155,17 @@ p3GxsReputation::p3GxsReputation(p3LinkMgr *lm)
mRequestTime = 0;
mStoreTime = 0;
mReputationsUpdated = false;
mLastActiveFriendsUpdate = time(NULL) - 0.5*ACTIVE_FRIENDS_UPDATE_PERIOD; // avoids doing it too soon since the TS from rsIdentity needs to be loaded already
mLastIdentityFlagsUpdate = time(NULL) - 3;
mAverageActiveFriends = 0 ;
mLastBannedNodesUpdate = 0 ;
mBannedNodesProxyNeedsUpdate = false;
mAutoSetPositiveOptionToContacts = true; // default
mMinVotesForRemotelyPositive = REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_POSITIVE;
mMinVotesForRemotelyNegative = REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_NEGATIVE;
mLastReputationConfigSaved = 0;
mChanged = false ;
mMaxPreventReloadBannedIds = 0 ; // default is "never"
}
const std::string GXS_REPUTATION_APP_NAME = "gxsreputation";
@ -188,24 +191,23 @@ int p3GxsReputation::tick()
time_t now = time(NULL);
if(mLastActiveFriendsUpdate + ACTIVE_FRIENDS_UPDATE_PERIOD < now)
if(mLastCleanUp + CLEANUP_PERIOD < now)
{
updateActiveFriends() ;
cleanup() ;
mLastActiveFriendsUpdate = now ;
mLastCleanUp = now ;
}
// no more than once per 5 second chunk.
if(now > IDENTITY_FLAGS_UPDATE_DELAY+mLastIdentityFlagsUpdate)
{
updateIdentityFlags() ;
updateStaticIdentityFlags() ;
mLastIdentityFlagsUpdate = now ;
}
if(now > BANNED_NODES_UPDATE_DELAY+mLastBannedNodesUpdate) // 613 is not a multiple of 100, to avoid piling up work
{
updateIdentityFlags() ; // needed before updateBannedNodesList!
updateStaticIdentityFlags() ; // needed before updateBannedNodesList!
updateBannedNodesProxy();
mLastBannedNodesUpdate = now ;
}
@ -225,25 +227,17 @@ int p3GxsReputation::tick()
debug_print() ;
}
#endif
if(mChanged && now > mLastReputationConfigSaved + MIN_DELAY_BETWEEN_REPUTATION_CONFIG_SAVE)
{
IndicateConfigChanged() ;
mLastReputationConfigSaved = now ;
mChanged = false ;
}
return 0;
}
// void p3GxsReputation::setNodeAutoBanThreshold(uint32_t n)
// {
// RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
//
// if(n != mPgpAutoBanThreshold)
// {
// mLastBannedNodesUpdate = 0 ;
// mPgpAutoBanThreshold = n ;
// IndicateConfigChanged() ;
// }
// }
// uint32_t p3GxsReputation::nodeAutoBanThreshold()
// {
// return mPgpAutoBanThreshold ;
// }
void p3GxsReputation::setNodeAutoPositiveOpinionForContacts(bool b)
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
@ -251,7 +245,9 @@ void p3GxsReputation::setNodeAutoPositiveOpinionForContacts(bool b)
if(b != mAutoSetPositiveOptionToContacts)
{
mLastIdentityFlagsUpdate = 0 ;
mLastCleanUp = 0 ;
mAutoSetPositiveOptionToContacts = b ;
IndicateConfigChanged() ;
}
}
@ -261,6 +257,23 @@ bool p3GxsReputation::nodeAutoPositiveOpinionForContacts()
return mAutoSetPositiveOptionToContacts ;
}
void p3GxsReputation::setRememberDeletedNodesThreshold(uint32_t days)
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
if(mMaxPreventReloadBannedIds != days*86400)
{
mMaxPreventReloadBannedIds = days*86400 ;
IndicateConfigChanged();
}
}
uint32_t p3GxsReputation::rememberDeletedNodesThreshold()
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
return mMaxPreventReloadBannedIds/86400;
}
int p3GxsReputation::status()
{
return 1;
@ -277,9 +290,6 @@ class ZeroInitCnt
void p3GxsReputation::updateBannedNodesProxy()
{
//#ifdef DEBUG_REPUTATION
// std::cerr << "Updating PGP ban list based on signed GxsIds to ban. Ban threshold = " << mPgpAutoBanThreshold << std::endl;
//#endif
// This function keeps the Banned GXS id proxy up to date.
//
@ -292,8 +302,12 @@ void p3GxsReputation::updateBannedNodesProxy()
mPerNodeBannedIdsProxy.insert(*it) ;
}
void p3GxsReputation::updateIdentityFlags()
void p3GxsReputation::updateStaticIdentityFlags()
{
// This function is the *only* place where rsIdentity is called. Normally the cross calls between p3IdService and p3GxsReputations should only
// happen one way: from rsIdentity to rsReputations. Still, reputations need to keep track of some identity flags. It's very important to make sure that
// rsIdentity is not called inside a mutex-protected zone, because normally calls happen in the other way.
std::list<RsGxsId> to_update ;
// we need to gather the list to be used in a non locked frame
@ -305,11 +319,11 @@ void p3GxsReputation::updateIdentityFlags()
#endif
for( std::map<RsGxsId, Reputation>::iterator rit = mReputations.begin();rit!=mReputations.end();++rit)
if( (rit->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE) && (mPerNodeBannedIdsProxy.find(rit->first) == mPerNodeBannedIdsProxy.end()))
{
if( (!(rit->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_UP_TO_DATE)) && (mPerNodeBannedIdsProxy.find(rit->first) == mPerNodeBannedIdsProxy.end()))
to_update.push_back(rit->first) ;
}
std::list<RsGxsId> should_set_to_positive ;
}
for(std::list<RsGxsId>::const_iterator rit(to_update.begin());rit!=to_update.end();++rit)
{
@ -322,8 +336,6 @@ void p3GxsReputation::updateIdentityFlags()
#endif
continue ;
}
bool is_a_contact = rsIdentity->isARegularContact(*rit) ;
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
std::map<RsGxsId,Reputation>::iterator it = mReputations.find(*rit) ;
@ -333,7 +345,7 @@ void p3GxsReputation::updateIdentityFlags()
std::cerr << " Weird situation: item " << *rit << " has been deleted from the list??" << std::endl;
continue ;
}
it->second.mIdentityFlags = 0 ;
it->second.mIdentityFlags = REPUTATION_IDENTITY_FLAG_UP_TO_DATE ; // resets the NEEDS_UPDATE flag. All other flags set later on.
if(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)
{
@ -342,20 +354,14 @@ void p3GxsReputation::updateIdentityFlags()
}
if(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN ) it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_KNOWN ;
if(mAutoSetPositiveOptionToContacts && is_a_contact && it->second.mOwnOpinion == RsReputations::OPINION_NEUTRAL)
should_set_to_positive.push_back(*rit) ;
#ifdef DEBUG_REPUTATION
std::cerr << " updated flags for " << *rit << " to " << std::hex << it->second.mIdentityFlags << std::dec << std::endl;
#endif
it->second.updateReputation() ;
IndicateConfigChanged();
mChanged = true ;
}
}
for(std::list<RsGxsId>::const_iterator it(should_set_to_positive.begin());it!=should_set_to_positive.end();++it)
setOwnOpinion(*it,RsReputations::OPINION_POSITIVE) ;
}
void p3GxsReputation::cleanup()
@ -363,56 +369,73 @@ void p3GxsReputation::cleanup()
// remove opinions from friends that havn't been seen online for more than the specified delay
#ifdef DEBUG_REPUTATION
#endif
std::cerr << "p3GxsReputation::cleanup() " << std::endl;
// Remove opinions about identities that do not exist anymore. That will in particular avoid asking p3idservice about deleted
// identities, which would cause an excess of hits to the database. We do it in two steps to avoid a deadlock when calling rsIdentity from here.
// Also, neutral opinions for banned PGP linked nodes are kept, so as to be able to not request them again.
bool updated = false ;
#endif
time_t now = time(NULL) ;
std::list<RsGxsId> ids_to_check_for_last_usage_ts;
// We should keep opinions about identities that do not exist anymore, but only rely on the usage TS. That will in particular avoid asking p3idservice about deleted
// identities, which would cause an excess of hits to the database. We do it in two steps to avoid a deadlock when calling rsIdentity from here.
// Also, neutral opinions for banned PGP linked nodes are kept, so as to be able to not request them again.
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
for(std::map<RsGxsId,Reputation>::iterator it(mReputations.begin());it!=mReputations.end();)
{
bool should_delete = false ;
if(it->second.mOwnOpinion == RsReputations::OPINION_NEGATIVE && mMaxPreventReloadBannedIds != 0 && it->second.mOwnOpinionTs + mMaxPreventReloadBannedIds < now)
{
#ifdef DEBUG_REPUTATION
std::cerr << " ID " << it->first << ": own is negative for more than " << mMaxPreventReloadBannedIds/86400 << " days. Reseting it!" << std::endl;
#endif
mChanged = true ;
}
// Delete slots with basically no information
if(it->second.mOpinions.empty() && it->second.mOwnOpinion == RsReputations::OPINION_NEUTRAL && (it->second.mOwnerNode.isNull()))
{
#ifdef DEBUG_REPUTATION
std::cerr << " ID " << it->first << ": own is neutral and no opinions from friends => remove entry" << std::endl;
#endif
should_delete = true ;
}
// Delete slots that havn't been used for a while. The else below is here for debug display purposes, and not harmful since both conditions lead the same effect.
else if(it->second.mLastUsedTS + REPUTATION_INFO_KEEP_DELAY_DEFAULT < now)
{
#ifdef DEBUG_REPUTATION
std::cerr << " ID " << it->first << ": no request for reputation for more than " << REPUTATION_INFO_KEEP_DELAY_DEFAULT/86400 << " days => deleting." << std::endl;
#endif
should_delete = true ;
}
#ifdef DEBUG_REPUTATION
else
std::cerr << " ID " << it->first << ": flags=" << std::hex << it->second.mIdentityFlags << std::dec << ". Last used: " << (now - it->second.mLastUsedTS)/86400 << " days ago: kept." << std::endl;
#endif
if(should_delete)
{
std::map<RsGxsId,Reputation>::iterator tmp(it) ;
++tmp ;
mReputations.erase(it) ;
it = tmp ;
updated = true ;
mChanged = true ;
}
else
{
ids_to_check_for_last_usage_ts.push_back(it->first) ;
++it;
}
}
for(std::list<RsGxsId>::const_iterator it(ids_to_check_for_last_usage_ts.begin());it!=ids_to_check_for_last_usage_ts.end();++it)
if(rsIdentity->getLastUsageTS(*it) + REPUTATION_INFO_KEEP_DELAY < now)
{
#ifdef DEBUG_REPUTATION
std::cerr << " Identity " << *it << " has a last usage TS of " << now - rsIdentity->getLastUsageTS(*it) << " secs ago: deleting it." << std::endl;
#endif
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
mReputations.erase(*it) ;
updated = true ;
}
// Clean up of the banned PGP ids.
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
for(std::map<RsPgpId,BannedNodeInfo>::iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();)
if(it->second.last_activity_TS + BANNED_NODES_INACTIVITY_KEEP < now)
if(it->second.last_activity_TS + BANNED_NODES_INACTIVITY_KEEP_DEFAULT < now)
{
#ifdef DEBUG_REPUTATION
std::cerr << " Removing all info about banned node " << it->first << " by lack of activity." << std::endl;
@ -422,47 +445,31 @@ void p3GxsReputation::cleanup()
mBannedPgpIds.erase(it) ;
it = tmp ;
updated = true ;
mChanged = true ;
}
else
++it ;
}
if(updated)
IndicateConfigChanged() ;
}
// update opinions based on flags and contact information
{
std::list<RsGxsId> should_set_to_positive ;
void p3GxsReputation::updateActiveFriends()
{
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
// keep track of who is recently connected. That will give a value to average friend
// for this, we count all friends that have been online in the last week.
time_t now = time(NULL) ;
std::list<RsPeerId> idList ;
mLinkMgr->getFriendList(idList) ;
mAverageActiveFriends = 0 ;
#ifdef DEBUG_REPUTATION
std::cerr << " counting recently online peers." << std::endl;
#endif
for(std::list<RsPeerId>::const_iterator it(idList.begin());it!=idList.end();++it)
for(std::map<RsGxsId,Reputation>::iterator it(mReputations.begin());it!=mReputations.end();++it)
{
RsPeerDetails details ;
#ifdef DEBUG_REPUTATION
std::cerr << " " << *it << ": last seen " << now - details.lastConnect << " secs ago" << std::endl;
#endif
bool is_a_contact = rsIdentity->isARegularContact(it->first) ;
if(rsPeers->getPeerDetails(*it, details) && now < details.lastConnect + ACTIVE_FRIENDS_ONLINE_DELAY)
++mAverageActiveFriends ;
if(mAutoSetPositiveOptionToContacts && is_a_contact && it->second.mOwnOpinion == RsReputations::OPINION_NEUTRAL)
should_set_to_positive.push_back(it->first) ;
}
}
#ifdef DEBUG_REPUTATION
std::cerr << " new count: " << mAverageActiveFriends << std::endl;
#endif
for(std::list<RsGxsId>::const_iterator it(should_set_to_positive.begin());it!=should_set_to_positive.end();++it)
setOwnOpinion(*it,RsReputations::OPINION_POSITIVE) ;
}
}
const float RsReputations::REPUTATION_THRESHOLD_ANTI_SPAM = 1.4f ;
@ -760,7 +767,15 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid,time_t latest_update)
* Opinion
****/
bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, const RsPgpId& ownerNode, RsReputations::ReputationInfo& info)
RsReputations::ReputationLevel p3GxsReputation::overallReputationLevel(const RsGxsId& id)
{
ReputationInfo info ;
getReputationInfo(id,RsPgpId(),info) ;
return info.mOverallReputationLevel ;
}
bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, const RsPgpId& ownerNode, RsReputations::ReputationInfo& info, bool stamp)
{
if(gxsid.isNull())
return false ;
@ -770,7 +785,7 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, const RsPgpId& own
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
#ifdef DEBUG_REPUTATION2
std::cerr << "getReputationInfo() for " << gxsid << std::endl;
std::cerr << "getReputationInfo() for " << gxsid << ", stamp = " << stamp << std::endl;
#endif
std::map<RsGxsId,Reputation>::iterator it = mReputations.find(gxsid) ;
RsPgpId owner_id ;
@ -793,10 +808,15 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, const RsPgpId& own
info.mFriendsNegativeVotes = rep.mFriendsNegative ;
info.mFriendsPositiveVotes = rep.mFriendsPositive ;
if(rep.mOwnerNode.isNull())
if(rep.mOwnerNode.isNull() && !ownerNode.isNull())
rep.mOwnerNode = ownerNode ;
owner_id = rep.mOwnerNode ;
if(stamp)
rep.mLastUsedTS = now ;
mChanged = true ;
}
// now compute overall score and reputation
@ -934,11 +954,34 @@ bool p3GxsReputation::isIdentityBanned(const RsGxsId &id)
return false ;
#ifdef DEBUG_REPUTATION
std::cerr << "isIdentityBanned(): returning " << (info.mAssessment == RsReputations::ASSESSMENT_BAD) << " for GXS id " << id << std::endl;
std::cerr << "isIdentityBanned(): returning " << (info.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE) << " for GXS id " << id << std::endl;
#endif
return info.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE ;
}
bool p3GxsReputation::getOwnOpinion(const RsGxsId& gxsid, RsReputations::Opinion& opinion)
{
#ifdef DEBUG_REPUTATION
std::cerr << "setOwnOpinion(): for GXS id " << gxsid << " to " << opinion << std::endl;
#endif
if(gxsid.isNull())
{
std::cerr << " ID " << gxsid << " is rejected. Look for a bug in calling method." << std::endl;
return false ;
}
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
std::map<RsGxsId, Reputation>::iterator rit = mReputations.find(gxsid);
if(rit != mReputations.end())
opinion = RsReputations::Opinion(rit->second.mOwnOpinion) ;
else
opinion = RsReputations::OPINION_NEUTRAL ;
return true;
}
bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::Opinion& opinion)
{
#ifdef DEBUG_REPUTATION
@ -993,7 +1036,6 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O
reputation.updateReputation();
mUpdated.insert(std::make_pair(now, gxsid));
mUpdatedReputations.insert(gxsid);
mReputationsUpdated = true;
mLastBannedNodesUpdate = 0 ; // for update of banned nodes
@ -1051,6 +1093,7 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list<RsItem*> &savelist)
item->mOwnOpinionTS = rit->second.mOwnOpinionTs;
item->mIdentityFlags = rit->second.mIdentityFlags;
item->mOwnerNodeId = rit->second.mOwnerNode;
item->mLastUsedTS = rit->second.mLastUsedTS;
std::map<RsPeerId, RsReputations::Opinion>::iterator oit;
for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit)
@ -1089,6 +1132,10 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list<RsItem*> &savelist)
kv.value = mAutoSetPositiveOptionToContacts?"YES":"NO";
vitem->tlvkvs.pairs.push_back(kv) ;
kv.key = "MAX_PREVENT_RELOAD_BANNED_IDS" ;
rs_sprintf(kv.value, "%d", mMaxPreventReloadBannedIds) ;
vitem->tlvkvs.pairs.push_back(kv) ;
savelist.push_back(vitem) ;
return true;
@ -1129,6 +1176,13 @@ bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
if (set)
loadReputationSet(set, peerSet);
RsGxsReputationSetItem_deprecated3 *set2 = dynamic_cast<RsGxsReputationSetItem_deprecated3 *>(*it);
if(set2)
{
std::cerr << "(II) reading and converting old format ReputationSetItem." << std::endl;
loadReputationSet_deprecated3(set2, peerSet);
}
RsGxsReputationBannedNodeSetItem *itm2 = dynamic_cast<RsGxsReputationBannedNodeSetItem*>(*it) ;
@ -1168,6 +1222,15 @@ bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
std::cerr << "Setting AutoPositiveContacts to " << kit->value << std::endl ;
mLastBannedNodesUpdate = 0 ; // force update
}
if(kit->key == "MAX_PREVENT_RELOAD_BANNED_IDS" )
{
int val ;
if (sscanf(kit->value.c_str(), "%d", &val) == 1)
{
mMaxPreventReloadBannedIds = val ;
std::cerr << "Setting mMaxPreventReloadBannedIds threshold to " << val << std::endl ;
}
}
}
delete (*it);
@ -1177,6 +1240,57 @@ bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
loadList.clear() ;
return true;
}
bool p3GxsReputation::loadReputationSet_deprecated3(RsGxsReputationSetItem_deprecated3 *item, const std::set<RsPeerId> &peerSet)
{
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
std::map<RsGxsId, Reputation>::iterator rit;
if(item->mGxsId.isNull()) // just a protection against potential errors having put 00000 into ids.
return false ;
/* find matching Reputation */
RsGxsId gxsId(item->mGxsId);
rit = mReputations.find(gxsId);
if (rit != mReputations.end())
{
std::cerr << "ERROR";
std::cerr << std::endl;
}
Reputation &reputation = mReputations[gxsId];
// install opinions.
std::map<RsPeerId, uint32_t>::const_iterator oit;
for(oit = item->mOpinions.begin(); oit != item->mOpinions.end(); ++oit)
{
// expensive ... but necessary.
RsPeerId peerId(oit->first);
if (peerSet.end() != peerSet.find(peerId))
reputation.mOpinions[peerId] = safe_convert_uint32t_to_opinion(oit->second);
}
reputation.mOwnOpinion = item->mOwnOpinion;
reputation.mOwnOpinionTs = item->mOwnOpinionTS;
reputation.mOwnerNode = item->mOwnerNodeId;
reputation.mIdentityFlags = item->mIdentityFlags & (~REPUTATION_IDENTITY_FLAG_UP_TO_DATE);
reputation.mLastUsedTS = time(NULL);
// if dropping entries has changed the score -> must update.
reputation.updateReputation() ;
mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId));
}
#ifdef DEBUG_REPUTATION
RsReputations::ReputationInfo info ;
getReputationInfo(item->mGxsId,item->mOwnerNodeId,info) ;
std::cerr << item->mGxsId << " : own: " << info.mOwnOpinion << ", owner node: " << item->mOwnerNodeId << ", overall level: " << info.mOverallReputationLevel << std::endl;
#endif
return true;
}
bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std::set<RsPeerId> &peerSet)
{
@ -1212,21 +1326,19 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std:
reputation.mOwnOpinion = item->mOwnOpinion;
reputation.mOwnOpinionTs = item->mOwnOpinionTS;
reputation.mOwnerNode = item->mOwnerNodeId;
reputation.mIdentityFlags = item->mIdentityFlags | REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE;
reputation.mIdentityFlags = item->mIdentityFlags;
reputation.mLastUsedTS = item->mLastUsedTS;
// if dropping entries has changed the score -> must update.
//float old_reputation = reputation.mReputation ;
//mUpdatedReputations.insert(gxsId) ;
reputation.updateReputation() ;
mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId));
}
#ifdef DEBUG_REPUTATION
RsReputations::ReputationInfo info ;
getReputationInfo(item->mGxsId,item->mOwnerNodeId,info) ;
std::cerr << item->mGxsId << " : own: " << info.mOwnOpinion << ", owner node: " << item->mOwnerNodeId << ", assessment: " << ((info.mAssessment==ASSESSMENT_BAD)?"BAD":"OK") << std::endl;
getReputationInfo(item->mGxsId,item->mOwnerNodeId,info,false) ;
std::cerr << item->mGxsId << " : own: " << info.mOwnOpinion << ", owner node: " << item->mOwnerNodeId << ", level: " << info.mOverallReputationLevel << std::endl;
#endif
return true;
}
@ -1418,21 +1530,39 @@ void Reputation::updateReputation()
void p3GxsReputation::debug_print()
{
std::cerr << "Reputations database: " << std::endl;
std::cerr << " Average number of peers: " << mAverageActiveFriends << std::endl;
std::cerr << " GXS ID data: " << std::endl;
std::cerr << std::dec ;
std::map<RsGxsId,Reputation> rep_copy;
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
rep_copy = mReputations ;
}
time_t now = time(NULL) ;
for(std::map<RsGxsId,Reputation>::const_iterator it(mReputations.begin());it!=mReputations.end();++it)
for(std::map<RsGxsId,Reputation>::const_iterator it(rep_copy.begin());it!=rep_copy.end();++it)
{
std::cerr << " " << it->first << ": own: " << it->second.mOwnOpinion << ", Friend average: " << it->second.mFriendAverage << ", global_score: " << it->second.mReputationScore
<< ", last own update: " << now - it->second.mOwnOpinionTs << " secs ago." << std::endl;
RsReputations::ReputationInfo info ;
getReputationInfo(it->first,RsPgpId(),info,false) ;
uint32_t lev = info.mOverallReputationLevel;
std::cerr << " " << it->first << ": own: " << it->second.mOwnOpinion
<< ", PGP id=" << it->second.mOwnerNode
<< ", flags=" << std::setfill('0') << std::setw(4) << std::hex << it->second.mIdentityFlags << std::dec
<< ", Friend pos/neg: " << it->second.mFriendsPositive << "/" << it->second.mFriendsNegative
<< ", reputation lev: [" << lev
<< "], last own update: " << std::setfill(' ') << std::setw(10) << now - it->second.mOwnOpinionTs << " secs ago"
<< ", last needed: " << std::setfill(' ') << std::setw(10) << now - it->second.mLastUsedTS << " secs ago, "
<< std::endl;
#ifdef DEBUG_REPUTATION2
for(std::map<RsPeerId,RsReputations::Opinion>::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2)
std::cerr << " " << it2->first << ": " << it2->second << std::endl;
#endif
}
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
std::cerr << " Banned RS nodes by ID: " << std::endl;
for(std::map<RsPgpId,BannedNodeInfo>::const_iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();++it)

View File

@ -32,14 +32,15 @@
#include <map>
#include <set>
#define REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE 0x0100
#define REPUTATION_IDENTITY_FLAG_PGP_LINKED 0x0001
#define REPUTATION_IDENTITY_FLAG_PGP_KNOWN 0x0002
static const uint32_t REPUTATION_IDENTITY_FLAG_UP_TO_DATE = 0x0100; // This flag means that the static info has been initialised from p3IdService. Normally such a call should happen once.
static const uint32_t REPUTATION_IDENTITY_FLAG_PGP_LINKED = 0x0001;
static const uint32_t REPUTATION_IDENTITY_FLAG_PGP_KNOWN = 0x0002;
#include "serialiser/rsgxsreputationitems.h"
#include "retroshare/rsidentity.h"
#include "retroshare/rsreputations.h"
#include "gxs/rsgixs.h"
#include "services/p3service.h"
@ -69,10 +70,10 @@ class Reputation
{
public:
Reputation()
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputationScore(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ }
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputationScore(RsReputations::OPINION_NEUTRAL),mIdentityFlags(0){ }
Reputation(const RsGxsId& /*about*/)
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputationScore(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ }
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputationScore(RsReputations::OPINION_NEUTRAL),mIdentityFlags(0){ }
void updateReputation();
@ -89,6 +90,8 @@ public:
RsPgpId mOwnerNode;
uint32_t mIdentityFlags;
time_t mLastUsedTS ; // last time the reputation was asked. Used to keep track of activity and clean up some reputation data.
};
@ -98,7 +101,7 @@ public:
*
*/
class p3GxsReputation: public p3Service, public p3Config, public RsReputations /* , public pqiMonitor */
class p3GxsReputation: public p3Service, public p3Config, public RsGixsReputation, public RsReputations /* , public pqiMonitor */
{
public:
p3GxsReputation(p3LinkMgr *lm);
@ -106,15 +109,20 @@ public:
/***** Interface for RsReputations *****/
virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) ;
virtual bool getReputationInfo(const RsGxsId& id, const RsPgpId &ownerNode, ReputationInfo& info) ;
virtual bool getOwnOpinion(const RsGxsId& key_id, Opinion& op) ;
virtual bool getReputationInfo(const RsGxsId& id, const RsPgpId &ownerNode, ReputationInfo& info,bool stamp=true) ;
virtual bool isIdentityBanned(const RsGxsId& id) ;
virtual bool isNodeBanned(const RsPgpId& id);
virtual void banNode(const RsPgpId& id,bool b) ;
virtual ReputationLevel overallReputationLevel(const RsGxsId& id);
virtual void setNodeAutoPositiveOpinionForContacts(bool b) ;
virtual bool nodeAutoPositiveOpinionForContacts() ;
virtual void setRememberDeletedNodesThreshold(uint32_t days) ;
virtual uint32_t rememberDeletedNodesThreshold() ;
uint32_t thresholdForRemotelyNegativeReputation();
uint32_t thresholdForRemotelyPositiveReputation();
void setThresholdForRemotelyNegativeReputation(uint32_t thresh);
@ -141,31 +149,29 @@ private:
bool SendReputations(RsGxsReputationRequestItem *request);
bool RecvReputations(RsGxsReputationUpdateItem *item);
bool updateLatestUpdate(RsPeerId peerid, time_t latest_update);
void updateActiveFriends() ;
void updateBannedNodesProxy();
// internal update of data. Takes care of cleaning empty boxes.
void locked_updateOpinion(const RsPeerId &from, const RsGxsId &about, RsReputations::Opinion op);
bool loadReputationSet(RsGxsReputationSetItem *item, const std::set<RsPeerId> &peerSet);
bool loadReputationSet_deprecated3(RsGxsReputationSetItem_deprecated3 *item, const std::set<RsPeerId> &peerSet);
int sendPackets();
void cleanup();
void sendReputationRequests();
int sendReputationRequest(RsPeerId peerid);
void debug_print() ;
void updateIdentityFlags();
void updateStaticIdentityFlags();
private:
RsMutex mReputationMtx;
time_t mLastActiveFriendsUpdate;
time_t mLastCleanUp;
time_t mRequestTime;
time_t mStoreTime;
time_t mLastBannedNodesUpdate ;
time_t mLastIdentityFlagsUpdate ;
bool mReputationsUpdated;
uint32_t mAverageActiveFriends ;
float mAutoBanIdentitiesLimit ;
bool mAutoSetPositiveOptionToContacts;
@ -177,9 +183,6 @@ private:
std::map<RsGxsId, Reputation> mReputations;
std::multimap<time_t, RsGxsId> mUpdated;
// set of Reputations to send to p3IdService.
std::set<RsGxsId> mUpdatedReputations;
// PGP Ids auto-banned. This is updated regularly.
std::map<RsPgpId,BannedNodeInfo> mBannedPgpIds ;
std::set<RsGxsId> mPerNodeBannedIdsProxy ;
@ -187,6 +190,10 @@ private:
uint32_t mMinVotesForRemotelyPositive ;
uint32_t mMinVotesForRemotelyNegative ;
uint32_t mMaxPreventReloadBannedIds ;
bool mChanged ; // slow version of IndicateConfigChanged();
time_t mLastReputationConfigSaved ;
};
#endif //SERVICE_RSGXSREPUTATION_HEADER

View File

@ -62,7 +62,8 @@
// unused keys are deleted according to some heuristic that should favor known keys, signed keys etc.
static const time_t MAX_KEEP_KEYS_BANNED = 2 * 86400 ; // get rid of banned ids after 1 days. That gives a chance to un-ban someone before he gets definitely kicked out
static const time_t MAX_KEEP_KEYS_BANNED_DEFAULT = 2 * 86400 ; // get rid of banned ids after 1 days. That gives a chance to un-ban someone before he gets definitely kicked out
static const time_t MAX_KEEP_KEYS_DEFAULT = 5 * 86400 ; // default for unsigned identities: 5 days
static const time_t MAX_KEEP_KEYS_SIGNED = 8 * 86400 ; // signed identities by unknown key
static const time_t MAX_KEEP_KEYS_SIGNED_KNOWN = 30 * 86400 ; // signed identities by known node keys
@ -164,6 +165,7 @@ p3IdService::p3IdService(RsGeneralDataService *gds, RsNetworkExchangeService *ne
mLastKeyCleaningTime = time(NULL) - int(MAX_DELAY_BEFORE_CLEANING * 0.9) ;
mLastConfigUpdate = 0 ;
mOwnIdsLoaded = false ;
mMaxKeepKeysBanned = MAX_KEEP_KEYS_BANNED_DEFAULT;
// Kick off Cache Testing, + Others.
RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD);
@ -320,6 +322,22 @@ bool p3IdService::loadList(std::list<RsItem*>& items)
mContacts = lii->mContacts ;
}
RsConfigKeyValueSet *vitem = dynamic_cast<RsConfigKeyValueSet *>(*it);
if(vitem)
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
{
if(kit->key == "REMOVE_BANNED_IDENTITIES_DELAY")
{
int val ;
if (sscanf(kit->value.c_str(), "%d", &val) == 1)
{
mMaxKeepKeysBanned = val ;
std::cerr << "Setting mMaxKeepKeysBanned threshold to " << val << std::endl ;
}
};
}
delete *it ;
}
@ -327,6 +345,23 @@ bool p3IdService::loadList(std::list<RsItem*>& items)
return true ;
}
void p3IdService::setDeleteBannedNodesThreshold(uint32_t days)
{
RsStackMutex stack(mIdMtx); /****** LOCKED MUTEX *******/
if(mMaxKeepKeysBanned != days*86400)
{
mMaxKeepKeysBanned = days*86400 ;
IndicateConfigChanged();
}
}
uint32_t p3IdService::deleteBannedNodesThreshold()
{
RsStackMutex stack(mIdMtx); /****** LOCKED MUTEX *******/
return mMaxKeepKeysBanned/86400;
}
bool p3IdService::saveList(bool& cleanup,std::list<RsItem*>& items)
{
#ifdef DEBUG_IDS
@ -343,13 +378,23 @@ bool p3IdService::saveList(bool& cleanup,std::list<RsItem*>& items)
item->mContacts = mContacts ;
items.push_back(item) ;
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ;
RsTlvKeyValue kv;
kv.key = "REMOVE_BANNED_IDENTITIES_DELAY" ;
rs_sprintf(kv.value, "%d", mMaxKeepKeysBanned);
vitem->tlvkvs.pairs.push_back(kv) ;
items.push_back(vitem) ;
return true ;
}
class IdCacheEntryCleaner
{
public:
IdCacheEntryCleaner(const std::map<RsGxsId,p3IdService::keyTSInfo>& last_usage_TSs) : mLastUsageTS(last_usage_TSs) {}
IdCacheEntryCleaner(const std::map<RsGxsId,p3IdService::keyTSInfo>& last_usage_TSs,uint32_t m) : mLastUsageTS(last_usage_TSs),mMaxKeepKeysBanned(m) {}
bool processEntry(RsGxsIdCache& entry)
{
@ -376,11 +421,17 @@ public:
time_t last_usage_ts = no_ts?0:(it->second.TS);
time_t max_keep_time ;
bool should_check = true ;
if(no_ts)
max_keep_time = 0 ;
else if(is_id_banned)
max_keep_time = MAX_KEEP_KEYS_BANNED ;
{
if(mMaxKeepKeysBanned == 0)
should_check = false ;
else
max_keep_time = mMaxKeepKeysBanned ;
}
else if(is_known_id)
max_keep_time = MAX_KEEP_KEYS_SIGNED_KNOWN ;
else if(is_signed_id)
@ -390,7 +441,7 @@ public:
std::cerr << ". Max keep = " << max_keep_time/86400 << " days. Unused for " << (now - last_usage_ts + 86399)/86400 << " days " ;
if(now > last_usage_ts + max_keep_time)
if(should_check && now > last_usage_ts + max_keep_time)
{
std::cerr << " => delete " << std::endl;
ids_to_delete.push_back(gxs_id) ;
@ -403,6 +454,7 @@ public:
std::list<RsGxsId> ids_to_delete ;
const std::map<RsGxsId,p3IdService::keyTSInfo>& mLastUsageTS;
uint32_t mMaxKeepKeysBanned ;
};
void p3IdService::cleanUnusedKeys()
@ -422,7 +474,7 @@ void p3IdService::cleanUnusedKeys()
}
// grab at most 10 identities to delete. No need to send too many requests to the token queue at once.
IdCacheEntryCleaner idcec(mKeysTS) ;
IdCacheEntryCleaner idcec(mKeysTS,mMaxKeepKeysBanned) ;
mKeyCache.applyToAllCachedEntries(idcec,&IdCacheEntryCleaner::processEntry);
@ -611,15 +663,6 @@ bool p3IdService::getIdDetails(const RsGxsId &id, RsIdentityDetails &details)
return false;
}
RsReputations::ReputationLevel p3IdService::overallReputationLevel(const RsGxsId &id)
{
#warning some IDs might be deleted but the reputation should still say they are banned.
RsIdentityDetails det ;
getIdDetails(id,det) ;
return det.mReputation.mOverallReputationLevel ;
}
bool p3IdService::isOwnId(const RsGxsId& id)
{
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
@ -1039,6 +1082,7 @@ bool p3IdService::decryptData(const uint8_t *encrypted_data,uint32_t encrypted_d
}
#ifdef TO_BE_REMOVED
/********************************************************************************/
/******************* RsGixsReputation ***************************************/
/********************************************************************************/
@ -1092,6 +1136,7 @@ bool p3IdService::getReputation(const RsGxsId &id, GixsReputation &rep)
}
return false;
}
#endif
#if 0
class RegistrationRequest
@ -4146,7 +4191,9 @@ RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCo
mHash = hs.hash();
#ifdef DEBUG_IDS
std::cerr << " hash =\"" << std::hex << mHash << "\"" << std::endl;
#endif
}

View File

@ -266,6 +266,9 @@ public:
virtual bool updateIdentity(uint32_t& token, RsGxsIdGroup &group);
virtual bool deleteIdentity(uint32_t& token, RsGxsIdGroup &group);
virtual void setDeleteBannedNodesThreshold(uint32_t days) ;
virtual uint32_t deleteBannedNodesThreshold() ;
virtual bool parseRecognTag(const RsGxsId &id, const std::string &nickname,
const std::string &tag, RsRecognTagDetails &details);
virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment,
@ -273,7 +276,6 @@ public:
virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) ;
virtual bool isARegularContact(const RsGxsId& id) ;
virtual RsReputations::ReputationLevel overallReputationLevel(const RsGxsId& id);
virtual time_t getLastUsageTS(const RsGxsId &id) ;
/**************** RsGixs Implementation ***************/
@ -304,9 +306,11 @@ public:
/**************** RsGixsReputation Implementation ****************/
// get Reputation.
#ifdef TO_BE_REMOVED
virtual bool haveReputation(const RsGxsId &id);
virtual bool loadReputation(const RsGxsId &id, const std::list<RsPeerId>& peers);
virtual bool getReputation(const RsGxsId &id, GixsReputation &rep);
#endif
protected:
@ -535,6 +539,7 @@ private:
time_t mLastConfigUpdate ;
bool mOwnIdsLoaded ;
uint32_t mMaxKeepKeysBanned ;
};
#endif // P3_IDENTITY_SERVICE_HEADER

View File

@ -110,24 +110,29 @@
// comment this out in order to remove the sorting of circles into "belong to" and "other visible circles"
#define CIRCLE_MEMBERSHIP_CATEGORIES 1
static const uint32_t SortRole = Qt::UserRole+1 ;
// quick solution for RSID_COL_VOTES sorting
class TreeWidgetItem : public QTreeWidgetItem {
class TreeWidgetItem : public QTreeWidgetItem
{
public:
TreeWidgetItem(int type=Type): QTreeWidgetItem(type) {}
TreeWidgetItem(QTreeWidget *tree): QTreeWidgetItem(tree) {}
TreeWidgetItem(const QStringList& strings): QTreeWidgetItem (strings) {}
bool operator< (const QTreeWidgetItem& other ) const {
bool operator< (const QTreeWidgetItem& other ) const
{
int column = treeWidget()->sortColumn();
const QVariant v1 = data(column, Qt::DisplayRole);
const QVariant v2 = other.data(column, Qt::DisplayRole);
double value1 = v1.toDouble();
double value2 = v2.toDouble();
if (value1 != value2) {
return value1 < value2;
}
else {
return (v1.toString().compare (v2.toString(), Qt::CaseInsensitive) < 0);
if(column == RSID_COL_VOTES)
{
const unsigned int v1 = data(column, SortRole).toUInt();
const unsigned int v2 = other.data(column, SortRole).toUInt();
return v1 < v2;
}
else
return data(column,Qt::DisplayRole).toString() < other.data(column,Qt::DisplayRole).toString();
}
};
@ -1475,6 +1480,7 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
item->setData(RSID_COL_KEYID, Qt::UserRole,QVariant(item_flags)) ;
item->setTextAlignment(RSID_COL_VOTES, Qt::AlignRight | Qt::AlignVCenter);
item->setData(RSID_COL_VOTES,Qt::DecorationRole, idd.mReputation.mOverallReputationLevel);
item->setData(RSID_COL_VOTES,SortRole, idd.mReputation.mOverallReputationLevel);
if(isOwnId)
{
@ -1984,6 +1990,7 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
default:
return QString("Undone yet");
}
return QString("Unknown");
}
void IdDialog::modifyReputation()

View File

@ -93,12 +93,10 @@ void GxsIdRSTreeWidgetItem::setId(const RsGxsId &id, int column, bool retryWhenF
//std::cerr << " GxsIdRSTreeWidgetItem::setId(" << id << "," << column << ")";
//std::cerr << std::endl;
if (mIdFound) {
if (mColumn == column && mId == id) {
if (mIdFound && mColumn == column && mId == id && (mBannedState == rsReputations->isIdentityBanned(mId)))
return;
}
}
mBannedState = rsReputations->isIdentityBanned(mId);
mIdFound = false;
mRetryWhenFailed = retryWhenFailed;
@ -110,14 +108,14 @@ void GxsIdRSTreeWidgetItem::setId(const RsGxsId &id, int column, bool retryWhenF
void GxsIdRSTreeWidgetItem::updateBannedState()
{
if(mBannedState != (rsIdentity->overallReputationLevel(mId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE))
if(mBannedState != rsReputations->isIdentityBanned(mId))
forceUpdate() ;
}
void GxsIdRSTreeWidgetItem::forceUpdate()
{
mIdFound = false;
mBannedState = (rsIdentity->overallReputationLevel(mId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE);
mBannedState = (rsReputations->isIdentityBanned(mId));
startProcess();
}
@ -163,7 +161,7 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const
if(mId.isNull())
return RSTreeWidgetItem::data(column, role);
else if(rsIdentity->overallReputationLevel(mId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
else if(rsReputations->overallReputationLevel(mId) == RsReputations::REPUTATION_LOCALLY_NEGATIVE)
pix = QImage(BANNED_IMAGE) ;
else if (mAvatar.mSize == 0 || !pix.loadFromData(mAvatar.mData, mAvatar.mSize, "PNG"))
pix = GxsIdDetails::makeDefaultIcon(mId);

View File

@ -67,6 +67,7 @@ private:
bool mIdFound;
bool mBannedState ;
bool mRetryWhenFailed;
RsReputations::ReputationLevel mReputationLevel ;
uint32_t mIconTypeMask;
RsGxsImage mAvatar;
};

View File

@ -85,8 +85,9 @@
#define COLUMN_THREAD_SIGNED 5
#define COLUMN_THREAD_CONTENT 6
#define COLUMN_THREAD_COUNT 7
#define COLUMN_THREAD_MSGID 8
#define COLUMN_THREAD_DATA 0 // column for storing the userdata like msgid and parentid
#define COLUMN_THREAD_DATA 0 // column for storing the userdata like parentid
#define ROLE_THREAD_MSGID Qt::UserRole
#define ROLE_THREAD_STATUS Qt::UserRole + 1
@ -106,7 +107,11 @@ public:
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
if(!index.isValid())
{
std::cerr << "(EE) attempt to draw an invalid index." << std::endl;
return ;
}
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
@ -574,15 +579,40 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
contextMnu.addAction(expandAll);
contextMnu.addAction(collapseAll);
QList<QTreeWidgetItem*> selectedItems = ui->threadTreeWidget->selectedItems();
if(selectedItems.size() == 1)
{
QTreeWidgetItem *item = *selectedItems.begin();
GxsIdRSTreeWidgetItem *gxsIdItem = dynamic_cast<GxsIdRSTreeWidgetItem*>(item);
RsGxsId author_id;
if(gxsIdItem && gxsIdItem->getId(author_id))
{
std::cerr << "Author is: " << author_id << std::endl;
contextMnu.addSeparator();
QMenu *submenu1 = contextMnu.addMenu(tr("Author's reputation")) ;
submenu1->addAction(flagaspositiveAct);
submenu1->addAction(flagasneutralAct);
submenu1->addAction(flagasnegativeAct);
contextMnu.addAction(showinpeopleAct);
RsReputations::Opinion op ;
if(!rsIdentity->isOwnId(author_id) && rsReputations->getOwnOpinion(author_id,op))
{
QMenu *submenu1 = contextMnu.addMenu(tr("Author's reputation")) ;
if(op != RsReputations::OPINION_POSITIVE)
submenu1->addAction(flagaspositiveAct);
if(op != RsReputations::OPINION_NEUTRAL)
submenu1->addAction(flagasneutralAct);
if(op != RsReputations::OPINION_NEGATIVE)
submenu1->addAction(flagasnegativeAct);
}
contextMnu.addAction(showinpeopleAct);
contextMnu.addAction(replyauthorAct);
}
}
contextMnu.exec(QCursor::pos());
}
@ -652,7 +682,7 @@ void GxsForumThreadWidget::changedThread()
if (!item || !item->isSelected()) {
mThreadId.clear();
} else {
mThreadId = RsGxsMessageId(item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString());
mThreadId = RsGxsMessageId(item->data(COLUMN_THREAD_MSGID, Qt::DisplayRole).toString().toStdString());
}
if (mFillThread) {
@ -1018,7 +1048,7 @@ void GxsForumThreadWidget::fillThreadFinished()
while ((item = *itemIterator) != NULL) {
++itemIterator;
if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString() == thread->mFocusMsgId) {
if (item->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString().toStdString() == thread->mFocusMsgId) {
ui->threadTreeWidget->setCurrentItem(item);
ui->threadTreeWidget->setFocus();
break;
@ -1123,7 +1153,6 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
rep_warning_level = 0 ;
rep_tooltip_str = tr("Message will be forwarded to your friends.") ;
}
std::cerr << "Inserting post from ID " << msg.mMeta.mAuthorId << ", group flags=" << std::hex << mForumGroup.mMeta.mSignFlags << " Identity flags = " << iddetails.mFlags << ": warning level = " << rep_warning_level << std::dec << std::endl;
item->setData(COLUMN_THREAD_DISTRIBUTION,Qt::ToolTipRole,rep_tooltip_str) ;
item->setData(COLUMN_THREAD_DISTRIBUTION,Qt::DecorationRole,rep_warning_level) ;
@ -1196,7 +1225,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
item->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" ")));
}
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msg.mMeta.mMsgId.toStdString()));
item->setData(COLUMN_THREAD_MSGID,Qt::DisplayRole, QString::fromStdString(msg.mMeta.mMsgId.toStdString()));
//#TODO
#if 0
if (IS_GROUP_SUBSCRIBED(subscribeFlags) && !(msginfo.mMsgFlags & RS_DISTRIB_MISSING_MSG)) {
@ -1218,7 +1247,7 @@ QTreeWidgetItem *GxsForumThreadWidget::generateMissingItem(const RsGxsMessageId
GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_AVATAR);
item->setText(COLUMN_THREAD_TITLE, tr("[ ... Missing Message ... ]"));
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msgId.toStdString()));
item->setData(COLUMN_THREAD_MSGID,Qt::DisplayRole, QString::fromStdString(msgId.toStdString()));
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, true);
item->setId(RsGxsId(), COLUMN_THREAD_AUTHOR, false); // fixed up columnId()
@ -1326,6 +1355,10 @@ static void copyItem(QTreeWidgetItem *item, const QTreeWidgetItem *newItem)
for (i = 0; i < ROLE_THREAD_COUNT; ++i) {
item->setData(COLUMN_THREAD_DATA, Qt::UserRole + i, newItem->data(COLUMN_THREAD_DATA, Qt::UserRole + i));
}
item->setData(COLUMN_THREAD_DISTRIBUTION,Qt::DecorationRole,newItem->data(COLUMN_THREAD_DISTRIBUTION,Qt::DecorationRole));
item->setData(COLUMN_THREAD_DISTRIBUTION,Qt::ToolTipRole, newItem->data(COLUMN_THREAD_DISTRIBUTION,Qt::ToolTipRole ));
item->setData(COLUMN_THREAD_MSGID, Qt::DisplayRole, newItem->data(COLUMN_THREAD_MSGID, Qt::DisplayRole ));
}
void GxsForumThreadWidget::fillThreads(QList<QTreeWidgetItem *> &threadList, bool expandNewMessages, QList<QTreeWidgetItem*> &itemToExpand)
@ -1336,49 +1369,49 @@ void GxsForumThreadWidget::fillThreads(QList<QTreeWidgetItem *> &threadList, boo
int index = 0;
QTreeWidgetItem *threadItem;
QList<QTreeWidgetItem *>::iterator newThread;
// store new items in a map, so as to allow a fast search
std::map<QString,QTreeWidgetItem*> newThreadMap ;
for(QList<QTreeWidgetItem *>::iterator newThread = threadList.begin (); newThread != threadList.end (); ++newThread)
newThreadMap[(*newThread)->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()] = *newThread ;
// delete not existing
while (index < ui->threadTreeWidget->topLevelItemCount()) {
while (index < ui->threadTreeWidget->topLevelItemCount())
{
threadItem = ui->threadTreeWidget->topLevelItem(index);
// search existing new thread
int found = -1;
for (newThread = threadList.begin (); newThread != threadList.end (); ++newThread) {
if (threadItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*newThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
// found it
found = index;
break;
}
}
if (found >= 0) {
++index;
} else {
if(newThreadMap.find(threadItem->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()) == newThreadMap.end())
delete(ui->threadTreeWidget->takeTopLevelItem(index));
else
++index;
}
}
// (csoler) QTreeWidget::findItems apparently does not always work so I need to make the search manually, which I do using a map for efficiency reasons.
std::map<QString,QTreeWidgetItem*> oldThreadMap ;
for(uint32_t i=0;i<ui->threadTreeWidget->topLevelItemCount();++i)
oldThreadMap[ui->threadTreeWidget->topLevelItem(i)->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()] = ui->threadTreeWidget->topLevelItem(i) ;
// iterate all new threads
for (newThread = threadList.begin (); newThread != threadList.end (); ++newThread) {
for (QList<QTreeWidgetItem *>::iterator newThread = threadList.begin (); newThread != threadList.end (); ++newThread) {
// search existing thread
int found = -1;
int count = ui->threadTreeWidget->topLevelItemCount();
for (index = 0; index < count; ++index) {
threadItem = ui->threadTreeWidget->topLevelItem(index);
if (threadItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*newThread)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
// found it
found = index;
break;
}
}
std::cerr << "Makign a search for string \"" << (*newThread)->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString().toStdString() << "\"" << std::endl;
std::map<QString,QTreeWidgetItem*>::const_iterator it = oldThreadMap.find((*newThread)->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()) ;
if(it != oldThreadMap.end())
{
threadItem = it->second ;
if (found >= 0) {
// set child data
copyItem(threadItem, *newThread);
// fill recursive
fillChildren(threadItem, *newThread, expandNewMessages, itemToExpand);
} else {
}
else
{
// add new thread
ui->threadTreeWidget->addTopLevelItem (*newThread);
threadItem = *newThread;
@ -1410,51 +1443,42 @@ void GxsForumThreadWidget::fillChildren(QTreeWidgetItem *parentItem, QTreeWidget
QTreeWidgetItem *childItem;
QTreeWidgetItem *newChildItem;
std::map<QString,QTreeWidgetItem*> newParentItemMap, parentItemMap ;
for(index = 0; index < newParentItem->childCount(); ++index) newParentItemMap[newParentItem->child(index)->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()] = newParentItem->child(index);
for(index = 0; index < parentItem->childCount(); ++index) parentItemMap[ parentItem->child(index)->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()] = parentItem->child(index);
// delete not existing
while (index < parentItem->childCount()) {
while (index < parentItem->childCount())
{
childItem = parentItem->child(index);
// search existing new child
int found = -1;
int count = newParentItem->childCount();
for (newIndex = 0; newIndex < count; ++newIndex) {
newChildItem = newParentItem->child(newIndex);
if (newChildItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == childItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
// found it
found = index;
break;
}
}
if (found >= 0) {
++index;
} else {
if(newParentItemMap.find(childItem->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()) == newParentItemMap.end())
delete(parentItem->takeChild (index));
}
else
++index;
}
// iterate all new children
for (newIndex = 0; newIndex < newCount; ++newIndex) {
for (newIndex = 0; newIndex < newParentItem->childCount(); ++newIndex)
{
newChildItem = newParentItem->child(newIndex);
// search existing child
int found = -1;
int count = parentItem->childCount();
for (index = 0; index < count; ++index) {
childItem = parentItem->child(index);
if (childItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == newChildItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
// found it
found = index;
break;
}
}
if (found >= 0) {
std::map<QString,QTreeWidgetItem*>::const_iterator it = parentItemMap.find(newChildItem->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString()) ;
if(it != parentItemMap.end())
{
// set child data
copyItem(childItem, newChildItem);
copyItem(it->second, newChildItem);
// fill recursive
fillChildren(childItem, newChildItem, expandNewMessages, itemToExpand);
} else {
fillChildren(it->second, newChildItem, expandNewMessages, itemToExpand);
childItem = it->second;
}
else
{
// add new child
childItem = newParentItem->takeChild(newIndex);
parentItem->addChild(childItem);
@ -1550,7 +1574,7 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg)
return;
}
uint32_t overall_reputation = rsIdentity->overallReputationLevel(msg.mMeta.mAuthorId) ;
uint32_t overall_reputation = rsReputations->overallReputationLevel(msg.mMeta.mAuthorId) ;
bool redacted = (overall_reputation == RsReputations::REPUTATION_LOCALLY_NEGATIVE) ;
mStateHelper->setActive(mTokenTypeMessageData, true);
@ -1728,7 +1752,7 @@ void GxsForumThreadWidget::setMsgReadStatus(QList<QTreeWidgetItem*> &rows, bool
if (status != statusNew) // is it different?
{
std::string msgId = (*row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString();
std::string msgId = (*row)->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString().toStdString();
// NB: MUST BE PART OF ACTIVE THREAD--- OR ELSE WE MUST STORE GROUPID SOMEWHERE!.
// LIKE THIS BELOW...
@ -1867,7 +1891,7 @@ bool GxsForumThreadWidget::navigate(const RsGxsMessageId &msgId)
while ((item = *itemIterator) != NULL) {
++itemIterator;
if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString() == msgIdString) {
if (item->data(COLUMN_THREAD_MSGID,Qt::DisplayRole).toString() == msgIdString) {
ui->threadTreeWidget->setCurrentItem(item);
ui->threadTreeWidget->setFocus();
return true;

View File

@ -193,8 +193,10 @@ void GxsForumsFillThread::run()
}
/* process messages */
while (msgs.size()) {
while (threadList.size() > 0) {
while (msgs.size())
{
while (!threadList.empty())
{
if (wasStopped()) {
break;
}

View File

@ -22,6 +22,7 @@
#include "PeoplePage.h"
#include "rsharesettings.h"
#include "retroshare/rsreputations.h"
#include "retroshare/rsidentity.h"
PeoplePage::PeoplePage(QWidget * parent, Qt::WindowFlags flags)
: ConfigPage(parent, flags)
@ -44,6 +45,8 @@ bool PeoplePage::save(QString &/*errmsg*/)
rsReputations->setThresholdForRemotelyPositiveReputation(ui.thresholdForPositive_SB->value());
rsReputations->setThresholdForRemotelyNegativeReputation(ui.thresholdForNegative_SB->value());
rsReputations->setRememberDeletedNodesThreshold(ui.preventReloadingBannedIdentitiesFor_SB->value());
rsIdentity->setDeleteBannedNodesThreshold(ui.deleteBannedIdentitiesAfter_SB->value());
return true;
}
@ -58,4 +61,6 @@ void PeoplePage::load()
ui.autoPositiveOpinion_CB->setChecked(auto_positive_contacts);
ui.thresholdForPositive_SB->setValue(threshold_for_positive);
ui.thresholdForNegative_SB->setValue(threshold_for_negative);
ui.deleteBannedIdentitiesAfter_SB->setValue(rsIdentity->deleteBannedNodesThreshold());
ui.preventReloadingBannedIdentitiesFor_SB->setValue(rsReputations->rememberDeletedNodesThreshold());
}

View File

@ -14,7 +14,7 @@
<item>
<widget class="QGroupBox" name="generalGroupBox">
<property name="title">
<string>Identities handling</string>
<string>Reputation</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@ -34,15 +34,21 @@
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Difference in votes to make friends globally negative:</string>
<string>Difference in votes (+/-) to rate an ID negatively:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="thresholdForNegative_SB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The default value of -0.6 needs 3 to 4 friends to set a negative opinion in order for that identity to be banned at your own node. This is a pretty conservative value. If you want to more easily get rid of banned identities, set the value to e.g. -0.2&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When an identity receives more negative votes than positive votes, it switches from &amp;quot;Neutral&amp;quot; to &amp;quot;Negative (according to your friends)&amp;quot;. By default, a one-vote difference is enough, but you can make this harder to happen by selecting a higher number here.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>1</number>
@ -55,7 +61,7 @@
<item row="0" column="2">
<widget class="QSpinBox" name="thresholdForPositive_SB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The default value of -0.6 needs 3 to 4 friends to set a negative opinion in order for that identity to be banned at your own node. This is a pretty conservative value. If you want to more easily get rid of banned identities, set the value to e.g. -0.2&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When an identity receives more positive votes than negative votes, it switches from &amp;quot;Neutral&amp;quot; to &amp;quot;Positive (according to your friends)&amp;quot;. By default, a one-vote difference is enough, but you can make this harder to happen by selecting a higher number here.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>1</number>
@ -63,12 +69,79 @@
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Difference in votes to make friends globally positive:</string>
<string>Difference in votes (+/-) to rate an ID positively:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Delete banned identities after (0 means indefinitely):</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Reset reputation of banned identities after (0 means never):</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="deleteBannedIdentitiesAfter_SB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Banned identities are not stamped and therefore lose activity. They get deleted automatically after a finit period of time.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string> days</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="preventReloadingBannedIdentitiesFor_SB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In order to prevent deleted banned IDs to come back because they are used in e.g. forums or channels, banned identities are kept in a list for some time. After that, they are &amp;quot;cleared&amp;quot; from the banning list, and will be downloaded again as unbanned if used in forus, chat rooms, etc.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string> days</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="value">
<number>60</number>
</property>
</widget>
</item>

View File

@ -50,6 +50,11 @@ rs_autologin:CONFIG -= no_rs_autologin
CONFIG *= rs_gxs
no_rs_gxs:CONFIG -= rs_gxs
# To disable Deprecated Warning append the following
# assignation to qmake command line "CONFIG+=rs_nodeprecatedwarning"
CONFIG *= no_rs_nodeprecatedwarning
rs_nodeprecatedwarning:CONFIG -= no_rs_nodeprecatedwarning
unix {
isEmpty(PREFIX) { PREFIX = "/usr" }
@ -153,3 +158,9 @@ 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_nodeprecatedwarning {
QMAKE_CXXFLAGS += -Wno-deprecated
QMAKE_CXXFLAGS += -Wno-deprecated-declarations
warning("QMAKE: You have disable deprecated warnings.")
}

View File

@ -62,7 +62,7 @@ bool rs_nxs_test::RsNxsSimpleDummyReputation::loadReputation(const RsGxsId& id,
bool rs_nxs_test::RsNxsSimpleDummyReputation::getReputation(const RsGxsId& id,
GixsReputation& rep) {
rep.score = 5;
rep.reputation_level = 5;
return true;
}

View File

@ -110,6 +110,8 @@ namespace rs_nxs_test
bool loadReputation(const RsGxsId &id, const std::list<RsPeerId>& peers);
bool getReputation(const RsGxsId &id, GixsReputation &rep);
virtual RsReputations::ReputationLevel overallReputationLevel(const RsGxsId&) { return RsReputations::REPUTATION_NEUTRAL ; }
private:
RepMap mRepMap;

View File

@ -50,7 +50,7 @@ GxsIsolatedServiceTester::GxsIsolatedServiceTester(const RsPeerId &ownId, const
mTestNs = new RsGxsNetService(
RS_SERVICE_GXS_TYPE_TEST, mTestDs, nxsMgr,
mTestService, mTestService->getServiceInfo(),
mGxsIdService, mGxsCircles);
NULL, mGxsCircles);
node->AddService(mTestNs);

View File

@ -67,7 +67,7 @@ GxsPeerNode::GxsPeerNode(const RsPeerId &ownId, const std::list<RsPeerId> &frien
mGxsIdNs = new RsGxsNetService(
RS_SERVICE_GXS_TYPE_GXSID, mGxsIdDs, nxsMgr,
mGxsIdService, mGxsIdService->getServiceInfo(),
mGxsIdService, mGxsCircles,mGxsIdService,
NULL, mGxsCircles,mGxsIdService,
mPgpAuxUtils,
false); // don't synchronise group automatic (need explicit group request)
@ -81,7 +81,7 @@ GxsPeerNode::GxsPeerNode(const RsPeerId &ownId, const std::list<RsPeerId> &frien
#endif
(RS_SERVICE_GXS_TYPE_GXSCIRCLE, mGxsCirclesDs, nxsMgr,
mGxsCircles, mGxsCircles->getServiceInfo(),
mGxsIdService, mGxsCircles,NULL,
NULL, mGxsCircles,NULL,
mPgpAuxUtils);
}
else
@ -107,7 +107,7 @@ GxsPeerNode::GxsPeerNode(const RsPeerId &ownId, const std::list<RsPeerId> &frien
#endif
(RS_SERVICE_GXS_TYPE_TEST, mTestDs, nxsMgr,
mTestService, mTestService->getServiceInfo(),
mGxsIdService, mGxsCircles,mGxsIdService,
NULL, mGxsCircles,mGxsIdService,
mPgpAuxUtils);
if (mUseIdentityService)