mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
commit
0120234f92
@ -34,6 +34,7 @@
|
||||
#include "pqi/p3historymgr.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
#include "retroshare/rsiface.h"
|
||||
#include "retroshare/rsreputations.h"
|
||||
#include "retroshare/rsidentity.h"
|
||||
#include "rsserver/p3face.h"
|
||||
#include "gxs/rsgixs.h"
|
||||
@ -175,6 +176,12 @@ bool DistributedChatService::handleRecvChatLobbyMsgItem(RsChatMsgItem *ci)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
if(rsReputations->isIdentityBanned(cli->signature.keyId))
|
||||
{
|
||||
std::cerr << "(WW) Received lobby msg/item from banned identity " << cli->signature.keyId << ". Dropping it." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
if(!bounceLobbyObject(cli,cli->PeerId())) // forwards the message to friends, keeps track of subscribers, etc.
|
||||
return false;
|
||||
|
||||
@ -672,6 +679,11 @@ void DistributedChatService::handleRecvChatLobbyEventItem(RsChatLobbyEventItem *
|
||||
return ;
|
||||
}
|
||||
}
|
||||
if(rsReputations->isIdentityBanned(item->signature.keyId))
|
||||
{
|
||||
std::cerr << "(WW) Received lobby msg/item from banned identity " << item->signature.keyId << ". Dropping it." << std::endl;
|
||||
return ;
|
||||
}
|
||||
addTimeShiftStatistics((int)now - (int)item->sendTime) ;
|
||||
|
||||
if(now+100 > (time_t) item->sendTime + MAX_KEEP_MSG_RECORD) // the message is older than the max cache keep minus 100 seconds ! It's too old, and is going to make an echo!
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "rsgxsnetservice.h"
|
||||
#include "retroshare/rsconfig.h"
|
||||
#include "retroshare/rsreputations.h"
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
#include "retroshare/rsgxscircles.h"
|
||||
#include "pgp/pgpauxutils.h"
|
||||
@ -1997,6 +1998,12 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(rsReputations->isIdentityBanned(syncItem->authorId))
|
||||
{
|
||||
std::cerr << ", Identity " << syncItem->authorId << " is banned. Not requesting message!" << std::endl;
|
||||
continue ;
|
||||
}
|
||||
|
||||
if(mReputations->haveReputation(syncItem->authorId) || noAuthor)
|
||||
{
|
||||
GixsReputation rep;
|
||||
@ -2009,7 +2016,7 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr)
|
||||
|
||||
// if author is required for this message, it will simply get dropped
|
||||
// at genexchange side of things
|
||||
if(rep.score > (int)grpMeta->mReputationCutOff || noAuthor)
|
||||
if(rep.score >= (int)grpMeta->mReputationCutOff || noAuthor)
|
||||
{
|
||||
#ifdef NXS_NET_DEBUG
|
||||
std::cerr << ", passed! Adding message to req list." << std::endl;
|
||||
@ -2211,6 +2218,12 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr)
|
||||
latestVersion = grpSyncItem->publishTs > metaIter->second->mPublishTs;
|
||||
}
|
||||
|
||||
if(!grpSyncItem->authorId.isNull() && rsReputations->isIdentityBanned(grpSyncItem->authorId))
|
||||
{
|
||||
std::cerr << " Identity " << grpSyncItem->authorId << " is banned. Not syncing group." << std::endl;
|
||||
continue ;
|
||||
}
|
||||
|
||||
if( (mGrpAutoSync && !haveItem) || latestVersion)
|
||||
{
|
||||
// determine if you need to check reputation
|
||||
|
@ -99,7 +99,7 @@ bool MsgRespPending::accepted()
|
||||
GixsReputation rep;
|
||||
if(getAuthorRep(rep, entry.mAuthorId, mPeerId))
|
||||
{
|
||||
if(rep.score > mCutOff)
|
||||
if(rep.score >= mCutOff)
|
||||
{
|
||||
entry.mPassedVetting = true;
|
||||
count++;
|
||||
@ -134,7 +134,7 @@ bool GrpRespPending::accepted()
|
||||
|
||||
if(getAuthorRep(rep, entry.mAuthorId, mPeerId))
|
||||
{
|
||||
if(rep.score > mCutOff)
|
||||
if(rep.score >= mCutOff)
|
||||
{
|
||||
entry.mPassedVetting = true;
|
||||
count++;
|
||||
|
@ -675,6 +675,7 @@ SOURCES += zeroconf/p3zcnatassist.cc \
|
||||
|
||||
# new gxs cache system
|
||||
# this should be disabled for releases until further notice.
|
||||
|
||||
DEFINES *= SQLITE_HAS_CODEC
|
||||
DEFINES *= GXS_ENABLE_SYNC_MSGS
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "retroshare/rstokenservice.h"
|
||||
#include "retroshare/rsgxsifacehelper.h"
|
||||
#include "retroshare/rsreputations.h"
|
||||
#include "retroshare/rsids.h"
|
||||
#include "serialiser/rstlvimage.h"
|
||||
#include "retroshare/rsgxscommon.h"
|
||||
@ -158,8 +159,7 @@ class RsIdentityDetails
|
||||
{
|
||||
public:
|
||||
RsIdentityDetails()
|
||||
:mIsOwnId(false), mPgpLinked(false), mPgpKnown(false),
|
||||
mReputation(), mLastUsageTS(0) { return; }
|
||||
:mIsOwnId(false), mPgpLinked(false), mPgpKnown(false), mLastUsageTS(0) { return; }
|
||||
|
||||
RsGxsId mId;
|
||||
|
||||
@ -175,8 +175,12 @@ public:
|
||||
// Recogn details.
|
||||
std::list<RsRecognTag> mRecognTags;
|
||||
|
||||
// reputation details.
|
||||
GxsReputation mReputation;
|
||||
// Cyril: Reputation details. At some point we might want to merge information
|
||||
// between the two into a single global score. Since the old reputation system
|
||||
// is not finished yet, I leave this in place. We should decide what to do with it.
|
||||
|
||||
GxsReputation mReputation_oldSystem; // this is the old "mReputation" field, which apparently is not used.
|
||||
RsReputations::ReputationInfo mReputation;
|
||||
|
||||
// avatar
|
||||
RsGxsImage mAvatar ;
|
||||
|
@ -40,6 +40,7 @@ extern RsPluginHandler *rsPlugins ;
|
||||
|
||||
class p3Service ;
|
||||
class RsServiceControl ;
|
||||
class RsReputations ;
|
||||
class RsTurtle ;
|
||||
class RsDht ;
|
||||
class RsDisc ;
|
||||
@ -116,6 +117,7 @@ public:
|
||||
RsUtil::inited_ptr<PgpAuxUtils> mPgpAuxUtils;
|
||||
RsUtil::inited_ptr<RsGxsForums> mGxsForums;
|
||||
RsUtil::inited_ptr<RsGxsChannels> mGxsChannels;
|
||||
RsUtil::inited_ptr<RsReputations> mReputations;
|
||||
};
|
||||
|
||||
class RsPlugin
|
||||
|
58
libretroshare/src/retroshare/rsreputations.h
Normal file
58
libretroshare/src/retroshare/rsreputations.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* libretroshare/src/services: rsreputation.h
|
||||
*
|
||||
* Services for RetroShare.
|
||||
*
|
||||
* Copyright 2015 by Cyril Soler
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "csoler@users.sourceforge.net".
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "retroshare/rsids.h"
|
||||
#include "retroshare/rsgxsifacetypes.h"
|
||||
|
||||
class RsReputations
|
||||
{
|
||||
public:
|
||||
// This is the interface file for the reputation system
|
||||
//
|
||||
enum Opinion { OPINION_NEGATIVE = 0, OPINION_NEUTRAL = 1, OPINION_POSITIVE = 2 } ;
|
||||
enum Assessment { ASSESSMENT_BAD = 0, ASSESSMENT_OK = 1 } ;
|
||||
|
||||
struct ReputationInfo
|
||||
{
|
||||
RsReputations::Opinion mOwnOpinion ;
|
||||
float mOverallReputationScore ;
|
||||
float mFriendAverage ;
|
||||
RsReputations::Assessment mAssessment; // this should help clients in taking decisions
|
||||
};
|
||||
|
||||
virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) =0;
|
||||
virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) =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
|
||||
|
||||
virtual bool isIdentityBanned(const RsGxsId& id) =0;
|
||||
};
|
||||
|
||||
// To access reputations from anywhere
|
||||
//
|
||||
extern RsReputations *rsReputations ;
|
@ -819,6 +819,7 @@ bool RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port)
|
||||
|
||||
RsFiles *rsFiles = NULL;
|
||||
RsTurtle *rsTurtle = NULL ;
|
||||
RsReputations *rsReputations = NULL ;
|
||||
#ifdef ENABLE_GROUTER
|
||||
RsGRouter *rsGRouter = NULL ;
|
||||
#endif
|
||||
@ -847,6 +848,7 @@ RsGRouter *rsGRouter = NULL ;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "services/p3gxsreputation.h"
|
||||
#include "services/p3serviceinfo.h"
|
||||
#include "services/p3heartbeat.h"
|
||||
#include "services/p3discovery2.h"
|
||||
@ -1357,6 +1359,11 @@ int RsServer::StartupRetroShare()
|
||||
|
||||
mPosted->setNetworkExchangeService(posted_ns) ;
|
||||
|
||||
/**** Reputation system ****/
|
||||
|
||||
p3GxsReputation *mReputations = new p3GxsReputation(mLinkMgr) ;
|
||||
rsReputations = mReputations ;
|
||||
|
||||
/**** Wiki GXS service ****/
|
||||
|
||||
|
||||
@ -1493,7 +1500,7 @@ int RsServer::StartupRetroShare()
|
||||
pqih -> addService(msgSrv,true);
|
||||
pqih -> addService(chatSrv,true);
|
||||
pqih -> addService(mStatusSrv,true);
|
||||
|
||||
pqih -> addService(mReputations,true);
|
||||
|
||||
// set interfaces for plugins
|
||||
//
|
||||
@ -1514,6 +1521,8 @@ int RsServer::StartupRetroShare()
|
||||
interfaces.mPgpAuxUtils = pgpAuxUtils;
|
||||
interfaces.mGxsForums = mGxsForums;
|
||||
interfaces.mGxsChannels = mGxsChannels;
|
||||
interfaces.mReputations = mReputations;
|
||||
|
||||
mPluginsManager->setInterfaces(interfaces);
|
||||
|
||||
// now add plugin objects inside the loop:
|
||||
@ -1607,6 +1616,7 @@ int RsServer::StartupRetroShare()
|
||||
mConfigMgr->addConfiguration("turtle.cfg", tr);
|
||||
mConfigMgr->addConfiguration("banlist.cfg", mBanList);
|
||||
mConfigMgr->addConfiguration("servicecontrol.cfg", serviceCtrl);
|
||||
mConfigMgr->addConfiguration("reputations.cfg", mReputations);
|
||||
#ifdef ENABLE_GROUTER
|
||||
mConfigMgr->addConfiguration("grouter.cfg", gr);
|
||||
#endif
|
||||
|
@ -23,9 +23,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
#include "serialiser/rsbanlistitems.h"
|
||||
#include "serialiser/rstlvbanlist.h"
|
||||
#include "serialiser/rsgxsreputationitems.h"
|
||||
|
||||
/***
|
||||
#define RSSERIAL_DEBUG 1
|
||||
@ -35,170 +35,395 @@
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef SUSPENDED
|
||||
RsBanListItem::~RsBanListItem()
|
||||
bool RsReputationItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) const
|
||||
{
|
||||
return;
|
||||
tlvsize = serial_size() ;
|
||||
offset = 0;
|
||||
|
||||
if (pktsize < tlvsize)
|
||||
return false; /* not enough space */
|
||||
|
||||
pktsize = tlvsize;
|
||||
|
||||
if(!setRsItemHeader(data, tlvsize, PacketId(), tlvsize))
|
||||
{
|
||||
std::cerr << "RsReputationItem::serialise_header(): ERROR. Not enough size!" << std::endl;
|
||||
return false ;
|
||||
}
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsReputationItem::serialise() Header: " << ok << std::endl;
|
||||
#endif
|
||||
offset += 8;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
void RsBanListItem::clear()
|
||||
/*************************************************************************/
|
||||
|
||||
void RsGxsReputationSetItem::clear()
|
||||
{
|
||||
peerList.TlvClear();
|
||||
mOpinions.clear() ;
|
||||
}
|
||||
|
||||
std::ostream &RsBanListItem::print(std::ostream &out, uint16_t indent)
|
||||
void RsGxsReputationUpdateItem::clear()
|
||||
{
|
||||
printRsItemBase(out, "RsBanListItem", indent);
|
||||
mOpinions.clear() ;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
std::ostream& RsGxsReputationConfigItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsReputationConfigItem", indent);
|
||||
uint16_t int_Indent = indent + 2;
|
||||
peerList.print(out, int_Indent);
|
||||
|
||||
printRsItemEnd(out, "RsBanListItem", indent);
|
||||
out << "mPeerId: " << mPeerId << std::endl;
|
||||
out << "last update: " << time(NULL) - mLatestUpdate << " secs ago." << std::endl;
|
||||
out << "last query : " << time(NULL) - mLastQuery << " secs ago." << std::endl;
|
||||
|
||||
printRsItemEnd(out, "RsReputationConfigItem", indent);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& RsGxsReputationSetItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsReputationSetItem", indent);
|
||||
uint16_t int_Indent = indent + 2;
|
||||
|
||||
uint32_t RsBanListSerialiser::sizeList(RsBanListItem *item)
|
||||
out << "GxsId: " << mGxsId << std::endl;
|
||||
out << "mOwnOpinion: " << mOwnOpinion << std::endl;
|
||||
out << "mOwnOpinionTS : " << time(NULL) - mOwnOpinionTS << " secs ago." << std::endl;
|
||||
out << "Opinions from neighbors: " << std::endl;
|
||||
|
||||
for(std::map<RsPeerId,uint32_t>::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it)
|
||||
out << " " << it->first << ": " << it->second << std::endl;
|
||||
|
||||
printRsItemEnd(out, "RsReputationSetItem", indent);
|
||||
return out;
|
||||
}
|
||||
std::ostream& RsGxsReputationUpdateItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsReputationUpdateItem", indent);
|
||||
uint16_t int_Indent = indent + 2;
|
||||
|
||||
out << "from: " << PeerId() << std::endl;
|
||||
out << "last update: " << time(NULL) - mLatestUpdate << " secs ago." << std::endl;
|
||||
|
||||
for(std::map<RsGxsId,uint32_t>::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it)
|
||||
out << " " << it->first << ": " << it->second << std::endl;
|
||||
|
||||
printRsItemEnd(out, "RsReputationUpdateItem", indent);
|
||||
return out;
|
||||
}
|
||||
std::ostream& RsGxsReputationRequestItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsReputationRequestItem", indent);
|
||||
uint16_t int_Indent = indent + 2;
|
||||
|
||||
out << "last update: " << time(NULL) - mLastUpdate << " secs ago." << std::endl;
|
||||
|
||||
printRsItemEnd(out, "RsReputationRequestItem", indent);
|
||||
return out;
|
||||
}
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t RsGxsReputationConfigItem::serial_size() const
|
||||
{
|
||||
uint32_t s = 8; /* header */
|
||||
s += item->peerList.TlvSize();
|
||||
|
||||
s += mPeerId.serial_size() ; // PeerId
|
||||
s += 4 ; // mLatestUpdate
|
||||
s += 4 ; // mLastQuery
|
||||
|
||||
return s ;
|
||||
}
|
||||
|
||||
uint32_t RsGxsReputationSetItem::serial_size() const
|
||||
{
|
||||
uint32_t s = 8; /* header */
|
||||
|
||||
s += mGxsId.serial_size() ;
|
||||
s += 4 ; // mOwnOpinion
|
||||
s += 4 ; // mOwnOpinionTS
|
||||
|
||||
s += 4 ; // mOpinions.size()
|
||||
|
||||
s += (4+RsPeerId::serial_size()) * mOpinions.size() ;
|
||||
|
||||
return s ;
|
||||
}
|
||||
|
||||
uint32_t RsGxsReputationUpdateItem::serial_size() const
|
||||
{
|
||||
uint32_t s = 8; /* header */
|
||||
|
||||
s += 4 ; // mLatestUpdate
|
||||
s += 4 ; // mOpinions.size();
|
||||
|
||||
s += (RsGxsId::serial_size() + 4) * mOpinions.size() ;
|
||||
|
||||
return s ;
|
||||
}
|
||||
|
||||
uint32_t RsGxsReputationRequestItem::serial_size() const
|
||||
{
|
||||
uint32_t s = 8; /* header */
|
||||
|
||||
s += 4 ; // mLastUpdate
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* serialise the data to the buffer */
|
||||
bool RsBanListSerialiser::serialiseList(RsBanListItem *item, void *data, uint32_t *pktsize)
|
||||
/*************************************************************************/
|
||||
|
||||
bool RsGxsReputationConfigItem::serialise(void *data, uint32_t& pktsize) const
|
||||
{
|
||||
uint32_t tlvsize = sizeList(item);
|
||||
uint32_t offset = 0;
|
||||
uint32_t tlvsize ;
|
||||
uint32_t offset=0;
|
||||
|
||||
if (*pktsize < tlvsize)
|
||||
return false; /* not enough space */
|
||||
|
||||
*pktsize = tlvsize;
|
||||
if(!serialise_header(data,pktsize,tlvsize,offset))
|
||||
return false ;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize);
|
||||
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsDsdvSerialiser::serialiseRoute() Header: " << ok << std::endl;
|
||||
std::cerr << "RsDsdvSerialiser::serialiseRoute() Size: " << tlvsize << std::endl;
|
||||
#endif
|
||||
|
||||
/* skip the header */
|
||||
offset += 8;
|
||||
|
||||
/* add mandatory parts first */
|
||||
ok &= item->peerList.SetTlv(data, tlvsize, &offset);
|
||||
ok &= mPeerId.serialise(data,tlvsize,offset) ;
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mLatestUpdate);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mLastQuery);
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
ok = false;
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsDsdvSerialiser::serialiseRoute() Size Error! " << std::endl;
|
||||
#endif
|
||||
std::cerr << "RsGxsReputationConfigItem::serialisedata() size error! " << std::endl;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
RsBanListItem *RsBanListSerialiser::deserialiseList(void *data, uint32_t *pktsize)
|
||||
bool RsGxsReputationSetItem::serialise(void *data, uint32_t& pktsize) const
|
||||
{
|
||||
/* get the type and size */
|
||||
uint32_t rstype = getRsItemId(data);
|
||||
uint32_t tlvsize = getRsItemSize(data);
|
||||
uint32_t tlvsize ;
|
||||
uint32_t offset=0;
|
||||
|
||||
uint32_t offset = 0;
|
||||
|
||||
|
||||
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) ||
|
||||
(RS_SERVICE_TYPE_BANLIST != getRsItemService(rstype)) ||
|
||||
(RS_PKT_SUBTYPE_BANLIST_ITEM != getRsItemSubType(rstype)))
|
||||
{
|
||||
return NULL; /* wrong type */
|
||||
}
|
||||
|
||||
if (*pktsize < tlvsize) /* check size */
|
||||
return NULL; /* not enough data */
|
||||
|
||||
/* set the packet length */
|
||||
*pktsize = tlvsize;
|
||||
if(!serialise_header(data,pktsize,tlvsize,offset))
|
||||
return false ;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
/* ready to load */
|
||||
RsBanListItem *item = new RsBanListItem();
|
||||
item->clear();
|
||||
ok &= mGxsId.serialise(data,tlvsize,offset) ;
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinion);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinionTS);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mOpinions.size());
|
||||
|
||||
/* skip the header */
|
||||
offset += 8;
|
||||
|
||||
/* add mandatory parts first */
|
||||
ok &= item->peerList.GetTlv(data, tlvsize, &offset);
|
||||
for(std::map<RsPeerId,uint32_t>::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it)
|
||||
{
|
||||
ok &= it->first.serialise(data,tlvsize,offset) ;
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, it->second) ;
|
||||
}
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
/* error */
|
||||
delete item;
|
||||
return NULL;
|
||||
ok = false;
|
||||
std::cerr << "RsGxsReputationSetItem::serialisedata() size error! " << std::endl;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
return ok;
|
||||
}
|
||||
bool RsGxsReputationUpdateItem::serialise(void *data, uint32_t& pktsize) const
|
||||
{
|
||||
uint32_t tlvsize ;
|
||||
uint32_t offset=0;
|
||||
|
||||
if(!serialise_header(data,pktsize,tlvsize,offset))
|
||||
return false ;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mLatestUpdate);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mOpinions.size());
|
||||
|
||||
for(std::map<RsGxsId,uint32_t>::const_iterator it(mOpinions.begin());ok && it!=mOpinions.end();++it)
|
||||
{
|
||||
ok &= it->first.serialise(data, tlvsize, offset) ;
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, it->second) ;
|
||||
}
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
ok = false;
|
||||
std::cerr << "RsGxsReputationUpdateItem::serialisedata() size error! " << std::endl;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
/* serialise the data to the buffer */
|
||||
bool RsGxsReputationRequestItem::serialise(void *data, uint32_t& pktsize) const
|
||||
{
|
||||
uint32_t tlvsize ;
|
||||
uint32_t offset=0;
|
||||
|
||||
if(!serialise_header(data,pktsize,tlvsize,offset))
|
||||
return false ;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, mLastUpdate);
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
ok = false;
|
||||
std::cerr << "RsGxsReputationRequestItem::serialisedata() size error! " << std::endl;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
/*************************************************************************/
|
||||
|
||||
RsGxsReputationConfigItem *RsGxsReputationSerialiser::deserialiseReputationConfigItem(void *data,uint32_t size)
|
||||
{
|
||||
uint32_t offset = 8; // skip the header
|
||||
uint32_t rssize = getRsItemSize(data);
|
||||
bool ok = true ;
|
||||
|
||||
RsGxsReputationConfigItem *item = new RsGxsReputationConfigItem() ;
|
||||
|
||||
/* add mandatory parts first */
|
||||
ok &= item->mPeerId.deserialise(data, size, offset) ;
|
||||
ok &= getRawUInt32(data, size, &offset, &item->mLatestUpdate);
|
||||
ok &= getRawUInt32(data, size, &offset, &item->mLastQuery);
|
||||
|
||||
if (offset != rssize || !ok)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl;
|
||||
delete item;
|
||||
return NULL;
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
uint32_t S ;
|
||||
ok &= getRawUInt32(data, tlvsize, &offset, &S);
|
||||
|
||||
for(int 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
|
||||
uint32_t rssize = getRsItemSize(data);
|
||||
bool ok = true ;
|
||||
|
||||
RsGxsReputationUpdateItem *item = new RsGxsReputationUpdateItem() ;
|
||||
|
||||
/* add mandatory parts first */
|
||||
ok &= getRawUInt32(data, tlvsize, &offset, &item->mLatestUpdate);
|
||||
|
||||
uint32_t S ;
|
||||
ok &= getRawUInt32(data, tlvsize, &offset, &S) ;
|
||||
|
||||
for(uint32_t i=0;ok && i<S;++i)
|
||||
{
|
||||
RsGxsId gid ;
|
||||
uint32_t op ;
|
||||
|
||||
ok &= gid.deserialise(data, tlvsize, offset) ;
|
||||
ok &= getRawUInt32(data, tlvsize, &offset, &op);
|
||||
|
||||
if(ok)
|
||||
item->mOpinions[gid] = op ;
|
||||
|
||||
}
|
||||
|
||||
if (offset != rssize || !ok)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl;
|
||||
delete item;
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
RsGxsReputationRequestItem *RsGxsReputationSerialiser::deserialiseReputationRequestItem(void *data,uint32_t tlvsize)
|
||||
{
|
||||
uint32_t offset = 8; // skip the header
|
||||
uint32_t rssize = getRsItemSize(data);
|
||||
bool ok = true ;
|
||||
|
||||
RsGxsReputationRequestItem *item = new RsGxsReputationRequestItem() ;
|
||||
|
||||
/* add mandatory parts first */
|
||||
ok &= getRawUInt32(data, tlvsize, &offset, &item->mLastUpdate);
|
||||
|
||||
if (offset != rssize || !ok)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl;
|
||||
delete item;
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t RsBanListSerialiser::size(RsItem *i)
|
||||
{
|
||||
RsBanListItem *dri;
|
||||
|
||||
if (NULL != (dri = dynamic_cast<RsBanListItem *>(i)))
|
||||
{
|
||||
return sizeList(dri);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool RsBanListSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize)
|
||||
{
|
||||
RsBanListItem *dri;
|
||||
|
||||
if (NULL != (dri = dynamic_cast<RsBanListItem *>(i)))
|
||||
{
|
||||
return serialiseList(dri, data, pktsize);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RsItem *RsBanListSerialiser::deserialise(void *data, uint32_t *pktsize)
|
||||
RsItem *RsGxsReputationSerialiser::deserialise(void *data, uint32_t *pktsize)
|
||||
{
|
||||
/* get the type and size */
|
||||
uint32_t rstype = getRsItemId(data);
|
||||
|
||||
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) ||
|
||||
(RS_SERVICE_TYPE_BANLIST != getRsItemService(rstype)))
|
||||
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_GXS_TYPE_REPUTATION != getRsItemService(rstype)))
|
||||
{
|
||||
std::cerr << "RsReputationSerialiser::deserialise(): wrong item type " << std::hex << rstype << std::dec << std::endl;
|
||||
return NULL; /* wrong type */
|
||||
}
|
||||
|
||||
switch(getRsItemSubType(rstype))
|
||||
{
|
||||
case RS_PKT_SUBTYPE_BANLIST_ITEM:
|
||||
return deserialiseList(data, pktsize);
|
||||
break;
|
||||
case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM : return deserialiseReputationSetItem (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);
|
||||
|
||||
default:
|
||||
std::cerr << "RsGxsReputationSerialiser::deserialise(): unknown item subtype " << std::hex<< rstype << std::dec << std::endl;
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
|
@ -32,88 +32,94 @@
|
||||
#include "serialiser/rsserial.h"
|
||||
#include "retroshare/rsgxsifacetypes.h"
|
||||
|
||||
#define RS_PKT_SUBTYPE_GXSREPUTATION_CONFIG_ITEM 0x01
|
||||
#define RS_PKT_SUBTYPE_GXSREPUTATION_SET_ITEM 0x02
|
||||
#define RS_PKT_SUBTYPE_GXSREPUTATION_UPDATE_ITEM 0x03
|
||||
#define RS_PKT_SUBTYPE_GXSREPUTATION_REQUEST_ITEM 0x04
|
||||
#define RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM 0x01
|
||||
#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM 0x02
|
||||
#define RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM 0x03
|
||||
#define RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM 0x04
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
class RsGxsReputationConfigItem: public RsItem
|
||||
class RsReputationItem: public RsItem
|
||||
{
|
||||
public:
|
||||
RsGxsReputationConfigItem()
|
||||
:RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_REPUTATION,
|
||||
RS_PKT_SUBTYPE_GXSREPUTATION_CONFIG_ITEM)
|
||||
RsReputationItem(uint8_t reputation_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_REPUTATION,reputation_subtype)
|
||||
{
|
||||
setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM);
|
||||
return;
|
||||
}
|
||||
|
||||
virtual ~RsGxsReputationConfigItem();
|
||||
virtual void clear();
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
virtual ~RsReputationItem() {}
|
||||
|
||||
std::string mPeerId;
|
||||
virtual bool serialise(void *data,uint32_t& size) const = 0 ;
|
||||
virtual uint32_t serial_size() const = 0 ;
|
||||
|
||||
virtual void clear() = 0 ;
|
||||
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0;
|
||||
|
||||
protected:
|
||||
bool serialise_header(void *data, uint32_t& pktsize, uint32_t& tlvsize, uint32_t& offset) const;
|
||||
};
|
||||
|
||||
class RsGxsReputationConfigItem: public RsReputationItem
|
||||
{
|
||||
public:
|
||||
RsGxsReputationConfigItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM) {}
|
||||
|
||||
virtual ~RsGxsReputationConfigItem() {}
|
||||
virtual void clear() {}
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
virtual bool serialise(void *data,uint32_t& size) const ;
|
||||
virtual uint32_t serial_size() const ;
|
||||
|
||||
RsPeerId mPeerId;
|
||||
uint32_t mLatestUpdate; // timestamp they returned.
|
||||
uint32_t mLastQuery; // when we sent out.
|
||||
};
|
||||
|
||||
class RsGxsReputationSetItem: public RsItem
|
||||
class RsGxsReputationSetItem: public RsReputationItem
|
||||
{
|
||||
public:
|
||||
RsGxsReputationSetItem()
|
||||
:RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_REPUTATION,
|
||||
RS_PKT_SUBTYPE_GXSREPUTATION_SET_ITEM)
|
||||
{
|
||||
setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM);
|
||||
return;
|
||||
}
|
||||
public:
|
||||
RsGxsReputationSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM) {}
|
||||
|
||||
virtual ~RsGxsReputationSetItem();
|
||||
virtual void clear();
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
virtual ~RsGxsReputationSetItem() {}
|
||||
virtual void clear();
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
std::string mGxsId;
|
||||
virtual bool serialise(void *data,uint32_t& size) const ;
|
||||
virtual uint32_t serial_size() const ;
|
||||
|
||||
RsGxsId mGxsId;
|
||||
uint32_t mOwnOpinion;
|
||||
uint32_t mOwnOpinionTs;
|
||||
uint32_t mReputation;
|
||||
std::map<std::string, uint32_t> mOpinions; // RsPeerId -> Opinion.
|
||||
uint32_t mOwnOpinionTS;
|
||||
std::map<RsPeerId, uint32_t> mOpinions; // RsPeerId -> Opinion.
|
||||
};
|
||||
|
||||
class RsGxsReputationUpdateItem: public RsItem
|
||||
class RsGxsReputationUpdateItem: public RsReputationItem
|
||||
{
|
||||
public:
|
||||
RsGxsReputationUpdateItem()
|
||||
:RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_REPUTATION,
|
||||
RS_PKT_SUBTYPE_GXSREPUTATION_UPDATE_ITEM)
|
||||
{
|
||||
setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM);
|
||||
return;
|
||||
}
|
||||
public:
|
||||
RsGxsReputationUpdateItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM) {}
|
||||
|
||||
virtual ~RsGxsReputationUpdateItem();
|
||||
virtual void clear();
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
virtual ~RsGxsReputationUpdateItem() {}
|
||||
virtual void clear();
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
virtual bool serialise(void *data,uint32_t& size) const ;
|
||||
virtual uint32_t serial_size() const ;
|
||||
|
||||
std::map<RsGxsId, uint32_t> mOpinions; // GxsId -> Opinion.
|
||||
uint32_t mLatestUpdate;
|
||||
std::map<RsGxsId, uint32_t> mOpinions; // GxsId -> Opinion.
|
||||
};
|
||||
|
||||
class RsGxsReputationRequestItem: public RsItem
|
||||
class RsGxsReputationRequestItem: public RsReputationItem
|
||||
{
|
||||
public:
|
||||
RsGxsReputationRequestItem()
|
||||
:RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_REPUTATION,
|
||||
RS_PKT_SUBTYPE_GXSREPUTATION_REQUEST_ITEM)
|
||||
{
|
||||
setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM);
|
||||
return;
|
||||
}
|
||||
public:
|
||||
RsGxsReputationRequestItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM) {}
|
||||
|
||||
virtual ~RsGxsReputationRequestItem();
|
||||
virtual void clear();
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
virtual ~RsGxsReputationRequestItem() {}
|
||||
virtual void clear() {}
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
virtual bool serialise(void *data,uint32_t& size) const ;
|
||||
virtual uint32_t serial_size() const ;
|
||||
|
||||
uint32_t mLastUpdate;
|
||||
};
|
||||
@ -121,39 +127,26 @@ std::ostream &print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
class RsGxsReputationSerialiser: public RsSerialType
|
||||
{
|
||||
public:
|
||||
RsGxsReputationSerialiser()
|
||||
:RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_REPUTATION)
|
||||
{ return; }
|
||||
virtual ~RsGxsReputationSerialiser()
|
||||
{ return; }
|
||||
public:
|
||||
RsGxsReputationSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_REPUTATION){}
|
||||
|
||||
virtual uint32_t size(RsItem *);
|
||||
virtual bool serialise (RsItem *item, void *data, uint32_t *size);
|
||||
virtual RsItem * deserialise(void *data, uint32_t *size);
|
||||
|
||||
private:
|
||||
|
||||
virtual uint32_t sizeConfig(RsGxsReputationConfigItem *);
|
||||
virtual bool serialiseConfig(RsGxsReputationConfigItem *item, void *data, uint32_t *size);
|
||||
virtual RsGxsReputationConfigItem *deserialiseConfig(void *data, uint32_t *size);
|
||||
|
||||
|
||||
virtual uint32_t sizeSet(RsGxsReputationSetItem *);
|
||||
virtual bool serialiseSet(RsGxsReputationSetItem *item, void *data, uint32_t *size);
|
||||
virtual RsGxsReputationSetItem *deserialiseSet(void *data, uint32_t *size);
|
||||
|
||||
|
||||
virtual uint32_t sizeUpdate(RsGxsReputationUpdateItem *);
|
||||
virtual bool serialiseUpdate(RsGxsReputationUpdateItem *item, void *data, uint32_t *size);
|
||||
virtual RsGxsReputationUpdateItem *deserialiseUpdate(void *data, uint32_t *size);
|
||||
|
||||
|
||||
virtual uint32_t sizeRequest(RsGxsReputationRequestItem *);
|
||||
virtual bool serialiseRequest(RsGxsReputationRequestItem *item, void *data, uint32_t *size);
|
||||
virtual RsGxsReputationRequestItem *deserialiseRequest(void *data, uint32_t *size);
|
||||
virtual ~RsGxsReputationSerialiser(){}
|
||||
|
||||
virtual uint32_t size(RsItem *item)
|
||||
{
|
||||
return dynamic_cast<RsReputationItem*>(item)->serial_size() ;
|
||||
}
|
||||
virtual bool serialise (RsItem *item, void *data, uint32_t *size)
|
||||
{
|
||||
return dynamic_cast<RsReputationItem*>(item)->serialise(data,*size) ;
|
||||
}
|
||||
virtual RsItem * deserialise(void *data, uint32_t *size);
|
||||
|
||||
private:
|
||||
static RsGxsReputationConfigItem *deserialiseReputationConfigItem (void *data, uint32_t size);
|
||||
static RsGxsReputationSetItem *deserialiseReputationSetItem (void *data, uint32_t size);
|
||||
static RsGxsReputationUpdateItem *deserialiseReputationUpdateItem (void *data, uint32_t size);
|
||||
static RsGxsReputationRequestItem *deserialiseReputationRequestItem(void *data, uint32_t size);
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
@ -38,13 +38,6 @@
|
||||
* #define DEBUG_REPUTATION 1
|
||||
****/
|
||||
|
||||
|
||||
/* DEFINE INTERFACE POINTER! */
|
||||
//RsGxsReputation *rsGxsReputation = NULL;
|
||||
|
||||
const int kMaximumPeerAge = 180; // half a year.
|
||||
const int kMaximumSetSize = 100;
|
||||
|
||||
/************ IMPLEMENTATION NOTES *********************************
|
||||
*
|
||||
* p3GxsReputation shares opinions / reputations with peers.
|
||||
@ -61,8 +54,12 @@ const int kMaximumSetSize = 100;
|
||||
* last update ----------->
|
||||
* <----------- modified opinions.
|
||||
*
|
||||
* This service will have to store a huge amount of data.
|
||||
* need to workout how to reduce it.
|
||||
* If not clever enough, this service will have to store a huge amount of data.
|
||||
* To make things tractable we do this:
|
||||
* - do not store reputations when no data is present, or when all friends are neutral
|
||||
* - only send a neutral opinion when they are a true change over someone's opinion
|
||||
* - only send a neutral opinion when it is a true change over someone's opinion
|
||||
* - auto-clean reputations for default values
|
||||
*
|
||||
* std::map<RsGxsId, Reputation> mReputations.
|
||||
* std::multimap<time_t, RsGxsId> mUpdated.
|
||||
@ -70,55 +67,72 @@ const int kMaximumSetSize = 100;
|
||||
* std::map<RsPeerId, ReputationConfig> mConfig;
|
||||
*
|
||||
* Updates from p3GxsReputation -> p3IdService.
|
||||
*
|
||||
*
|
||||
* Updates from p3IdService -> p3GxsReputation.
|
||||
*
|
||||
* Each peer locally stores reputations for all GXS ids. If not stored, a default value
|
||||
* is used, corresponding to a neutral opinion. Peers also share their reputation level
|
||||
* with their neighbor nodes.
|
||||
*
|
||||
* The calculation method is the following:
|
||||
*
|
||||
* Local values:
|
||||
* Good: 2
|
||||
* Neutral: 1
|
||||
* Bad: 0
|
||||
*
|
||||
* Overall reputation score:
|
||||
*
|
||||
* if(own_opinion == 0) // means we dont' care
|
||||
* r = average_of_friends_opinions
|
||||
* else
|
||||
* r = own_opinion
|
||||
*
|
||||
* Decisions based on reputation score:
|
||||
*
|
||||
* 0 x1 1 x2 2
|
||||
* | <-----------------------------------------------------------------------> |
|
||||
* ---------+
|
||||
* Lobbies | Msgs dropped
|
||||
* Forums | Msgs dropped
|
||||
* Messages | Msgs dropped
|
||||
* ---------+----------------------------------------------------------------------------
|
||||
*
|
||||
* We select x1=0.5
|
||||
*
|
||||
* => to kill an identity, either you, or at least 50% of your friends need to flag it
|
||||
* as bad.
|
||||
* Rules:
|
||||
* * a single peer cannot drastically change the behavior of a given GXS id
|
||||
* * it should be easy for many peers to globally kill a GXS id
|
||||
*
|
||||
* Typical examples:
|
||||
*
|
||||
* Friends | Friend average | Own | alpha | Score
|
||||
* -----------+---------------------+----------+------------+--------------
|
||||
* 10 | 0.5 | 1 | 0.25 | 0.375
|
||||
* 10 | 1.0 | 1 | 0.25 | 1.0
|
||||
* 10 | 1.0 | 0 | 0.25 | 1.0
|
||||
*
|
||||
* To check:
|
||||
* [ ] Opinions are saved/loaded accross restart
|
||||
* [ ] Opinions are transmitted to friends
|
||||
* [ ] Opinions are transmitted to friends when updated
|
||||
*
|
||||
* To do:
|
||||
* [ ] Add debug info
|
||||
* [ ] Test the whole thing
|
||||
* [X] Implement a system to allow not storing info when we don't have it
|
||||
*/
|
||||
|
||||
const int32_t REPUTATION_OFFSET = 100000;
|
||||
const int32_t LOWER_LIMIT = -100;
|
||||
const int32_t UPPER_LIMIT = 100;
|
||||
|
||||
int32_t ConvertFromSerialised(uint32_t value, bool limit)
|
||||
{
|
||||
int32_t converted = ((int32_t) value) - REPUTATION_OFFSET ;
|
||||
if (limit)
|
||||
{
|
||||
if (converted < LOWER_LIMIT)
|
||||
{
|
||||
converted = LOWER_LIMIT;
|
||||
}
|
||||
if (converted > UPPER_LIMIT)
|
||||
{
|
||||
converted = UPPER_LIMIT;
|
||||
}
|
||||
}
|
||||
return converted;
|
||||
}
|
||||
|
||||
uint32_t ConvertToSerialised(int32_t value, bool limit)
|
||||
{
|
||||
if (limit)
|
||||
{
|
||||
if (value < LOWER_LIMIT)
|
||||
{
|
||||
value = LOWER_LIMIT;
|
||||
}
|
||||
if (value > UPPER_LIMIT)
|
||||
{
|
||||
value = UPPER_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
value += REPUTATION_OFFSET;
|
||||
if (value < 0)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
return (uint32_t) value;
|
||||
}
|
||||
static const uint32_t LOWER_LIMIT = 0; // used to filter valid Opinion values from serialized data
|
||||
static const uint32_t UPPER_LIMIT = 2; // used to filter valid Opinion values from serialized data
|
||||
static const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; // reputation under which the peer gets killed
|
||||
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 ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week.
|
||||
static const int kReputationRequestPeriod = 600; // 10 mins
|
||||
static const int kReputationStoreWait = 180; // 3 minutes.
|
||||
|
||||
|
||||
|
||||
@ -131,9 +145,10 @@ p3GxsReputation::p3GxsReputation(p3LinkMgr *lm)
|
||||
mRequestTime = 0;
|
||||
mStoreTime = 0;
|
||||
mReputationsUpdated = false;
|
||||
mLastActiveFriendsUpdate = 0 ;
|
||||
mAverageActiveFriends = 0 ;
|
||||
}
|
||||
|
||||
|
||||
const std::string GXS_REPUTATION_APP_NAME = "gxsreputation";
|
||||
const uint16_t GXS_REPUTATION_APP_MAJOR_VERSION = 1;
|
||||
const uint16_t GXS_REPUTATION_APP_MINOR_VERSION = 0;
|
||||
@ -150,13 +165,30 @@ RsServiceInfo p3GxsReputation::getServiceInfo()
|
||||
GXS_REPUTATION_MIN_MINOR_VERSION);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int p3GxsReputation::tick()
|
||||
{
|
||||
processIncoming();
|
||||
sendPackets();
|
||||
|
||||
time_t now = time(NULL);
|
||||
|
||||
if(mLastActiveFriendsUpdate + ACTIVE_FRIENDS_UPDATE_PERIOD < now)
|
||||
{
|
||||
updateActiveFriends() ;
|
||||
cleanup() ;
|
||||
|
||||
mLastActiveFriendsUpdate = now ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
static time_t last_debug_print = time(NULL) ;
|
||||
|
||||
if(now > 10+last_debug_print)
|
||||
{
|
||||
last_debug_print = now ;
|
||||
debug_print() ;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -165,7 +197,53 @@ int p3GxsReputation::status()
|
||||
return 1;
|
||||
}
|
||||
|
||||
void p3GxsReputation::cleanup()
|
||||
{
|
||||
// remove opinions from friends that havn't been seen online for more than the specified delay
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::cleanup() " << std::endl;
|
||||
#endif
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": not implemented. TODO!" << std::endl;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
RsPeerDetails details ;
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " " << *it << ": last seen " << now - details.lastConnect << " secs ago" << std::endl;
|
||||
#endif
|
||||
|
||||
if(rsPeers->getPeerDetails(*it, details) && now < details.lastConnect + ACTIVE_FRIENDS_ONLINE_DELAY)
|
||||
++mAverageActiveFriends ;
|
||||
}
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " new count: " << mAverageActiveFriends << std::endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static RsReputations::Opinion safe_convert_uint32t_to_opinion(uint32_t op)
|
||||
{
|
||||
return RsReputations::Opinion(std::min((uint32_t)op,UPPER_LIMIT)) ;
|
||||
}
|
||||
/***** Implementation ******/
|
||||
|
||||
bool p3GxsReputation::processIncoming()
|
||||
@ -184,41 +262,32 @@ bool p3GxsReputation::processIncoming()
|
||||
switch(item->PacketSubType())
|
||||
{
|
||||
default:
|
||||
case RS_PKT_SUBTYPE_GXSREPUTATION_CONFIG_ITEM:
|
||||
case RS_PKT_SUBTYPE_GXSREPUTATION_SET_ITEM:
|
||||
case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM:
|
||||
case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM:
|
||||
std::cerr << "p3GxsReputation::processingIncoming() Unknown Item";
|
||||
std::cerr << std::endl;
|
||||
itemOk = false;
|
||||
break;
|
||||
|
||||
case RS_PKT_SUBTYPE_GXSREPUTATION_REQUEST_ITEM:
|
||||
case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM:
|
||||
{
|
||||
RsGxsReputationRequestItem *requestItem =
|
||||
dynamic_cast<RsGxsReputationRequestItem *>(item);
|
||||
RsGxsReputationRequestItem *requestItem = dynamic_cast<RsGxsReputationRequestItem *>(item);
|
||||
if (requestItem)
|
||||
{
|
||||
SendReputations(requestItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemOk = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RS_PKT_SUBTYPE_GXSREPUTATION_UPDATE_ITEM:
|
||||
case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM:
|
||||
{
|
||||
RsGxsReputationUpdateItem *updateItem =
|
||||
dynamic_cast<RsGxsReputationUpdateItem *>(item);
|
||||
RsGxsReputationUpdateItem *updateItem = dynamic_cast<RsGxsReputationUpdateItem *>(item);
|
||||
|
||||
if (updateItem)
|
||||
{
|
||||
RecvReputations(updateItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemOk = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -237,8 +306,9 @@ bool p3GxsReputation::processIncoming()
|
||||
|
||||
bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request)
|
||||
{
|
||||
std::cerr << "p3GxsReputation::SendReputations()";
|
||||
std::cerr << std::endl;
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::SendReputations()" << std::endl;
|
||||
#endif
|
||||
|
||||
RsPeerId peerId = request->PeerId();
|
||||
time_t last_update = request->mLastUpdate;
|
||||
@ -252,12 +322,13 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request)
|
||||
int count = 0;
|
||||
int totalcount = 0;
|
||||
RsGxsReputationUpdateItem *pkt = new RsGxsReputationUpdateItem();
|
||||
|
||||
pkt->PeerId(peerId);
|
||||
for(;tit != mUpdated.end(); ++tit)
|
||||
{
|
||||
/* find */
|
||||
std::map<RsGxsId, Reputation>::iterator rit;
|
||||
rit = mReputations.find(tit->second);
|
||||
std::map<RsGxsId, Reputation>::iterator rit = mReputations.find(tit->second);
|
||||
|
||||
if (rit == mReputations.end())
|
||||
{
|
||||
std::cerr << "p3GxsReputation::SendReputations() ERROR Missing Reputation";
|
||||
@ -275,8 +346,9 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request)
|
||||
}
|
||||
|
||||
RsGxsId gxsId = rit->first;
|
||||
pkt->mOpinions[gxsId] = ConvertToSerialised(rit->second.mOwnOpinion, true);
|
||||
pkt->mOpinions[gxsId] = rit->second.mOwnOpinion;
|
||||
pkt->mLatestUpdate = rit->second.mOwnOpinionTs;
|
||||
|
||||
if (pkt->mLatestUpdate == (uint32_t) now)
|
||||
{
|
||||
// if we could possibly get another Update at this point (same second).
|
||||
@ -289,10 +361,13 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request)
|
||||
|
||||
if (count > kMaximumSetSize)
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::SendReputations() Sending Full Packet";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
sendItem(pkt);
|
||||
|
||||
pkt = new RsGxsReputationUpdateItem();
|
||||
pkt->PeerId(peerId);
|
||||
count = 0;
|
||||
@ -301,8 +376,10 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request)
|
||||
|
||||
if (!pkt->mOpinions.empty())
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::SendReputations() Sending Final Packet";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
sendItem(pkt);
|
||||
}
|
||||
@ -311,52 +388,125 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request)
|
||||
delete pkt;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::SendReputations() Total Count: " << totalcount;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void p3GxsReputation::locked_updateOpinion(const RsPeerId& from,const RsGxsId& about,RsReputations::Opinion op)
|
||||
{
|
||||
/* find matching Reputation */
|
||||
std::map<RsGxsId, Reputation>::iterator rit = mReputations.find(about);
|
||||
|
||||
RsReputations::Opinion new_opinion = safe_convert_uint32t_to_opinion(op);
|
||||
RsReputations::Opinion old_opinion = RsReputations::OPINION_NEUTRAL ; // default if not set
|
||||
|
||||
bool updated = false ;
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::update opinion of " << about << " from " << from << " to " << op << std::endl;
|
||||
#endif
|
||||
// now 4 cases;
|
||||
// Opinion already stored
|
||||
// New opinion is same: nothing to do
|
||||
// New opinion is different: if neutral, remove entry
|
||||
// Nothing stored
|
||||
// New opinion is neutral: nothing to do
|
||||
// New opinion is != 1: create entry and store
|
||||
|
||||
if (rit == mReputations.end())
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " no preview record"<< std::endl;
|
||||
#endif
|
||||
|
||||
if(new_opinion != RsReputations::OPINION_NEUTRAL)
|
||||
{
|
||||
mReputations[about] = Reputation(about);
|
||||
rit = mReputations.find(about);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " no changes!"<< std::endl;
|
||||
#endif
|
||||
return ; // nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
Reputation& reputation = rit->second;
|
||||
|
||||
std::map<RsPeerId,RsReputations::Opinion>::iterator it2 = reputation.mOpinions.find(from) ;
|
||||
|
||||
if(it2 == reputation.mOpinions.end())
|
||||
{
|
||||
if(new_opinion != RsReputations::OPINION_NEUTRAL)
|
||||
{
|
||||
reputation.mOpinions[from] = new_opinion; // filters potentially tweaked reputation score sent by friend
|
||||
updated = true ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
old_opinion = it2->second ;
|
||||
|
||||
if(new_opinion == RsReputations::OPINION_NEUTRAL)
|
||||
{
|
||||
reputation.mOpinions.erase(it2) ; // don't store when the opinion is neutral
|
||||
updated = true ;
|
||||
}
|
||||
else if(new_opinion != old_opinion)
|
||||
{
|
||||
it2->second = new_opinion ;
|
||||
updated = true ;
|
||||
}
|
||||
}
|
||||
|
||||
if(reputation.mOpinions.empty() && reputation.mOwnOpinion == RsReputations::OPINION_NEUTRAL)
|
||||
{
|
||||
mReputations.erase(rit) ;
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " own is neutral and no opinions from friends => remove entry" << std::endl;
|
||||
#endif
|
||||
updated = true ;
|
||||
}
|
||||
else if(updated)
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " reputation changed. re-calculating." << std::endl;
|
||||
#endif
|
||||
reputation.updateReputation(mAverageActiveFriends) ;
|
||||
}
|
||||
|
||||
if(updated)
|
||||
IndicateConfigChanged() ;
|
||||
}
|
||||
|
||||
bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item)
|
||||
{
|
||||
std::cerr << "p3GxsReputation::RecvReputations()";
|
||||
std::cerr << std::endl;
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::RecvReputations() from " << item->PeerId() << std::endl;
|
||||
#endif
|
||||
|
||||
RsPeerId peerid = item->PeerId();
|
||||
|
||||
std::map<RsGxsId, uint32_t>::iterator it;
|
||||
for(it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it)
|
||||
for( std::map<RsGxsId, uint32_t>::iterator it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it)
|
||||
{
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
|
||||
/* find matching Reputation */
|
||||
std::map<RsGxsId, Reputation>::iterator rit;
|
||||
RsGxsId gxsId(it->first);
|
||||
|
||||
rit = mReputations.find(gxsId);
|
||||
if (rit == mReputations.end())
|
||||
{
|
||||
mReputations[gxsId] = Reputation(gxsId);
|
||||
rit = mReputations.find(gxsId);
|
||||
locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second));
|
||||
}
|
||||
|
||||
Reputation &reputation = rit->second;
|
||||
reputation.mOpinions[peerid] = ConvertFromSerialised(it->second, true);
|
||||
updateLatestUpdate(peerid,item->mLatestUpdate);
|
||||
|
||||
int previous = reputation.mReputation;
|
||||
if (previous != reputation.CalculateReputation())
|
||||
{
|
||||
// updated from the network.
|
||||
mUpdatedReputations.insert(gxsId);
|
||||
}
|
||||
}
|
||||
updateLatestUpdate(peerid, item->mLatestUpdate);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid, time_t ts)
|
||||
bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid,time_t latest_update)
|
||||
{
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
|
||||
@ -367,11 +517,12 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid, time_t ts)
|
||||
mConfig[peerid] = ReputationConfig(peerid);
|
||||
it = mConfig.find(peerid) ;
|
||||
}
|
||||
it->second.mLatestUpdate = ts;
|
||||
it->second.mLatestUpdate = latest_update ;
|
||||
|
||||
mReputationsUpdated = true;
|
||||
// Switched to periodic save due to scale of data.
|
||||
//IndicateConfigChanged();
|
||||
|
||||
IndicateConfigChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -380,14 +531,75 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid, time_t ts)
|
||||
* Opinion
|
||||
****/
|
||||
|
||||
bool p3GxsReputation::updateOpinion(const RsGxsId& gxsid, int opinion)
|
||||
bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::ReputationInfo& info)
|
||||
{
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "getReputationInfo() for " << gxsid << std::endl;
|
||||
#endif
|
||||
|
||||
std::map<RsGxsId,Reputation>::const_iterator it = mReputations.find(gxsid);
|
||||
|
||||
if (it == mReputations.end())
|
||||
{
|
||||
info.mOwnOpinion = RsReputations::OPINION_NEUTRAL ;
|
||||
info.mFriendAverage = RsReputations::OPINION_NEUTRAL ;
|
||||
info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ;
|
||||
info.mAssessment = RsReputations::ASSESSMENT_OK ;
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " no information present. Returning default. OwnOp = " << info.mOwnOpinion << ", overall score=" << info.mAssessment << std::endl;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
info.mOwnOpinion = RsReputations::Opinion(it->second.mOwnOpinion) ;
|
||||
info.mOverallReputationScore = it->second.mReputation ;
|
||||
info.mFriendAverage = it->second.mFriendAverage ;
|
||||
|
||||
if(info.mOverallReputationScore > REPUTATION_ASSESSMENT_THRESHOLD_X1)
|
||||
info.mAssessment = RsReputations::ASSESSMENT_OK ;
|
||||
else
|
||||
info.mAssessment = RsReputations::ASSESSMENT_BAD ;
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " information present. OwnOp = " << info.mOwnOpinion << ", overall score=" << info.mAssessment << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool p3GxsReputation::isIdentityBanned(const RsGxsId &id)
|
||||
{
|
||||
RsReputations::ReputationInfo info ;
|
||||
|
||||
getReputationInfo(id,info) ;
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "isIdentityBanned(): returning " << (info.mAssessment == RsReputations::ASSESSMENT_BAD) << " for GXS id " << id << std::endl;
|
||||
#endif
|
||||
return info.mAssessment == RsReputations::ASSESSMENT_BAD ;
|
||||
}
|
||||
|
||||
bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const 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;
|
||||
|
||||
/* find matching Reputation */
|
||||
rit = mReputations.find(gxsid);
|
||||
|
||||
if (rit == mReputations.end())
|
||||
{
|
||||
mReputations[gxsid] = Reputation(gxsid);
|
||||
@ -420,14 +632,15 @@ bool p3GxsReputation::updateOpinion(const RsGxsId& gxsid, int opinion)
|
||||
time_t now = time(NULL);
|
||||
reputation.mOwnOpinion = opinion;
|
||||
reputation.mOwnOpinionTs = now;
|
||||
reputation.CalculateReputation();
|
||||
reputation.updateReputation(mAverageActiveFriends);
|
||||
|
||||
mUpdated.insert(std::make_pair(now, gxsid));
|
||||
mUpdatedReputations.insert(gxsid);
|
||||
|
||||
mReputationsUpdated = true;
|
||||
|
||||
// Switched to periodic save due to scale of data.
|
||||
//IndicateConfigChanged();
|
||||
IndicateConfigChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -448,6 +661,9 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list<RsItem*> &savelist)
|
||||
cleanup = true;
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::saveList()" << std::endl;
|
||||
#endif
|
||||
/* save */
|
||||
std::map<RsPeerId, ReputationConfig>::iterator it;
|
||||
for(it = mConfig.begin(); it != mConfig.end(); ++it)
|
||||
@ -459,7 +675,7 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list<RsItem*> &savelist)
|
||||
}
|
||||
|
||||
RsGxsReputationConfigItem *item = new RsGxsReputationConfigItem();
|
||||
item->mPeerId = it->first.toStdString();
|
||||
item->mPeerId = it->first;
|
||||
item->mLatestUpdate = it->second.mLatestUpdate;
|
||||
item->mLastQuery = it->second.mLastQuery;
|
||||
savelist.push_back(item);
|
||||
@ -470,16 +686,15 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list<RsItem*> &savelist)
|
||||
for(rit = mReputations.begin(); rit != mReputations.end(); ++rit, count++)
|
||||
{
|
||||
RsGxsReputationSetItem *item = new RsGxsReputationSetItem();
|
||||
item->mGxsId = rit->first.toStdString();
|
||||
item->mOwnOpinion = ConvertToSerialised(rit->second.mOwnOpinion, false);
|
||||
item->mOwnOpinionTs = rit->second.mOwnOpinionTs;
|
||||
item->mReputation = ConvertToSerialised(rit->second.mReputation, false);
|
||||
item->mGxsId = rit->first;
|
||||
item->mOwnOpinion = rit->second.mOwnOpinion;
|
||||
item->mOwnOpinionTS = rit->second.mOwnOpinionTs;
|
||||
|
||||
std::map<RsPeerId, int32_t>::iterator oit;
|
||||
std::map<RsPeerId, RsReputations::Opinion>::iterator oit;
|
||||
for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit)
|
||||
{
|
||||
// should be already limited.
|
||||
item->mOpinions[oit->first.toStdString()] = ConvertToSerialised(oit->second, false);
|
||||
item->mOpinions[oit->first] = (uint32_t)oit->second;
|
||||
}
|
||||
|
||||
savelist.push_back(item);
|
||||
@ -495,6 +710,9 @@ void p3GxsReputation::saveDone()
|
||||
|
||||
bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::saveList()" << std::endl;
|
||||
#endif
|
||||
std::list<RsItem *>::iterator it;
|
||||
std::set<RsPeerId> peerSet;
|
||||
|
||||
@ -515,9 +733,8 @@ bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
|
||||
}
|
||||
RsGxsReputationSetItem *set = dynamic_cast<RsGxsReputationSetItem *>(*it);
|
||||
if (set)
|
||||
{
|
||||
loadReputationSet(set, peerSet);
|
||||
}
|
||||
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
@ -530,6 +747,9 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std:
|
||||
|
||||
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);
|
||||
@ -542,26 +762,24 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std:
|
||||
Reputation &reputation = mReputations[gxsId];
|
||||
|
||||
// install opinions.
|
||||
std::map<std::string, uint32_t>::const_iterator oit;
|
||||
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] = ConvertFromSerialised(oit->second, true);
|
||||
}
|
||||
reputation.mOpinions[peerId] = safe_convert_uint32t_to_opinion(oit->second);
|
||||
}
|
||||
|
||||
reputation.mOwnOpinion = ConvertFromSerialised(item->mOwnOpinion, false);
|
||||
reputation.mOwnOpinionTs = item->mOwnOpinionTs;
|
||||
reputation.mOwnOpinion = item->mOwnOpinion;
|
||||
reputation.mOwnOpinionTs = item->mOwnOpinionTS;
|
||||
|
||||
// if dropping entries has changed the score -> must update.
|
||||
int previous = ConvertFromSerialised(item->mReputation, false);
|
||||
if (previous != reputation.CalculateReputation())
|
||||
{
|
||||
mUpdatedReputations.insert(gxsId);
|
||||
}
|
||||
|
||||
float old_reputation = reputation.mReputation ;
|
||||
|
||||
if(old_reputation != reputation.updateReputation(mAverageActiveFriends))
|
||||
mUpdatedReputations.insert(gxsId) ;
|
||||
|
||||
mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId));
|
||||
return true;
|
||||
@ -572,9 +790,6 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std:
|
||||
* Send Requests.
|
||||
****/
|
||||
|
||||
const int kReputationRequestPeriod = 3600;
|
||||
const int kReputationStoreWait = 180; // 3 minutes.
|
||||
|
||||
int p3GxsReputation::sendPackets()
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
@ -585,7 +800,7 @@ int p3GxsReputation::sendPackets()
|
||||
storeTime = mStoreTime;
|
||||
}
|
||||
|
||||
if (now - requestTime > kReputationRequestPeriod)
|
||||
if (now > requestTime + kReputationRequestPeriod)
|
||||
{
|
||||
sendReputationRequests();
|
||||
|
||||
@ -629,48 +844,41 @@ void p3GxsReputation::sendReputationRequests()
|
||||
|
||||
mLinkMgr->getOnlineList(idList);
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::sendReputationRequests()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* prepare packets */
|
||||
std::list<RsPeerId>::iterator it;
|
||||
for(it = idList.begin(); it != idList.end(); ++it)
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::sendReputationRequest() To: " << *it;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
sendReputationRequest(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int p3GxsReputation::sendReputationRequest(RsPeerId peerid)
|
||||
{
|
||||
std::cerr << "p3GxsReputation::sendReputationRequest(" << peerid << ")";
|
||||
std::cerr << std::endl;
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " p3GxsReputation::sendReputationRequest(" << peerid << ") " ;
|
||||
#endif
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
/* */
|
||||
RsGxsReputationRequestItem *requestItem =
|
||||
new RsGxsReputationRequestItem();
|
||||
|
||||
RsGxsReputationRequestItem *requestItem = new RsGxsReputationRequestItem();
|
||||
requestItem->PeerId(peerid);
|
||||
|
||||
{
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
|
||||
/* find the last timestamp we have */
|
||||
std::map<RsPeerId, ReputationConfig>::iterator it;
|
||||
it = mConfig.find(peerid);
|
||||
std::map<RsPeerId, ReputationConfig>::iterator it = mConfig.find(peerid);
|
||||
|
||||
if (it != mConfig.end())
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " lastUpdate = " << now - it->second.mLatestUpdate << " secs ago. Requesting only more recent." << std::endl;
|
||||
#endif
|
||||
requestItem->mLastUpdate = it->second.mLatestUpdate;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << " lastUpdate = never. Requesting all!" << std::endl;
|
||||
#endif
|
||||
// get whole list.
|
||||
requestItem->mLastUpdate = 0;
|
||||
}
|
||||
@ -680,4 +888,44 @@ int p3GxsReputation::sendReputationRequest(RsPeerId peerid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
float Reputation::updateReputation(uint32_t average_active_friends)
|
||||
{
|
||||
// the calculation of reputation makes the whole thing
|
||||
|
||||
int friend_total = 0;
|
||||
|
||||
// accounts for all friends. Neutral opinions count for 1-1=0
|
||||
|
||||
for(std::map<RsPeerId,RsReputations::Opinion>::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it)
|
||||
friend_total += it->second - 1;
|
||||
|
||||
if(mOpinions.empty()) // includes the case of no friends!
|
||||
mFriendAverage = 1.0f ;
|
||||
else
|
||||
mFriendAverage = 1.0+friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size()));
|
||||
|
||||
if(mOwnOpinion == RsReputations::OPINION_NEUTRAL)
|
||||
mReputation = mFriendAverage ;
|
||||
else
|
||||
mReputation = (float)mOwnOpinion ;
|
||||
|
||||
return float(mOwnOpinion) ;
|
||||
}
|
||||
|
||||
void p3GxsReputation::debug_print()
|
||||
{
|
||||
std::cerr << "Reputations database: " << std::endl;
|
||||
std::cerr << " Average number of peers: " << mAverageActiveFriends << std::endl;
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
for(std::map<RsGxsId,Reputation>::const_iterator it(mReputations.begin());it!=mReputations.end();++it)
|
||||
{
|
||||
std::cerr << " ID=" << it->first << ", own: " << it->second.mOwnOpinion << ", Friend average: " << it->second.mFriendAverage << ", global_score: " << it->second.mReputation
|
||||
<< ", last own update: " << now - it->second.mOwnOpinionTs << " secs ago." << std::endl;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "serialiser/rsgxsreputationitems.h"
|
||||
|
||||
#include "retroshare/rsidentity.h"
|
||||
#include "retroshare/rsreputations.h"
|
||||
#include "services/p3service.h"
|
||||
|
||||
|
||||
@ -58,19 +59,19 @@ class Reputation
|
||||
{
|
||||
public:
|
||||
Reputation()
|
||||
:mOwnOpinion(0), mOwnOpinionTs(0), mReputation(0) { return; }
|
||||
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { }
|
||||
|
||||
Reputation(const RsGxsId& about)
|
||||
:mGxsId(about), mOwnOpinion(0), mOwnOpinionTs(0), mReputation(0) { return; }
|
||||
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { }
|
||||
|
||||
int32_t CalculateReputation();
|
||||
float updateReputation(uint32_t average_active_friends);
|
||||
|
||||
RsGxsId mGxsId;
|
||||
std::map<RsPeerId, int32_t> mOpinions;
|
||||
std::map<RsPeerId, RsReputations::Opinion> mOpinions;
|
||||
int32_t mOwnOpinion;
|
||||
time_t mOwnOpinionTs;
|
||||
|
||||
int32_t mReputation;
|
||||
float mFriendAverage ;
|
||||
float mReputation;
|
||||
};
|
||||
|
||||
|
||||
@ -80,37 +81,25 @@ int32_t CalculateReputation();
|
||||
*
|
||||
*/
|
||||
|
||||
class p3GxsReputation: public p3Service, public p3Config /* , public pqiMonitor */
|
||||
class p3GxsReputation: public p3Service, public p3Config, public RsReputations /* , public pqiMonitor */
|
||||
{
|
||||
public:
|
||||
p3GxsReputation(p3LinkMgr *lm);
|
||||
virtual RsServiceInfo getServiceInfo();
|
||||
|
||||
/***** Interface for p3idservice *****/
|
||||
|
||||
virtual bool updateOpinion(const RsGxsId& gxsid, int opinion);
|
||||
/***** Interface for RsReputations *****/
|
||||
virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) ;
|
||||
virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) ;
|
||||
virtual bool isIdentityBanned(const RsGxsId& id) ;
|
||||
|
||||
/***** overloaded from p3Service *****/
|
||||
/*!
|
||||
* This retrieves all chat msg items and also (important!)
|
||||
* processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned
|
||||
* (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status
|
||||
* : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar
|
||||
* @see NotifyBase
|
||||
|
||||
*/
|
||||
virtual int tick();
|
||||
virtual int status();
|
||||
|
||||
|
||||
/*!
|
||||
* Interface stuff.
|
||||
*/
|
||||
|
||||
/*************** pqiMonitor callback ***********************/
|
||||
//virtual void statusChange(const std::list<pqipeer> &plist);
|
||||
|
||||
|
||||
/************* from p3Config *******************/
|
||||
virtual RsSerialiser *setupSerialiser() ;
|
||||
virtual bool saveList(bool& cleanup, std::list<RsItem*>&) ;
|
||||
@ -123,22 +112,27 @@ class p3GxsReputation: public p3Service, public p3Config /* , public pqiMonitor
|
||||
|
||||
bool SendReputations(RsGxsReputationRequestItem *request);
|
||||
bool RecvReputations(RsGxsReputationUpdateItem *item);
|
||||
bool updateLatestUpdate(RsPeerId peerid, time_t ts);
|
||||
bool updateLatestUpdate(RsPeerId peerid, time_t latest_update);
|
||||
void updateActiveFriends() ;
|
||||
|
||||
bool loadReputationSet(RsGxsReputationSetItem *item,
|
||||
const std::set<RsPeerId> &peerSet);
|
||||
// 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);
|
||||
|
||||
int sendPackets();
|
||||
void cleanup();
|
||||
void sendReputationRequests();
|
||||
int sendReputationRequest(RsPeerId peerid);
|
||||
|
||||
void debug_print() ;
|
||||
|
||||
private:
|
||||
RsMutex mReputationMtx;
|
||||
|
||||
time_t mLastActiveFriendsUpdate;
|
||||
time_t mRequestTime;
|
||||
time_t mStoreTime;
|
||||
bool mReputationsUpdated;
|
||||
uint32_t mAverageActiveFriends ;
|
||||
|
||||
p3LinkMgr *mLinkMgr;
|
||||
|
||||
|
@ -413,6 +413,8 @@ bool p3IdService:: getIdDetails(const RsGxsId &id, RsIdentityDetails &details)
|
||||
if(details.mNickname.length() > RSID_MAXIMUM_NICKNAME_SIZE*4)
|
||||
details.mNickname = "[too long a name]" ;
|
||||
|
||||
rsReputations->getReputationInfo(id,details.mReputation) ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -421,6 +423,9 @@ bool p3IdService:: getIdDetails(const RsGxsId &id, RsIdentityDetails &details)
|
||||
{
|
||||
details = data.details;
|
||||
details.mLastUsageTS = locked_getLastUsageTS(id) ;
|
||||
|
||||
rsReputations->getReputationInfo(id,details.mReputation) ;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -831,7 +836,7 @@ bool p3IdService::getReputation(const RsGxsId &id, GixsReputation &rep)
|
||||
if (mPublicKeyCache.fetch(id, data))
|
||||
{
|
||||
rep.id = id;
|
||||
rep.score = data.details.mReputation.mOverallScore;
|
||||
rep.score = 0;//data.details.mReputation.mOverallScore;
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "p3IdService::getReputation() id: ";
|
||||
std::cerr << id.toStdString() << " score: " <<
|
||||
@ -1669,14 +1674,14 @@ void RsGxsIdCache::updateServiceString(std::string serviceString)
|
||||
}
|
||||
|
||||
// copy over Reputation scores.
|
||||
details.mReputation = ssdata.score.rep;
|
||||
//details.mReputation = ssdata.score.rep;
|
||||
}
|
||||
else
|
||||
{
|
||||
details.mPgpKnown = false;
|
||||
details.mPgpId.clear();
|
||||
details.mReputation.updateIdScore(false, false);
|
||||
details.mReputation.update();
|
||||
//details.mReputation.updateIdScore(false, false);
|
||||
//details.mReputation.update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "gui/msgs/MessageComposer.h"
|
||||
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <retroshare/rsreputations.h>
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
#include "retroshare/rsmsgs.h"
|
||||
#include <iostream>
|
||||
@ -92,18 +93,9 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Type);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->toolButton_Reputation);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->line_RatingOverall);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->line_RatingImplicit);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->line_RatingOwn);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->line_RatingPeers);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->repModButton);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->repMod_Accept);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->repMod_Ban);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->repMod_Negative);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->repMod_Positive);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->repMod_Custom);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->repMod_spinBox);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->ownOpinion_CB);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->overallOpinion_TF);
|
||||
mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->neighborNodesOpinion_TF);
|
||||
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname);
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName);
|
||||
@ -113,10 +105,7 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Type);
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName);
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed);
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOverall);
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingImplicit);
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOwn);
|
||||
mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingPeers);
|
||||
//mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOverall);
|
||||
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname);
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId);
|
||||
@ -125,10 +114,6 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Type);
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName);
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed);
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingOverall);
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingImplicit);
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingOwn);
|
||||
mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingPeers);
|
||||
|
||||
//mStateHelper->addWidget(IDDIALOG_REPLIST, ui->treeWidget_RepList);
|
||||
//mStateHelper->addLoadPlaceholder(IDDIALOG_REPLIST, ui->treeWidget_RepList);
|
||||
@ -147,7 +132,7 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||
|
||||
connect(ui->filterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterComboBoxChanged()));
|
||||
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
|
||||
connect(ui->repModButton, SIGNAL(clicked()), this, SLOT(modifyReputation()));
|
||||
connect(ui->ownOpinion_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(modifyReputation()));
|
||||
|
||||
connect(ui->messageButton, SIGNAL(clicked()), this, SLOT(sendMsg()));
|
||||
|
||||
@ -197,7 +182,7 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||
|
||||
// Hiding RepList until that part is finished.
|
||||
//ui->treeWidget_RepList->setVisible(false);
|
||||
ui->toolButton_Reputation->setVisible(false);
|
||||
|
||||
#ifndef UNFINISHED
|
||||
ui->todoPushButton->hide() ;
|
||||
#endif
|
||||
@ -225,8 +210,8 @@ IdDialog::IdDialog(QWidget *parent) :
|
||||
processSettings(true);
|
||||
|
||||
// hide reputation sice it's currently unused
|
||||
ui->reputationGroupBox->hide();
|
||||
ui->tweakGroupBox->hide();
|
||||
//ui->reputationGroupBox->hide();
|
||||
//ui->tweakGroupBox->hide();
|
||||
}
|
||||
|
||||
IdDialog::~IdDialog()
|
||||
@ -652,36 +637,9 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
else
|
||||
ui->lineEdit_Type->setText(tr("Anonymous identity")) ;
|
||||
|
||||
// if (isOwnId)
|
||||
// {
|
||||
// ui->radioButton_IdYourself->setChecked(true);
|
||||
// }
|
||||
// else if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID)
|
||||
// {
|
||||
// if (data.mPgpKnown)
|
||||
// {
|
||||
// if (rsPeers->isGPGAccepted(data.mPgpId))
|
||||
// {
|
||||
// ui->radioButton_IdFriend->setChecked(true);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ui->radioButton_IdFOF->setChecked(true);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ui->radioButton_IdOther->setChecked(true);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ui->radioButton_IdPseudo->setChecked(true);
|
||||
// }
|
||||
|
||||
if (isOwnId)
|
||||
{
|
||||
mStateHelper->setWidgetEnabled(ui->toolButton_Reputation, false);
|
||||
mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, false);
|
||||
ui->editIdentity->setEnabled(true);
|
||||
ui->removeIdentity->setEnabled(true);
|
||||
ui->chatIdentity->setEnabled(false);
|
||||
@ -690,7 +648,7 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
else
|
||||
{
|
||||
// No Reputation yet!
|
||||
mStateHelper->setWidgetEnabled(ui->toolButton_Reputation, /*true*/ false);
|
||||
mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, true);
|
||||
ui->editIdentity->setEnabled(false);
|
||||
ui->removeIdentity->setEnabled(false);
|
||||
ui->chatIdentity->setEnabled(true);
|
||||
@ -698,9 +656,8 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
}
|
||||
|
||||
/* now fill in the reputation information */
|
||||
ui->line_RatingOverall->setText("Overall Rating TODO");
|
||||
ui->line_RatingOwn->setText("Own Rating TODO");
|
||||
|
||||
#ifdef SUSPENDED
|
||||
if (data.mPgpKnown)
|
||||
{
|
||||
ui->line_RatingImplicit->setText(tr("+50 Known PGP"));
|
||||
@ -713,25 +670,28 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
{
|
||||
ui->line_RatingImplicit->setText(tr("+5 Anon Id"));
|
||||
}
|
||||
|
||||
{
|
||||
QString rating = QString::number(data.mReputation.mOverallScore);
|
||||
ui->line_RatingOverall->setText(rating);
|
||||
}
|
||||
|
||||
{
|
||||
QString rating = QString::number(data.mReputation.mIdScore);
|
||||
ui->line_RatingImplicit->setText(rating);
|
||||
}
|
||||
|
||||
{
|
||||
QString rating = QString::number(data.mReputation.mOwnOpinion);
|
||||
ui->line_RatingOwn->setText(rating);
|
||||
}
|
||||
#endif
|
||||
|
||||
RsReputations::ReputationInfo info ;
|
||||
rsReputations->getReputationInfo(RsGxsId(data.mMeta.mGroupId),info) ;
|
||||
|
||||
ui->neighborNodesOpinion_TF->setText(QString::number(info.mOverallReputationScore-1.0f));
|
||||
|
||||
ui->overallOpinion_TF->setText(QString::number(info.mOverallReputationScore-1.0f) +" ("+
|
||||
((info.mAssessment == RsReputations::ASSESSMENT_OK)? tr("OK") : tr("Banned")) +")" ) ;
|
||||
|
||||
switch(info.mOwnOpinion)
|
||||
{
|
||||
QString rating = QString::number(data.mReputation.mPeerOpinion);
|
||||
ui->line_RatingPeers->setText(rating);
|
||||
case RsReputations::OPINION_NEGATIVE: ui->ownOpinion_CB->setCurrentIndex(0); break ;
|
||||
case RsReputations::OPINION_NEUTRAL : ui->ownOpinion_CB->setCurrentIndex(1); break ;
|
||||
case RsReputations::OPINION_POSITIVE: ui->ownOpinion_CB->setCurrentIndex(2); break ;
|
||||
default:
|
||||
std::cerr << "Unexpected value in own opinion: " << info.mOwnOpinion << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,46 +704,37 @@ void IdDialog::modifyReputation()
|
||||
|
||||
RsGxsId id(ui->lineEdit_KeyId->text().toStdString());
|
||||
|
||||
int mod = 0;
|
||||
if (ui->repMod_Accept->isChecked())
|
||||
RsReputations::Opinion op ;
|
||||
|
||||
switch(ui->ownOpinion_CB->currentIndex())
|
||||
{
|
||||
mod += 100;
|
||||
}
|
||||
else if (ui->repMod_Positive->isChecked())
|
||||
{
|
||||
mod += 10;
|
||||
}
|
||||
else if (ui->repMod_Negative->isChecked())
|
||||
{
|
||||
mod += -10;
|
||||
}
|
||||
else if (ui->repMod_Ban->isChecked())
|
||||
{
|
||||
mod += -100;
|
||||
}
|
||||
else if (ui->repMod_Custom->isChecked())
|
||||
{
|
||||
mod += ui->repMod_spinBox->value();
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid
|
||||
return;
|
||||
case 0: op = RsReputations::OPINION_NEGATIVE ; break ;
|
||||
case 1: op = RsReputations::OPINION_NEUTRAL ; break ;
|
||||
case 2: op = RsReputations::OPINION_POSITIVE ; break ;
|
||||
default:
|
||||
std::cerr << "Wrong value from opinion combobox. Bug??" << std::endl;
|
||||
|
||||
}
|
||||
rsReputations->setOwnOpinion(id,op) ;
|
||||
|
||||
#ifdef ID_DEBUG
|
||||
std::cerr << "IdDialog::modifyReputation() ID: " << id << " Mod: " << mod;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
#ifdef SUSPENDED
|
||||
// Cyril: apparently the old reputation system was in used here. It's based on GXS data exchange, and probably not
|
||||
// very efficient because of this.
|
||||
|
||||
uint32_t token;
|
||||
if (!rsIdentity->submitOpinion(token, id, false, mod))
|
||||
if (!rsIdentity->submitOpinion(token, id, false, op))
|
||||
{
|
||||
#ifdef ID_DEBUG
|
||||
std::cerr << "IdDialog::modifyReputation() Error submitting Opinion";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ID_DEBUG
|
||||
std::cerr << "IdDialog::modifyReputation() queuingRequest(), token: " << token;
|
||||
@ -792,7 +743,7 @@ void IdDialog::modifyReputation()
|
||||
|
||||
// trigger refresh when finished.
|
||||
// basic / anstype are not needed.
|
||||
mIdQueue->queueRequest(token, 0, 0, IDDIALOG_REFRESH);
|
||||
requestIdDetails();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>826</width>
|
||||
<height>752</height>
|
||||
<height>757</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -483,7 +483,90 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="neighborNodesOpinion_TF">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html></string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Your opinion:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Neighbor nodes:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="ownOpinion_CB">
|
||||
<property name="toolTip">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself,</p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and is shared among friends. A final score is calculated according to a formula that accounts your own opinion and your friends' opinions about someone:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> S = own_opinion * a + friends_opinion * (1-a)</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The factor 'a' depends on the type of ID. </p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- anonymous IDs: </p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- PGP-signed IDs by unknown PGP keys: a=</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">S &lt; -0.5: Posts are not stored, nor forwarded </p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">S &lt; 0.2: Posts are hidden, but still transmitted</p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">S &lt; 0.0: </p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall rating is computed in such a way that it is not possible for a single person to deterministically change someone's status at neighbor nodes.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Negative</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../icons/yellow_biohazard64.png</normaloff>../icons/yellow_biohazard64.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Neutral</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Positive</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="overallOpinion_TF">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html></string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
@ -492,158 +575,12 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Overall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="line_RatingOverall">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Implicit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="line_RatingImplicit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Opinion</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="line_RatingOwn">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Peers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="line_RatingPeers">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
<string>Overall:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_Reputation">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit reputation</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/edit_24.png</normaloff>:/images/edit_24.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="tweakGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Tweak Opinion</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="repMod_Accept">
|
||||
<property name="text">
|
||||
<string>Accept (+100)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="repMod_Positive">
|
||||
<property name="text">
|
||||
<string>Positive (+10)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="repMod_Negative">
|
||||
<property name="text">
|
||||
<string>Negative (-10)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="repMod_Ban">
|
||||
<property name="text">
|
||||
<string>Ban (-100)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="repMod_Custom">
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="repMod_spinBox">
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="repModButton">
|
||||
<property name="text">
|
||||
<string>Modify</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -730,9 +667,6 @@
|
||||
<tabstop>lineEdit_KeyId</tabstop>
|
||||
<tabstop>lineEdit_GpgId</tabstop>
|
||||
<tabstop>lineEdit_GpgName</tabstop>
|
||||
<tabstop>line_RatingOverall</tabstop>
|
||||
<tabstop>line_RatingImplicit</tabstop>
|
||||
<tabstop>line_RatingOwn</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
|
@ -42,6 +42,8 @@
|
||||
#define TYPE_UNKNOWN_ID 3
|
||||
#define TYPE_CREATE_ID 4
|
||||
|
||||
#define BANNED_ICON ":/icons/yellow_biohazard64.png"
|
||||
|
||||
#define IDCHOOSER_REFRESH 1
|
||||
|
||||
//#define IDCHOOSER_DEBUG
|
||||
@ -148,6 +150,10 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail
|
||||
case GXS_ID_DETAILS_TYPE_DONE:
|
||||
GxsIdDetails::getIcons(details, icons);
|
||||
break;
|
||||
|
||||
case GXS_ID_DETAILS_TYPE_BANNED:
|
||||
icons.push_back(QIcon(BANNED_ICON)) ;
|
||||
break;
|
||||
}
|
||||
|
||||
chooser->setItemData(index, QString("%1_%2").arg((type == GXS_ID_DETAILS_TYPE_DONE) ? TYPE_FOUND_ID : TYPE_UNKNOWN_ID).arg(text), ROLE_SORT);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <math.h>
|
||||
#include "GxsIdDetails.h"
|
||||
#include "retroshare-gui/RsAutoUpdatePage.h"
|
||||
#include "retroshare/rsreputations.h"
|
||||
|
||||
#include <retroshare/rspeers.h>
|
||||
|
||||
@ -40,6 +41,7 @@
|
||||
#define IMAGE_PGPKNOWN ":/images/contact.png"
|
||||
#define IMAGE_PGPUNKNOWN ":/images/tags/pgp-unknown.png"
|
||||
#define IMAGE_ANON ":/images/tags/anon.png"
|
||||
#define IMAGE_BANNED ":/icons/yellow_biohazard64.png"
|
||||
|
||||
#define IMAGE_DEV_AMBASSADOR ":/images/tags/dev-ambassador.png"
|
||||
#define IMAGE_DEV_CONTRIBUTOR ":/images/tags/vote_down.png"
|
||||
@ -821,6 +823,9 @@ QString GxsIdDetails::getNameForType(GxsIdDetailsType type, const RsIdentityDeta
|
||||
case GXS_ID_DETAILS_TYPE_DONE:
|
||||
return getName(details);
|
||||
|
||||
case GXS_ID_DETAILS_TYPE_BANNED:
|
||||
return tr("[Banned]") ;
|
||||
|
||||
case GXS_ID_DETAILS_TYPE_FAILED:
|
||||
return getFailedText(details.mId);
|
||||
}
|
||||
@ -873,6 +878,9 @@ bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, QLi
|
||||
|
||||
QString GxsIdDetails::getName(const RsIdentityDetails &details)
|
||||
{
|
||||
if(rsReputations->isIdentityBanned(details.mId))
|
||||
return tr("[Banned]") ;
|
||||
|
||||
QString name = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE);
|
||||
|
||||
std::list<RsRecognTag>::const_iterator it;
|
||||
@ -887,8 +895,17 @@ QString GxsIdDetails::getName(const RsIdentityDetails &details)
|
||||
QString GxsIdDetails::getComment(const RsIdentityDetails &details)
|
||||
{
|
||||
QString comment;
|
||||
QString nickname ;
|
||||
|
||||
bool banned = rsReputations->isIdentityBanned(details.mId) ;
|
||||
|
||||
if(details.mNickname.empty())
|
||||
nickname = tr("[Unknown]") ;
|
||||
else if(banned)
|
||||
nickname = tr("[Banned]") ;
|
||||
else
|
||||
nickname = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE) ;
|
||||
|
||||
QString nickname = details.mNickname.empty()?tr("[Unknown]"):QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE) ;
|
||||
|
||||
comment = QString("%1:%2<br/>%3:%4").arg(QApplication::translate("GxsIdDetails", "Identity name"),
|
||||
nickname,
|
||||
@ -903,6 +920,7 @@ QString nickname = details.mNickname.empty()?tr("[Unknown]"):QString::fromUtf8(d
|
||||
{
|
||||
/* look up real name */
|
||||
std::string authorName = rsPeers->getGPGName(details.mPgpId);
|
||||
|
||||
comment += QString("%1 [%2]").arg(QString::fromUtf8(authorName.c_str()), QString::fromStdString(details.mPgpId.toStdString()));
|
||||
}
|
||||
else
|
||||
@ -918,6 +936,13 @@ void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList<QIcon> &icon
|
||||
{
|
||||
QPixmap pix ;
|
||||
|
||||
if(rsReputations->isIdentityBanned(details.mId))
|
||||
{
|
||||
icons.clear() ;
|
||||
icons.push_back(QIcon(IMAGE_BANNED)) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(icon_types & ICON_TYPE_AVATAR)
|
||||
{
|
||||
if(details.mAvatar.mSize == 0 || !pix.loadFromData(details.mAvatar.mData, details.mAvatar.mSize, "PNG"))
|
||||
|
@ -39,7 +39,8 @@ enum GxsIdDetailsType
|
||||
GXS_ID_DETAILS_TYPE_EMPTY,
|
||||
GXS_ID_DETAILS_TYPE_LOADING,
|
||||
GXS_ID_DETAILS_TYPE_DONE,
|
||||
GXS_ID_DETAILS_TYPE_FAILED
|
||||
GXS_ID_DETAILS_TYPE_FAILED,
|
||||
GXS_ID_DETAILS_TYPE_BANNED
|
||||
};
|
||||
|
||||
typedef void (*GxsIdDetailsCallbackFunction)(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &data);
|
||||
@ -53,6 +54,7 @@ public:
|
||||
static const int ICON_TYPE_PGP = 0x0002 ;
|
||||
static const int ICON_TYPE_RECOGN = 0x0004 ;
|
||||
static const int ICON_TYPE_ALL = 0x0007 ;
|
||||
static const int ICON_TYPE_REDACTED= 0x0008 ;
|
||||
|
||||
GxsIdDetails();
|
||||
virtual ~GxsIdDetails();
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include "GxsIdTreeWidgetItem.h"
|
||||
#include "GxsIdDetails.h"
|
||||
#include "util/HandleRichText.h"
|
||||
#include "retroshare/rsreputations.h"
|
||||
|
||||
#define BANNED_IMAGE ":/icons/yellow_biohazard64.png"
|
||||
|
||||
/** Constructor */
|
||||
GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, uint32_t icon_mask,QTreeWidget *parent)
|
||||
@ -71,6 +74,10 @@ static void fillGxsIdRSTreeWidgetItemCallback(GxsIdDetailsType type, const RsIde
|
||||
GxsIdDetails::getIcons(details, icons, item->iconTypeMask());
|
||||
item->processResult(true);
|
||||
break;
|
||||
|
||||
case GXS_ID_DETAILS_TYPE_BANNED:
|
||||
icons.push_back(QIcon("BANNED_IMAGE")) ;
|
||||
break ;
|
||||
}
|
||||
|
||||
int column = item->idColumn();
|
||||
@ -139,16 +146,19 @@ void GxsIdRSTreeWidgetItem::setAvatar(const RsGxsImage &avatar)
|
||||
|
||||
QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const
|
||||
{
|
||||
if (column == idColumn()) {
|
||||
switch (role) {
|
||||
case Qt::ToolTipRole:
|
||||
if (column == idColumn())
|
||||
{
|
||||
if (role == Qt::ToolTipRole)
|
||||
{
|
||||
QString t = RSTreeWidgetItem::data(column, role).toString();
|
||||
|
||||
QImage pix;
|
||||
if (mAvatar.mSize == 0 || !pix.loadFromData(mAvatar.mData, mAvatar.mSize, "PNG")) {
|
||||
|
||||
if(mId.isNull())
|
||||
return RSTreeWidgetItem::data(column, role);
|
||||
else if(rsReputations->isIdentityBanned(mId))
|
||||
pix = QImage(BANNED_IMAGE) ;
|
||||
else if (mAvatar.mSize == 0 || !pix.loadFromData(mAvatar.mData, mAvatar.mSize, "PNG"))
|
||||
pix = GxsIdDetails::makeDefaultIcon(mId);
|
||||
}
|
||||
|
||||
int S = QFontMetricsF(font(column)).height();
|
||||
|
||||
@ -160,7 +170,6 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RSTreeWidgetItem::data(column, role);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "util/QtVersion.h"
|
||||
|
||||
#include <retroshare/rsgxsforums.h>
|
||||
#include <retroshare/rsreputations.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
// These should be in retroshare/ folder.
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
@ -57,6 +58,7 @@
|
||||
#define IMAGE_DOWNLOAD ":/images/start.png"
|
||||
#define IMAGE_DOWNLOADALL ":/images/startall.png"
|
||||
#define IMAGE_COPYLINK ":/images/copyrslink.png"
|
||||
#define IMAGE_BIOHAZARD ":/icons/yellow_biohazard64.png"
|
||||
|
||||
#define VIEW_LAST_POST 0
|
||||
#define VIEW_THREADED 1
|
||||
@ -406,6 +408,10 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
|
||||
QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply with private message"), &contextMnu);
|
||||
connect(replyauthorAct, SIGNAL(triggered()), this, SLOT(replytomessage()));
|
||||
|
||||
QAction *flagasbadAct = new QAction(QIcon(IMAGE_BIOHAZARD), tr("Ban this author"), &contextMnu);
|
||||
flagasbadAct->setToolTip(tr("This will block/hide messages from this person, and notify neighbor nodes.")) ;
|
||||
connect(flagasbadAct, SIGNAL(triggered()), this, SLOT(flagpersonasbad()));
|
||||
|
||||
QAction *newthreadAct = new QAction(QIcon(IMAGE_MESSAGE), tr("Start New Thread"), &contextMnu);
|
||||
newthreadAct->setEnabled (IS_GROUP_SUBSCRIBED(mSubscribeFlags));
|
||||
connect(newthreadAct , SIGNAL(triggered()), this, SLOT(createthread()));
|
||||
@ -484,6 +490,8 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
|
||||
contextMnu.addAction(expandAll);
|
||||
contextMnu.addAction(collapseAll);
|
||||
|
||||
contextMnu.addSeparator();
|
||||
contextMnu.addAction(flagasbadAct);
|
||||
contextMnu.addSeparator();
|
||||
contextMnu.addAction(replyauthorAct);
|
||||
|
||||
@ -725,6 +733,9 @@ void GxsForumThreadWidget::insertGroupData()
|
||||
case GXS_ID_DETAILS_TYPE_LOADING:
|
||||
author = GxsIdDetails::getLoadingText(details.mId);
|
||||
break;
|
||||
case GXS_ID_DETAILS_TYPE_BANNED:
|
||||
author = tr("[Banned]") ;
|
||||
break ;
|
||||
case GXS_ID_DETAILS_TYPE_DONE:
|
||||
author = GxsIdDetails::getName(details);
|
||||
break;
|
||||
@ -886,11 +897,20 @@ void GxsForumThreadWidget::fillThreadStatus(QString text)
|
||||
|
||||
QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForumMsg &msg, bool useChildTS, uint32_t filterColumn)
|
||||
{
|
||||
GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_ALL);
|
||||
// Early check for a message that should be hidden because its author
|
||||
// is flagged with a bad reputation
|
||||
|
||||
|
||||
bool redacted = rsReputations->isIdentityBanned(msg.mMeta.mAuthorId) ;
|
||||
|
||||
GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_ALL || (redacted?(GxsIdDetails::ICON_TYPE_REDACTED):0));
|
||||
item->moveToThread(ui->threadTreeWidget->thread());
|
||||
|
||||
QString text;
|
||||
|
||||
if(redacted)
|
||||
item->setText(COLUMN_THREAD_TITLE, tr("[ ... Redacted message ... ]"));
|
||||
else
|
||||
item->setText(COLUMN_THREAD_TITLE, QString::fromUtf8(msg.mMeta.mMsgName.c_str()));
|
||||
|
||||
QDateTime qtime;
|
||||
@ -961,7 +981,6 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
|
||||
}
|
||||
#endif
|
||||
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, msg.mMeta.mMsgStatus);
|
||||
|
||||
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, false);
|
||||
|
||||
return item;
|
||||
@ -970,10 +989,13 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum
|
||||
QTreeWidgetItem *GxsForumThreadWidget::generateMissingItem(const RsGxsMessageId &msgId)
|
||||
{
|
||||
GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(mThreadCompareRole,GxsIdDetails::ICON_TYPE_ALL);
|
||||
|
||||
item->setText(COLUMN_THREAD_TITLE, tr("[ ... Missing Message ... ]"));
|
||||
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msgId.toStdString()));
|
||||
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, true);
|
||||
|
||||
item->setId(RsGxsId(), COLUMN_THREAD_AUTHOR, false); // fixed up columnId()
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -1301,6 +1323,8 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg)
|
||||
return;
|
||||
}
|
||||
|
||||
bool redacted = rsReputations->isIdentityBanned(msg.mMeta.mAuthorId) ;
|
||||
|
||||
mStateHelper->setActive(mTokenTypeMessageData, true);
|
||||
|
||||
QTreeWidgetItem *item = ui->threadTreeWidget->currentItem();
|
||||
@ -1334,9 +1358,20 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg)
|
||||
ui->by_text_label->show() ;
|
||||
ui->by_label->show() ;
|
||||
|
||||
QString extraTxt = RsHtml().formatText(ui->postText->document(), QString::fromUtf8(msg.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS);
|
||||
if(redacted)
|
||||
{
|
||||
QString extraTxt = tr("<p><font color=\"#ff0000\"><b>The author of this message (with ID %1) is banned.</b>").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ;
|
||||
extraTxt += tr("<UL><li><b><font color=\"#ff0000\">Messages from this author are not forwarded. </font></b></li>") ;
|
||||
extraTxt += tr("<li><b><font color=\"#ff0000\">Messages from this author are replaced by this text. </font></b></li></ul>") ;
|
||||
extraTxt += tr("<p><b><font color=\"#ff0000\">You can force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.</font></b></p>") ;
|
||||
|
||||
ui->postText->setHtml(extraTxt);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString extraTxt = RsHtml().formatText(ui->postText->document(), QString::fromUtf8(msg.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS);
|
||||
ui->postText->setHtml(extraTxt);
|
||||
}
|
||||
//ui->threadTitle->setText(QString::fromUtf8(msg.mMeta.mMsgName.c_str()));
|
||||
}
|
||||
|
||||
@ -1685,6 +1720,34 @@ static QString buildReplyHeader(const RsMsgMetaData &meta)
|
||||
return header;
|
||||
}
|
||||
|
||||
void GxsForumThreadWidget::flagpersonasbad()
|
||||
{
|
||||
// no need to use the token system for that, since we just need to find out the author's name, which is in the item.
|
||||
|
||||
if (groupId().isNull() || mThreadId.isNull()) {
|
||||
QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to a non-existant Message"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get Message ... then complete replyMessageData().
|
||||
RsGxsGrpMsgIdPair postId = std::make_pair(groupId(), mThreadId);
|
||||
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||
|
||||
#ifdef DEBUG_FORUMS
|
||||
std::cerr << "GxsForumThreadWidget::requestMsgData_BanAuthor(" << postId.first << "," << postId.second << ")";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
GxsMsgReq msgIds;
|
||||
std::vector<RsGxsMessageId> &vect = msgIds[postId.first];
|
||||
vect.push_back(postId.second);
|
||||
|
||||
uint32_t token;
|
||||
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeBanAuthor);
|
||||
}
|
||||
|
||||
void GxsForumThreadWidget::replytomessage()
|
||||
{
|
||||
if (groupId().isNull() || mThreadId.isNull()) {
|
||||
@ -1966,6 +2029,37 @@ void GxsForumThreadWidget::loadMsgData_ReplyMessage(const uint32_t &token)
|
||||
}
|
||||
}
|
||||
|
||||
void GxsForumThreadWidget::loadMsgData_BanAuthor(const uint32_t &token)
|
||||
{
|
||||
#ifdef DEBUG_FORUMS
|
||||
std::cerr << "GxsForumThreadWidget::loadMsgData_BanAuthor()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
std::vector<RsGxsForumMsg> msgs;
|
||||
if (rsGxsForums->getMsgData(token, msgs))
|
||||
{
|
||||
if (msgs.size() != 1)
|
||||
{
|
||||
std::cerr << "GxsForumThreadWidget::loadMsgData_ReplyMessage() ERROR Wrong number of answers";
|
||||
std::cerr << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << " banning author id " << msgs[0].mMeta.mAuthorId << std::endl;
|
||||
rsReputations->setOwnOpinion(msgs[0].mMeta.mAuthorId,RsReputations::OPINION_NEGATIVE) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "GxsForumThreadWidget::loadMsgData_ReplyMessage() ERROR Missing Message Data...";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
updateDisplay(true) ;
|
||||
|
||||
// we should also update the icons so that they changed to the icon for banned peers.
|
||||
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": need to implement the update of GxsTreeWidgetItems icons too." << std::endl;
|
||||
}
|
||||
/*********************** **** **** **** ***********************/
|
||||
/*********************** **** **** **** ***********************/
|
||||
|
||||
@ -1993,6 +2087,11 @@ void GxsForumThreadWidget::loadRequest(const TokenQueue *queue, const TokenReque
|
||||
loadMsgData_ReplyMessage(req.mToken);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.mUserType == mTokenTypeBanAuthor) {
|
||||
loadMsgData_BanAuthor(req.mToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GxsMessageFrameWidget::loadRequest(queue, req);
|
||||
|
@ -101,6 +101,7 @@ private slots:
|
||||
void downloadAllFiles();
|
||||
|
||||
void changedViewBox();
|
||||
void flagpersonasbad();
|
||||
|
||||
void filterColumnChanged(int column);
|
||||
void filterItems(const QString &text);
|
||||
@ -140,6 +141,7 @@ private:
|
||||
void loadMessageData(const uint32_t &token);
|
||||
void requestMsgData_ReplyMessage(const RsGxsGrpMsgIdPair &msgId);
|
||||
void loadMsgData_ReplyMessage(const uint32_t &token);
|
||||
void loadMsgData_BanAuthor(const uint32_t &token);
|
||||
|
||||
private:
|
||||
RsGxsGroupId mLastForumID;
|
||||
@ -159,6 +161,7 @@ private:
|
||||
uint32_t mTokenTypeInsertThreads;
|
||||
uint32_t mTokenTypeMessageData;
|
||||
uint32_t mTokenTypeReplyMessage;
|
||||
uint32_t mTokenTypeBanAuthor;
|
||||
|
||||
/* Color definitions (for standard see qss.default) */
|
||||
QColor mTextColorRead;
|
||||
|
@ -60,5 +60,6 @@
|
||||
<file>icons/user-busy_64.png</file>
|
||||
<file>icons/user-offline_64.png</file>
|
||||
<file>icons/user-online_64.png</file>
|
||||
<file>icons/yellow_biohazard64.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
BIN
retroshare-gui/src/gui/icons/yellow_biohazard64.png
Normal file
BIN
retroshare-gui/src/gui/icons/yellow_biohazard64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.9 KiB |
Loading…
Reference in New Issue
Block a user