From c17dddb79c660b440e615ac40f92f9732ec03be7 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 4 Oct 2015 17:47:30 -0400 Subject: [PATCH 01/23] updated GUI for reputation --- libretroshare/src/retroshare/rsidentity.h | 6 + retroshare-gui/src/gui/Identity/IdDialog.cpp | 136 ++++------- retroshare-gui/src/gui/Identity/IdDialog.ui | 228 +++++++------------ 3 files changed, 120 insertions(+), 250 deletions(-) diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index fec4d0944..ca67623bc 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -214,6 +214,12 @@ public: /********************************************************************************************/ /********************************************************************************************/ + + enum Opinion { + OPINION_NEGATIVE = -1, + OPINION_NEUTRAL = 0, + OPINION_POSITIVE = 1 + }; // For Other Services.... // It should be impossible for them to get a message which we don't have the identity. diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 1189b2d37..b6b691a2e 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -91,19 +91,10 @@ IdDialog::IdDialog(QWidget *parent) : mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); 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->lineEdit_LastUsed); + 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); @@ -112,23 +103,16 @@ IdDialog::IdDialog(QWidget *parent) : mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); 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->lineEdit_LastUsed); + //mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOverall); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); // mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgHash); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); 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->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed); //mStateHelper->addWidget(IDDIALOG_REPLIST, ui->treeWidget_RepList); //mStateHelper->addLoadPlaceholder(IDDIALOG_REPLIST, ui->treeWidget_RepList); @@ -147,7 +131,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 +181,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 +209,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 +636,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 +647,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 +655,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,26 +669,25 @@ 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); } +#endif + + ui->overallOpinion_TF->setText(QString::number(data.mReputation.mOverallScore)); + + switch(data.mReputation.mOwnOpinion) { - QString rating = QString::number(data.mReputation.mOwnOpinion); - ui->line_RatingOwn->setText(rating); + case RsIdentity::OPINION_NEGATIVE: ui->ownOpinion_CB->setCurrentIndex(0); break ; + case RsIdentity::OPINION_NEUTRAL : ui->ownOpinion_CB->setCurrentIndex(1); break ; + case RsIdentity::OPINION_POSITIVE: ui->ownOpinion_CB->setCurrentIndex(2); break ; + default: + std::cerr << "Unexpected value in own opinion: " << data.mReputation.mOwnOpinion << std::endl; } - { - QString rating = QString::number(data.mReputation.mPeerOpinion); - ui->line_RatingPeers->setText(rating); - } + ui->neighborNodesOpinion_TF->setText(QString::number(data.mReputation.mPeerOpinion)); } void IdDialog::modifyReputation() @@ -743,33 +698,18 @@ void IdDialog::modifyReputation() #endif RsGxsId id(ui->lineEdit_KeyId->text().toStdString()); + + RsIdentity::Opinion op ; - int mod = 0; - if (ui->repMod_Accept->isChecked()) - { - 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; - } + switch(ui->ownOpinion_CB->currentIndex()) + { + case 0: op = RsIdentity::OPINION_NEGATIVE ; break ; + case 1: op = RsIdentity::OPINION_NEUTRAL ; break ; + case 2: op = RsIdentity::OPINION_POSITIVE ; break ; + default: + std::cerr << "Wrong value from opinion combobox. Bug??" << std::endl; + + } #ifdef ID_DEBUG std::cerr << "IdDialog::modifyReputation() ID: " << id << " Mod: " << mod; @@ -777,7 +717,7 @@ void IdDialog::modifyReputation() #endif 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"; diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index 4109e6bcb..789dd66f6 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -7,7 +7,7 @@ 0 0 826 - 752 + 757 @@ -483,7 +483,80 @@ - + + + + true + + + + + + + Your opinion: + + + + + + + Neighbor nodes: + + + + + + + <!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> + + + 1 + + + + Positive + + + + + Neutral + + + + + Negative + + + + + + + + true + + + + @@ -492,158 +565,12 @@ - Overall - - - - - - - true - - - - - - - Implicit - - - - - - - true - - - - - - - Opinion - - - - - - - true - - - - - - - Peers - - - - - - - true + Overall: - - - - Qt::NoFocus - - - Edit reputation - - - - :/images/edit_24.png:/images/edit_24.png - - - - 24 - 24 - - - - Qt::ToolButtonTextBesideIcon - - - true - - - - - - - - - - - 0 - 0 - - - - Tweak Opinion - - - - - - Accept (+100) - - - - - - - Positive (+10) - - - - - - - Negative (-10) - - - - - - - Ban (-100) - - - - - - - - - Custom - - - - - - - -100 - - - 100 - - - - - - - - - Modify - - - @@ -730,9 +657,6 @@ lineEdit_KeyId lineEdit_GpgId lineEdit_GpgName - line_RatingOverall - line_RatingImplicit - line_RatingOwn From 317e7ea5abeb710335d9fa449d753af03c870e15 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 4 Oct 2015 23:14:49 -0400 Subject: [PATCH 02/23] added some backend for reputation system --- libretroshare/src/libretroshare.pro | 1 + libretroshare/src/retroshare/rsidentity.h | 6 ---- libretroshare/src/retroshare/rsplugin.h | 2 ++ libretroshare/src/rsserver/rsinit.cc | 26 +++++++++++------ libretroshare/src/services/p3gxsreputation.cc | 8 +++++- libretroshare/src/services/p3gxsreputation.h | 9 ++++-- retroshare-gui/src/gui/Identity/IdDialog.cpp | 28 +++++++++++++------ 7 files changed, 54 insertions(+), 26 deletions(-) diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 18ded24a5..0f895940f 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -708,6 +708,7 @@ gxs { gxs/rsgxsnetservice.h \ retroshare/rsgxsflags.h \ retroshare/rsgxsifacetypes.h \ + retroshare/rsreputations.h \ gxs/rsgenexchange.h \ gxs/rsnxsobserver.h \ gxs/rsgxsdata.h \ diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index ca67623bc..66957ee92 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -215,12 +215,6 @@ public: /********************************************************************************************/ /********************************************************************************************/ - enum Opinion { - OPINION_NEGATIVE = -1, - OPINION_NEUTRAL = 0, - OPINION_POSITIVE = 1 - }; - // For Other Services.... // It should be impossible for them to get a message which we don't have the identity. // Its a major error if we don't have the identity. diff --git a/libretroshare/src/retroshare/rsplugin.h b/libretroshare/src/retroshare/rsplugin.h index e8cb91714..6dc6dc05b 100644 --- a/libretroshare/src/retroshare/rsplugin.h +++ b/libretroshare/src/retroshare/rsplugin.h @@ -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 mPgpAuxUtils; RsUtil::inited_ptr mGxsForums; RsUtil::inited_ptr mGxsChannels; + RsUtil::inited_ptr mReputations; }; class RsPlugin diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index c0e7697fa..4a131ad9f 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -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 ****/ @@ -1489,8 +1496,8 @@ int RsServer::StartupRetroShare() pqih -> addService(mDisc,true); pqih -> addService(msgSrv,true); pqih -> addService(chatSrv,true); - pqih -> addService(mStatusSrv,true); - + pqih -> addService(mStatusSrv,true); + pqih -> addService(mReputations,true); // set interfaces for plugins // @@ -1511,6 +1518,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: @@ -1598,12 +1607,13 @@ int RsServer::StartupRetroShare() mConfigMgr->addConfiguration("peers.cfg", mPeerMgr); mConfigMgr->addConfiguration("general.cfg", mGeneralConfig); mConfigMgr->addConfiguration("msgs.cfg", msgSrv); - mConfigMgr->addConfiguration("chat.cfg", chatSrv); - mConfigMgr->addConfiguration("p3History.cfg", mHistoryMgr); - mConfigMgr->addConfiguration("p3Status.cfg", mStatusSrv); - mConfigMgr->addConfiguration("turtle.cfg", tr); - mConfigMgr->addConfiguration("banlist.cfg", mBanList); - mConfigMgr->addConfiguration("servicecontrol.cfg", serviceCtrl); + mConfigMgr->addConfiguration("chat.cfg", chatSrv); + mConfigMgr->addConfiguration("p3History.cfg", mHistoryMgr); + mConfigMgr->addConfiguration("p3Status.cfg", mStatusSrv); + 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 diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 943569732..342b6db3e 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -380,7 +380,13 @@ 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) +{ + std::cerr << __PRETTY_FUNCTION__ << ": not implemented yet!" << std::endl; + return true ; +} + +bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::Opinion& opinion) { RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index 7456b004a..1b519c5cb 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -35,6 +35,7 @@ #include "serialiser/rsgxsreputationitems.h" #include "retroshare/rsidentity.h" +#include "retroshare/rsreputations.h" #include "services/p3service.h" @@ -80,14 +81,16 @@ 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 *****/ - + /***** Interface for RsReputations *****/ + virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) ; + virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) ; + virtual bool updateOpinion(const RsGxsId& gxsid, int opinion); /***** overloaded from p3Service *****/ diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index b6b691a2e..1443c4f61 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -34,6 +34,7 @@ #include "gui/msgs/MessageComposer.h" #include +#include #include "retroshare/rsgxsflags.h" #include "retroshare/rsmsgs.h" #include @@ -676,13 +677,16 @@ void IdDialog::insertIdDetails(uint32_t token) #endif - ui->overallOpinion_TF->setText(QString::number(data.mReputation.mOverallScore)); + RsReputations::ReputationInfo info ; + rsReputations->getReputationInfo(RsGxsId(data.mMeta.mGroupId),info) ; + + ui->overallOpinion_TF->setText(QString::number(info.mOverallReputationScore)); switch(data.mReputation.mOwnOpinion) { - case RsIdentity::OPINION_NEGATIVE: ui->ownOpinion_CB->setCurrentIndex(0); break ; - case RsIdentity::OPINION_NEUTRAL : ui->ownOpinion_CB->setCurrentIndex(1); break ; - case RsIdentity::OPINION_POSITIVE: ui->ownOpinion_CB->setCurrentIndex(2); break ; + 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: " << data.mReputation.mOwnOpinion << std::endl; } @@ -699,23 +703,28 @@ void IdDialog::modifyReputation() RsGxsId id(ui->lineEdit_KeyId->text().toStdString()); - RsIdentity::Opinion op ; + RsReputations::Opinion op ; switch(ui->ownOpinion_CB->currentIndex()) { - case 0: op = RsIdentity::OPINION_NEGATIVE ; break ; - case 1: op = RsIdentity::OPINION_NEUTRAL ; break ; - case 2: op = RsIdentity::OPINION_POSITIVE ; break ; + 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, op)) { @@ -724,15 +733,18 @@ void IdDialog::modifyReputation() std::cerr << std::endl; #endif } +#endif #ifdef ID_DEBUG std::cerr << "IdDialog::modifyReputation() queuingRequest(), token: " << token; std::cerr << std::endl; #endif +#ifdef SUSPENDED // trigger refresh when finished. // basic / anstype are not needed. mIdQueue->queueRequest(token, 0, 0, IDDIALOG_REFRESH); +#endif return; } From 7a7f4c99a316f9aa6d3eb006861060c3d0764cb0 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 4 Oct 2015 23:18:31 -0400 Subject: [PATCH 03/23] added missing file --- libretroshare/src/retroshare/rsreputations.h | 53 ++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 libretroshare/src/retroshare/rsreputations.h diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h new file mode 100644 index 000000000..5db1153b5 --- /dev/null +++ b/libretroshare/src/retroshare/rsreputations.h @@ -0,0 +1,53 @@ +/* + * 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" + +typedef uint32_t GRouterServiceId ; +typedef uint64_t GRouterMsgPropagationId ; + +class RsReputations +{ +public: + // This is the interface file for the reputation system + // + enum Opinion { OPINION_NEGATIVE = -1, OPINION_NEUTRAL = 0, OPINION_POSITIVE = 1 } ; + + struct ReputationInfo + { + RsReputations::Opinion mOwnOpinion ; + float mOverallReputationScore ; + }; + + virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) =0; + virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) =0 ; +}; + +// To access reputations from anywhere +// +extern RsReputations *rsReputations ; From 9f6bc0c3fc90ea24dcd777471dc38fe064caea4e Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 6 Oct 2015 00:11:18 -0400 Subject: [PATCH 04/23] added code for all reputation items --- .../src/serialiser/rsgxsreputationitems.cc | 490 +++++++++++++----- .../src/serialiser/rsgxsreputationitems.h | 170 +++--- libretroshare/src/services/p3gxsreputation.cc | 22 +- 3 files changed, 448 insertions(+), 234 deletions(-) diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.cc b/libretroshare/src/serialiser/rsgxsreputationitems.cc index 7b56d4675..90f10e433 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.cc +++ b/libretroshare/src/serialiser/rsgxsreputationitems.cc @@ -23,9 +23,9 @@ * */ +#include #include "serialiser/rsbaseserial.h" -#include "serialiser/rsbanlistitems.h" -#include "serialiser/rstlvbanlist.h" +#include "serialiser/rsgxsreputationitems.h" /*** #define RSSERIAL_DEBUG 1 @@ -35,170 +35,392 @@ /*************************************************************************/ -#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; -void RsBanListItem::clear() -{ - peerList.TlvClear(); -} - -std::ostream &RsBanListItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsBanListItem", indent); - uint16_t int_Indent = indent + 2; - peerList.print(out, int_Indent); - - printRsItemEnd(out, "RsBanListItem", indent); - return out; -} - - -uint32_t RsBanListSerialiser::sizeList(RsBanListItem *item) -{ - uint32_t s = 8; /* header */ - s += item->peerList.TlvSize(); - - return s; -} - -/* serialise the data to the buffer */ -bool RsBanListSerialiser::serialiseList(RsBanListItem *item, void *data, uint32_t *pktsize) -{ - uint32_t tlvsize = sizeList(item); - uint32_t offset = 0; - - if (*pktsize < tlvsize) + if (pktsize < tlvsize) return false; /* not enough space */ - *pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + 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 << "RsDsdvSerialiser::serialiseRoute() Header: " << ok << std::endl; - std::cerr << "RsDsdvSerialiser::serialiseRoute() Size: " << tlvsize << std::endl; + std::cerr << "RsReputationItem::serialise() Header: " << ok << std::endl; #endif - - /* skip the header */ offset += 8; - /* add mandatory parts first */ - ok &= item->peerList.SetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - ok = false; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseRoute() Size Error! " << std::endl; -#endif - } - - return ok; -} - -RsBanListItem *RsBanListSerialiser::deserialiseList(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t tlvsize = getRsItemSize(data); - - 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; - - bool ok = true; - - /* ready to load */ - RsBanListItem *item = new RsBanListItem(); - item->clear(); - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->peerList.GetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - /* error */ - delete item; - return NULL; - } - - if (!ok) - { - delete item; - return NULL; - } - - return item; + return true ; } /*************************************************************************/ -uint32_t RsBanListSerialiser::size(RsItem *i) +void RsGxsReputationSetItem::clear() { - RsBanListItem *dri; - - if (NULL != (dri = dynamic_cast(i))) - { - return sizeList(dri); - } - return 0; + mOpinions.clear() ; } -bool RsBanListSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +void RsGxsReputationUpdateItem::clear() { - RsBanListItem *dri; - - if (NULL != (dri = dynamic_cast(i))) - { - return serialiseList(dri, data, pktsize); - } - return false; + mOpinions.clear() ; } -RsItem *RsBanListSerialiser::deserialise(void *data, uint32_t *pktsize) +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + +std::ostream& RsGxsReputationConfigItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsReputationConfigItem", indent); + uint16_t int_Indent = indent + 2; + + 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; + + out << "GxsId: " << mGxsId << std::endl; + out << "mOwnOpinion: " << mOwnOpinion << std::endl; + out << "mOwnOpinionTS : " << time(NULL) - mOwnOpinionTS << " secs ago." << std::endl; + out << "mReputation: " << mReputation << std::endl; + out << "Opinions from neighbors: " << std::endl; + + for(std::map::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::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 += 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 ; // mReputation + + 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; +} + +/*************************************************************************/ + +bool RsGxsReputationConfigItem::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 &= mPeerId.serialise(data,tlvsize,offset) ; + ok &= setRawUInt32(data, tlvsize, &offset, mLatestUpdate); + ok &= setRawUInt32(data, tlvsize, &offset, mLastQuery); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; + } + + return ok; +} +bool RsGxsReputationSetItem::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 &= mGxsId.serialise(data,tlvsize,offset) ; + ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinion); + ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinionTS); + ok &= setRawUInt32(data, tlvsize, &offset, mReputation); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; + } + + 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::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 << "RsGRouterGenericDataItem::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 << "RsGRouterGenericDataItem::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 item; +} + +RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem(void *data,uint32_t tlvsize) +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + + RsGxsReputationSetItem *item = new RsGxsReputationSetItem() ; + + /* add mandatory parts first */ + ok &= item->mGxsId.deserialise(data, tlvsize, offset) ; + ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinion); + ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinionTS); + ok &= getRawUInt32(data, tlvsize, &offset, &item->mReputation); + + uint32_t S ; + ok &= getRawUInt32(data, tlvsize, &offset, &S); + + for(int i=0;ok && imOpinions[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 && imOpinions[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; +} +/*************************************************************************/ + +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))) - { - return NULL; /* wrong type */ - } + 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 /*************************************************************************/ diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.h b/libretroshare/src/serialiser/rsgxsreputationitems.h index b238217c9..bbd75db50 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.h +++ b/libretroshare/src/serialiser/rsgxsreputationitems.h @@ -32,88 +32,95 @@ #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) - { - setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM); - return; - } + RsReputationItem(uint8_t reputation_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_REPUTATION,reputation_subtype) + { + setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM); + } -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 mOwnOpinionTS; uint32_t mReputation; - std::map mOpinions; // RsPeerId -> Opinion. + std::map 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); - std::map mOpinions; // GxsId -> Opinion. - uint32_t mLatestUpdate; + virtual bool serialise(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; + + uint32_t mLatestUpdate; + std::map 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 +128,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; } - -virtual uint32_t size(RsItem *); -virtual bool serialise (RsItem *item, void *data, uint32_t *size); -virtual RsItem * deserialise(void *data, uint32_t *size); +public: + RsGxsReputationSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_REPUTATION){} - 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(item)->serial_size() ; + } + virtual bool serialise (RsItem *item, void *data, uint32_t *size) + { + return dynamic_cast(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); }; /**************************************************************************/ diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 342b6db3e..0cac0cf31 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -184,14 +184,14 @@ 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(item); @@ -206,7 +206,7 @@ bool p3GxsReputation::processIncoming() } break; - case RS_PKT_SUBTYPE_GXSREPUTATION_UPDATE_ITEM: + case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM: { RsGxsReputationUpdateItem *updateItem = dynamic_cast(item); @@ -465,7 +465,7 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list &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); @@ -476,16 +476,16 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) for(rit = mReputations.begin(); rit != mReputations.end(); ++rit, count++) { RsGxsReputationSetItem *item = new RsGxsReputationSetItem(); - item->mGxsId = rit->first.toStdString(); + item->mGxsId = rit->first; item->mOwnOpinion = ConvertToSerialised(rit->second.mOwnOpinion, false); - item->mOwnOpinionTs = rit->second.mOwnOpinionTs; + item->mOwnOpinionTS = rit->second.mOwnOpinionTs; item->mReputation = ConvertToSerialised(rit->second.mReputation, false); std::map::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] = ConvertToSerialised(oit->second, false); } savelist.push_back(item); @@ -548,19 +548,17 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: Reputation &reputation = mReputations[gxsId]; // install opinions. - std::map::const_iterator oit; + std::map::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.mOwnOpinion = ConvertFromSerialised(item->mOwnOpinion, false); - reputation.mOwnOpinionTs = item->mOwnOpinionTs; + reputation.mOwnOpinionTs = item->mOwnOpinionTS; // if dropping entries has changed the score -> must update. int previous = ConvertFromSerialised(item->mReputation, false); From b0940890cd76064e6972c34c0693dcff85bd3493 Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 6 Oct 2015 22:39:14 -0400 Subject: [PATCH 05/23] fixed compilation --- libretroshare/src/serialiser/rsgxsreputationitems.h | 6 +++--- libretroshare/src/services/p3gxsreputation.cc | 8 +++++++- libretroshare/src/services/p3gxsreputation.h | 6 ++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.h b/libretroshare/src/serialiser/rsgxsreputationitems.h index bbd75db50..ca6d8f9a3 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.h +++ b/libretroshare/src/serialiser/rsgxsreputationitems.h @@ -80,7 +80,7 @@ class RsGxsReputationSetItem: public RsReputationItem public: RsGxsReputationSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM) {} - virtual ~RsGxsReputationSetItem(); + virtual ~RsGxsReputationSetItem() {} virtual void clear(); std::ostream &print(std::ostream &out, uint16_t indent = 0); @@ -99,7 +99,7 @@ class RsGxsReputationUpdateItem: public RsReputationItem public: RsGxsReputationUpdateItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM) {} - virtual ~RsGxsReputationUpdateItem(); + virtual ~RsGxsReputationUpdateItem() {} virtual void clear(); std::ostream &print(std::ostream &out, uint16_t indent = 0); @@ -115,7 +115,7 @@ class RsGxsReputationRequestItem: public RsReputationItem public: RsGxsReputationRequestItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM) {} - virtual ~RsGxsReputationRequestItem(); + virtual ~RsGxsReputationRequestItem() {} virtual void clear() {} std::ostream &print(std::ostream &out, uint16_t indent = 0); diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 0cac0cf31..6c7479785 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -684,4 +684,10 @@ int p3GxsReputation::sendReputationRequest(RsPeerId peerid) return 1; } - +float Reputation::CalculateReputation() +{ + // the calculation of reputation makes the whole thing + + std::cerr << __PRETTY_FUNCTION__ << ": not implemented yet!" << std::endl; + return 0.0 ; +} diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index 1b519c5cb..1ee828a68 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -64,14 +64,14 @@ public: Reputation(const RsGxsId& about) :mGxsId(about), mOwnOpinion(0), mOwnOpinionTs(0), mReputation(0) { return; } -int32_t CalculateReputation(); + float CalculateReputation(); RsGxsId mGxsId; std::map mOpinions; int32_t mOwnOpinion; time_t mOwnOpinionTs; - int32_t mReputation; + float mReputation; }; @@ -91,8 +91,6 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) ; virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) ; - virtual bool updateOpinion(const RsGxsId& gxsid, int opinion); - /***** overloaded from p3Service *****/ /*! * This retrieves all chat msg items and also (important!) From 78e6f67c698b2c31567499b41274b3491e616994 Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 6 Oct 2015 23:56:39 -0400 Subject: [PATCH 06/23] added some documentation in p3gxsreputation.cc, and the method for computing final assessment --- libretroshare/src/retroshare/rsreputations.h | 12 +- libretroshare/src/services/p3gxsreputation.cc | 168 +++++++++++------- libretroshare/src/services/p3gxsreputation.h | 22 +-- 3 files changed, 120 insertions(+), 82 deletions(-) diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h index 5db1153b5..7b227e70f 100644 --- a/libretroshare/src/retroshare/rsreputations.h +++ b/libretroshare/src/retroshare/rsreputations.h @@ -28,24 +28,28 @@ #include "retroshare/rsids.h" #include "retroshare/rsgxsifacetypes.h" -typedef uint32_t GRouterServiceId ; -typedef uint64_t GRouterMsgPropagationId ; - class RsReputations { public: // This is the interface file for the reputation system // - enum Opinion { OPINION_NEGATIVE = -1, OPINION_NEUTRAL = 0, OPINION_POSITIVE = 1 } ; + 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 ; + 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 ASSESSMENT_OK + + virtual bool isIdentityOk(const RsGxsId& id) =0; }; // To access reputations from anywhere diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 6c7479785..6e7633aa4 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -70,57 +70,65 @@ const int kMaximumSetSize = 100; * std::map 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: + * [ ] Test the whole thing + * [ ] 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; -} - - +const uint32_t LOWER_LIMIT = 0; +const uint32_t UPPER_LIMIT = 2; +const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) :p3Service(), p3Config(), @@ -133,7 +141,6 @@ p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) mReputationsUpdated = false; } - 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; @@ -275,7 +282,7 @@ 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) { @@ -341,8 +348,8 @@ bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item) rit = mReputations.find(gxsId); } - Reputation &reputation = rit->second; - reputation.mOpinions[peerid] = ConvertFromSerialised(it->second, true); + Reputation& reputation = rit->second; + reputation.mOpinions[peerid] = std::min(it->second,UPPER_LIMIT); // filters potentially tweaked reputation score sent by friend int previous = reputation.mReputation; if (previous != reputation.CalculateReputation()) @@ -382,10 +389,39 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid, time_t ts) bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::ReputationInfo& info) { - std::cerr << __PRETTY_FUNCTION__ << ": not implemented yet!" << std::endl; + RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ + + std::map::const_iterator it = mReputations.find(gxsid); + + if (it == mReputations.end()) + { + info.mOwnOpinion = RsReputations::OPINION_NEUTRAL ; + info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ; + info.mAssessment = RsReputations::ASSESSMENT_OK ; + } + else + { + info.mOwnOpinion = RsReputations::Opinion(it->second.mOwnOpinion) ; + info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ; + + if(info.mOverallReputationScore > REPUTATION_ASSESSMENT_THRESHOLD_X1) + info.mAssessment = RsReputations::ASSESSMENT_OK ; + else + info.mAssessment = RsReputations::ASSESSMENT_BAD ; + } + return true ; } +bool p3GxsReputation::isIdentityOk(const RsGxsId &id) +{ + RsReputations::ReputationInfo info ; + + getReputationInfo(id,info) ; + + return info.mAssessment == RsReputations::ASSESSMENT_OK ; +} + bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::Opinion& opinion) { RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ @@ -477,15 +513,15 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) { RsGxsReputationSetItem *item = new RsGxsReputationSetItem(); item->mGxsId = rit->first; - item->mOwnOpinion = ConvertToSerialised(rit->second.mOwnOpinion, false); + item->mOwnOpinion = rit->second.mOwnOpinion; item->mOwnOpinionTS = rit->second.mOwnOpinionTs; - item->mReputation = ConvertToSerialised(rit->second.mReputation, false); + item->mReputation = rit->second.mReputation; - std::map::iterator oit; + std::map::iterator oit; for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit) { // should be already limited. - item->mOpinions[oit->first] = ConvertToSerialised(oit->second, false); + item->mOpinions[oit->first] = oit->second; } savelist.push_back(item); @@ -554,14 +590,14 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: // expensive ... but necessary. RsPeerId peerId(oit->first); if (peerSet.end() != peerSet.find(peerId)) - reputation.mOpinions[peerId] = ConvertFromSerialised(oit->second, true); + reputation.mOpinions[peerId] = oit->second; } - reputation.mOwnOpinion = ConvertFromSerialised(item->mOwnOpinion, false); + reputation.mOwnOpinion = item->mOwnOpinion; reputation.mOwnOpinionTs = item->mOwnOpinionTS; // if dropping entries has changed the score -> must update. - int previous = ConvertFromSerialised(item->mReputation, false); + int previous = item->mReputation; if (previous != reputation.CalculateReputation()) { mUpdatedReputations.insert(gxsId); @@ -688,6 +724,18 @@ float Reputation::CalculateReputation() { // the calculation of reputation makes the whole thing - std::cerr << __PRETTY_FUNCTION__ << ": not implemented yet!" << std::endl; - return 0.0 ; + if(mOwnOpinion == RsReputations::OPINION_NEUTRAL) + { + uint32_t friend_total = 0; + + for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) + friend_total += it->second ; + + if(friend_total == 0) // includes the case of no friends! + return 0.0f ; + else + return friend_total / float(mOpinions.size()) ; + } + else + return float(mOwnOpinion) ; } diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index 1ee828a68..a9763944c 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -59,15 +59,14 @@ 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) { } float CalculateReputation(); - RsGxsId mGxsId; - std::map mOpinions; + std::map mOpinions; int32_t mOwnOpinion; time_t mOwnOpinionTs; @@ -90,28 +89,16 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / /***** Interface for RsReputations *****/ virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) ; virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) ; + virtual bool isIdentityOk(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 &plist); - - /************* from p3Config *******************/ virtual RsSerialiser *setupSerialiser() ; virtual bool saveList(bool& cleanup, std::list&) ; @@ -133,7 +120,6 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / void sendReputationRequests(); int sendReputationRequest(RsPeerId peerid); - private: RsMutex mReputationMtx; From 80ed6d1815f567391b8862c2220e68b4aabc2f61 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 7 Oct 2015 23:44:24 -0400 Subject: [PATCH 07/23] added pruning of opinions to limit data in memory. Fixed up types and sending/receiving friends opinions --- libretroshare/src/services/p3gxsreputation.cc | 200 +++++++++++++----- libretroshare/src/services/p3gxsreputation.h | 12 +- 2 files changed, 152 insertions(+), 60 deletions(-) diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 6e7633aa4..b8f187f3d 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -42,8 +42,11 @@ /* DEFINE INTERFACE POINTER! */ //RsGxsReputation *rsGxsReputation = NULL; -const int kMaximumPeerAge = 180; // half a year. -const int kMaximumSetSize = 100; +static const int kMaximumPeerAge = 180; // half a year. +static const int kMaximumSetSize = 100; + +static const int ACTIVE_FRIENDS_UPDATE_PERIOD = 600 ; // 10 minutes +static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. /************ IMPLEMENTATION NOTES ********************************* * @@ -61,8 +64,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 mReputations. * std::multimap mUpdated. @@ -122,6 +129,7 @@ const int kMaximumSetSize = 100; * [ ] Opinions are transmitted to friends when updated * * To do: + * [ ] Add debug info * [ ] Test the whole thing * [ ] Implement a system to allow not storing info when we don't have it */ @@ -139,6 +147,7 @@ p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) mRequestTime = 0; mStoreTime = 0; mReputationsUpdated = false; + mLastActiveFriendsUpdate = 0 ; } const std::string GXS_REPUTATION_APP_NAME = "gxsreputation"; @@ -163,6 +172,14 @@ int p3GxsReputation::tick() { processIncoming(); sendPackets(); + + time_t now = time(NULL); + + if(mLastActiveFriendsUpdate + ACTIVE_FRIENDS_UPDATE_PERIOD < now) + { + updateActiveFriends() ; + mLastActiveFriendsUpdate = now ; + } return 0; } @@ -172,7 +189,34 @@ int p3GxsReputation::status() return 1; } +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 idList ; + mLinkMgr->getFriendList(idList) ; + + mAverageActiveFriends = 0 ; + + for(std::list::const_iterator it(idList.begin());it!=idList.end();++it) + { + peerConnectState state ; + + if(mLinkMgr->getFriendNetStatus(*it, state) && now < state.lastavailable + ACTIVE_FRIENDS_ONLINE_DELAY) + ++mAverageActiveFriends ; + } + +} + +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() @@ -200,31 +244,22 @@ bool p3GxsReputation::processIncoming() case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM: { - RsGxsReputationRequestItem *requestItem = - dynamic_cast(item); + RsGxsReputationRequestItem *requestItem = dynamic_cast(item); if (requestItem) - { SendReputations(requestItem); - } else - { itemOk = false; - } } break; case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM: { - RsGxsReputationUpdateItem *updateItem = - dynamic_cast(item); + RsGxsReputationUpdateItem *updateItem = dynamic_cast(item); + if (updateItem) - { RecvReputations(updateItem); - } else - { itemOk = false; - } } break; } @@ -324,42 +359,93 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request) return true; } +void p3GxsReputation::locked_updateOpinion(const RsPeerId& from,const RsGxsId& about,RsReputations::Opinion op) +{ + /* find matching Reputation */ + std::map::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 ; + + // 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()) + { + if(new_opinion != RsReputations::OPINION_NEUTRAL) + { + mReputations[about] = Reputation(about); + rit = mReputations.find(about); + } + else + return ; // nothing to do + } + + Reputation& reputation = rit->second; + + std::map::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) ; + else if(updated) + { + reputation.CalculateReputation(mAverageActiveFriends) ; + + IndicateConfigChanged() ; + } +} bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item) { - std::cerr << "p3GxsReputation::RecvReputations()"; - std::cerr << std::endl; + std::cerr << "p3GxsReputation::RecvReputations()"; + std::cerr << std::endl; - RsPeerId peerid = item->PeerId(); + RsPeerId peerid = item->PeerId(); - std::map::iterator it; - for(it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ + for( std::map::iterator it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it) + { + RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - /* find matching Reputation */ - std::map::iterator rit; - RsGxsId gxsId(it->first); + locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second)); + } - rit = mReputations.find(gxsId); - if (rit == mReputations.end()) - { - mReputations[gxsId] = Reputation(gxsId); - rit = mReputations.find(gxsId); - } - Reputation& reputation = rit->second; - reputation.mOpinions[peerid] = std::min(it->second,UPPER_LIMIT); // filters potentially tweaked reputation score sent by friend + 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; + // now update all reputations of IDs for which some opinions have changed. + + return true; } @@ -462,7 +548,7 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O time_t now = time(NULL); reputation.mOwnOpinion = opinion; reputation.mOwnOpinionTs = now; - reputation.CalculateReputation(); + reputation.CalculateReputation(mAverageActiveFriends); mUpdated.insert(std::make_pair(now, gxsid)); mUpdatedReputations.insert(gxsid); @@ -517,11 +603,11 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) item->mOwnOpinionTS = rit->second.mOwnOpinionTs; item->mReputation = rit->second.mReputation; - std::map::iterator oit; + std::map::iterator oit; for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit) { // should be already limited. - item->mOpinions[oit->first] = oit->second; + item->mOpinions[oit->first] = (uint32_t)oit->second; } savelist.push_back(item); @@ -590,7 +676,7 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: // expensive ... but necessary. RsPeerId peerId(oit->first); if (peerSet.end() != peerSet.find(peerId)) - reputation.mOpinions[peerId] = oit->second; + reputation.mOpinions[peerId] = safe_convert_uint32t_to_opinion(oit->second); } reputation.mOwnOpinion = item->mOwnOpinion; @@ -598,7 +684,7 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: // if dropping entries has changed the score -> must update. int previous = item->mReputation; - if (previous != reputation.CalculateReputation()) + if (previous != reputation.CalculateReputation(mAverageActiveFriends)) { mUpdatedReputations.insert(gxsId); } @@ -686,8 +772,6 @@ void p3GxsReputation::sendReputationRequests() } } - - int p3GxsReputation::sendReputationRequest(RsPeerId peerid) { std::cerr << "p3GxsReputation::sendReputationRequest(" << peerid << ")"; @@ -720,21 +804,23 @@ int p3GxsReputation::sendReputationRequest(RsPeerId peerid) return 1; } -float Reputation::CalculateReputation() +float Reputation::CalculateReputation(uint32_t average_active_friends) { // the calculation of reputation makes the whole thing if(mOwnOpinion == RsReputations::OPINION_NEUTRAL) { - uint32_t friend_total = 0; + int friend_total = 0; - for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) - friend_total += it->second ; + // accounts for all friends. Neutral opinions count for 1-1=0 - if(friend_total == 0) // includes the case of no friends! - return 0.0f ; + for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) + friend_total += it->second - 1; + + if(mOpinions.empty()) // includes the case of no friends! + return 1.0f; else - return friend_total / float(mOpinions.size()) ; + return 1.0f + friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size())) ; } else return float(mOwnOpinion) ; diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index a9763944c..d9eabfadc 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -64,9 +64,9 @@ public: Reputation(const RsGxsId& about) :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { } - float CalculateReputation(); + float CalculateReputation(uint32_t average_active_friends); - std::map mOpinions; + std::map mOpinions; int32_t mOwnOpinion; time_t mOwnOpinionTs; @@ -112,6 +112,10 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / bool SendReputations(RsGxsReputationRequestItem *request); bool RecvReputations(RsGxsReputationUpdateItem *item); bool updateLatestUpdate(RsPeerId peerid, time_t ts); + void updateActiveFriends() ; + + // 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 &peerSet); @@ -123,9 +127,11 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / private: RsMutex mReputationMtx; + time_t mLastActiveFriendsUpdate; time_t mRequestTime; time_t mStoreTime; bool mReputationsUpdated; + uint32_t mAverageActiveFriends ; p3LinkMgr *mLinkMgr; @@ -135,7 +141,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / std::multimap mUpdated; // set of Reputations to send to p3IdService. - std::set mUpdatedReputations; + std::set mUpdatedReputations; }; #endif //SERVICE_RSGXSREPUTATION_HEADER From 3d21d996010ce9251d1ed25d727419b9713c4a85 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 8 Oct 2015 18:39:50 -0400 Subject: [PATCH 08/23] added debug info for reputation system --- libretroshare/src/services/p3gxsreputation.cc | 117 ++++++++++++++---- libretroshare/src/services/p3gxsreputation.h | 1 + 2 files changed, 97 insertions(+), 21 deletions(-) diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index b8f187f3d..29b1dcf8f 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -37,6 +37,7 @@ /**** * #define DEBUG_REPUTATION 1 ****/ +#define DEBUG_REPUTATION 1 /* DEFINE INTERFACE POINTER! */ @@ -131,7 +132,7 @@ static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. * To do: * [ ] Add debug info * [ ] Test the whole thing - * [ ] Implement a system to allow not storing info when we don't have it + * [X] Implement a system to allow not storing info when we don't have it */ const uint32_t LOWER_LIMIT = 0; @@ -181,6 +182,15 @@ int p3GxsReputation::tick() 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; } @@ -195,7 +205,7 @@ void p3GxsReputation::updateActiveFriends() // 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 idList ; @@ -210,6 +220,9 @@ void p3GxsReputation::updateActiveFriends() if(mLinkMgr->getFriendNetStatus(*it, state) && now < state.lastavailable + ACTIVE_FRIENDS_ONLINE_DELAY) ++mAverageActiveFriends ; } +#ifdef DEBUG_REPUTATION + std::cerr << "p3GxsReputation::updateActiveFriends(): new count: " << mAverageActiveFriends << std::endl; +#endif } @@ -279,8 +292,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; @@ -366,9 +380,12 @@ void p3GxsReputation::locked_updateOpinion(const RsPeerId& from,const RsGxsId& a 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 @@ -379,13 +396,22 @@ void p3GxsReputation::locked_updateOpinion(const RsPeerId& from,const RsGxsId& a 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; @@ -417,35 +443,46 @@ void p3GxsReputation::locked_updateOpinion(const RsPeerId& from,const RsGxsId& a } 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.CalculateReputation(mAverageActiveFriends) ; - - IndicateConfigChanged() ; } + + 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(); + RsPeerId peerid = item->PeerId(); - for( std::map::iterator it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ + for( std::map::iterator it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it) + { + RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second)); - } + locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second)); + } - updateLatestUpdate(peerid, item->mLatestUpdate); + updateLatestUpdate(peerid, item->mLatestUpdate); - // now update all reputations of IDs for which some opinions have changed. + // now update all reputations of IDs for which some opinions have changed. - return true; + return true; } @@ -477,6 +514,10 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::Rep { RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ +#ifdef DEBUG_REPUTATION + std::cerr << "getReputationInfo() for " << gxsid << std::endl; +#endif + std::map::const_iterator it = mReputations.find(gxsid); if (it == mReputations.end()) @@ -484,16 +525,24 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::Rep info.mOwnOpinion = RsReputations::OPINION_NEUTRAL ; info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ; info.mAssessment = RsReputations::ASSESSMENT_OK ; +#ifdef DEBUG_REPUTATION + std::cerr << " no information present. Returning default" << std::endl; + std::cerr << " information present. OwnOp = " << info.mOwnOpinion << ", overall score=" << info.mAssessment << std::endl; +#endif } else { info.mOwnOpinion = RsReputations::Opinion(it->second.mOwnOpinion) ; - info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ; + info.mOverallReputationScore = float(it->second.mReputation) ; 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 ; @@ -505,11 +554,17 @@ bool p3GxsReputation::isIdentityOk(const RsGxsId &id) getReputationInfo(id,info) ; +#ifdef DEBUG_REPUTATION + std::cerr << "isIdentityOk(): returning " << (info.mAssessment == RsReputations::ASSESSMENT_OK) << " for GXS id " << id << std::endl; +#endif return info.mAssessment == RsReputations::ASSESSMENT_OK ; } 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 RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ std::map::iterator rit; @@ -576,6 +631,9 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) cleanup = true; RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ +#ifdef DEBUG_REPUTATION + std::cerr << "p3GxsReputation::saveList()" << std::endl; +#endif /* save */ std::map::iterator it; for(it = mConfig.begin(); it != mConfig.end(); ++it) @@ -623,6 +681,9 @@ void p3GxsReputation::saveDone() bool p3GxsReputation::loadList(std::list& loadList) { +#ifdef DEBUG_REPUTATION + std::cerr << "p3GxsReputation::saveList()" << std::endl; +#endif std::list::iterator it; std::set peerSet; @@ -643,9 +704,8 @@ bool p3GxsReputation::loadList(std::list& loadList) } RsGxsReputationSetItem *set = dynamic_cast(*it); if (set) - { loadReputationSet(set, peerSet); - } + delete (*it); } @@ -825,3 +885,18 @@ float Reputation::CalculateReputation(uint32_t average_active_friends) else return float(mOwnOpinion) ; } + +void p3GxsReputation::debug_print() +{ + std::cerr << "Reputations database: " << std::endl; + std::cerr << " Average number of peers: " << mAverageActiveFriends << std::endl; + + for(std::map::const_iterator it(mReputations.begin());it!=mReputations.end();++it) + { + std::cerr << "ID=it->first, own: " << it->second.mOwnOpinion << ", global_score: " << it->second.mReputation << std::endl; + + for(std::map::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2) + std::cerr << " " << it2->first << ": " << it2->second << std::endl; + } +} + diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index d9eabfadc..d96f9b336 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -123,6 +123,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / int sendPackets(); void sendReputationRequests(); int sendReputationRequest(RsPeerId peerid); + void debug_print() ; private: RsMutex mReputationMtx; From 8c6c9344fe4db50096ccdd6e6d23eda4016a14a3 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 8 Oct 2015 23:02:34 -0400 Subject: [PATCH 09/23] fixed a few bugs in reputation items serialisation code and GUI display --- .../src/serialiser/rsgxsreputationitems.cc | 19 +++++++------ .../src/serialiser/rsgxsreputationitems.h | 1 - libretroshare/src/services/p3gxsreputation.cc | 27 ++++++++++--------- retroshare-gui/src/gui/Identity/IdDialog.cpp | 6 ++--- retroshare-gui/src/gui/Identity/IdDialog.ui | 4 +-- 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.cc b/libretroshare/src/serialiser/rsgxsreputationitems.cc index 90f10e433..876d055f7 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.cc +++ b/libretroshare/src/serialiser/rsgxsreputationitems.cc @@ -95,7 +95,6 @@ std::ostream& RsGxsReputationSetItem::print(std::ostream &out, uint16_t indent) out << "GxsId: " << mGxsId << std::endl; out << "mOwnOpinion: " << mOwnOpinion << std::endl; out << "mOwnOpinionTS : " << time(NULL) - mOwnOpinionTS << " secs ago." << std::endl; - out << "mReputation: " << mReputation << std::endl; out << "Opinions from neighbors: " << std::endl; for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) @@ -148,7 +147,6 @@ uint32_t RsGxsReputationSetItem::serial_size() const s += mGxsId.serial_size() ; s += 4 ; // mOwnOpinion s += 4 ; // mOwnOpinionTS - s += 4 ; // mReputation s += 4 ; // mOpinions.size() @@ -197,7 +195,7 @@ bool RsGxsReputationConfigItem::serialise(void *data, uint32_t& pktsize) const if (offset != tlvsize) { ok = false; - std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; + std::cerr << "RsGxsReputationConfigItem::serialisedata() size error! " << std::endl; } return ok; @@ -215,12 +213,18 @@ bool RsGxsReputationSetItem::serialise(void *data, uint32_t& pktsize) const ok &= mGxsId.serialise(data,tlvsize,offset) ; ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinion); ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinionTS); - ok &= setRawUInt32(data, tlvsize, &offset, mReputation); + ok &= setRawUInt32(data, tlvsize, &offset, mOpinions.size()); + + for(std::map::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) { ok = false; - std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; + std::cerr << "RsGxsReputationSetItem::serialisedata() size error! " << std::endl; } return ok; @@ -247,7 +251,7 @@ bool RsGxsReputationUpdateItem::serialise(void *data, uint32_t& pktsize) const if (offset != tlvsize) { ok = false; - std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; + std::cerr << "RsGxsReputationUpdateItem::serialisedata() size error! " << std::endl; } return ok; @@ -268,7 +272,7 @@ bool RsGxsReputationRequestItem::serialise(void *data, uint32_t& pktsize) const if (offset != tlvsize) { ok = false; - std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; + std::cerr << "RsGxsReputationRequestItem::serialisedata() size error! " << std::endl; } return ok; @@ -310,7 +314,6 @@ RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem( ok &= item->mGxsId.deserialise(data, tlvsize, offset) ; ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinion); ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinionTS); - ok &= getRawUInt32(data, tlvsize, &offset, &item->mReputation); uint32_t S ; ok &= getRawUInt32(data, tlvsize, &offset, &S); diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.h b/libretroshare/src/serialiser/rsgxsreputationitems.h index ca6d8f9a3..16b90847c 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.h +++ b/libretroshare/src/serialiser/rsgxsreputationitems.h @@ -90,7 +90,6 @@ public: RsGxsId mGxsId; uint32_t mOwnOpinion; uint32_t mOwnOpinionTS; - uint32_t mReputation; std::map mOpinions; // RsPeerId -> Opinion. }; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 29b1dcf8f..b69f4fcd0 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -526,8 +526,7 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::Rep info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ; info.mAssessment = RsReputations::ASSESSMENT_OK ; #ifdef DEBUG_REPUTATION - std::cerr << " no information present. Returning default" << std::endl; - std::cerr << " information present. OwnOp = " << info.mOwnOpinion << ", overall score=" << info.mAssessment << std::endl; + std::cerr << " no information present. Returning default. OwnOp = " << info.mOwnOpinion << ", overall score=" << info.mAssessment << std::endl; #endif } else @@ -571,6 +570,7 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O /* find matching Reputation */ rit = mReputations.find(gxsid); + if (rit == mReputations.end()) { mReputations[gxsid] = Reputation(gxsid); @@ -607,10 +607,11 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O 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; } @@ -659,7 +660,6 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) item->mGxsId = rit->first; item->mOwnOpinion = rit->second.mOwnOpinion; item->mOwnOpinionTS = rit->second.mOwnOpinionTs; - item->mReputation = rit->second.mReputation; std::map::iterator oit; for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit) @@ -743,11 +743,11 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: reputation.mOwnOpinionTs = item->mOwnOpinionTS; // if dropping entries has changed the score -> must update. - int previous = item->mReputation; - if (previous != reputation.CalculateReputation(mAverageActiveFriends)) - { - mUpdatedReputations.insert(gxsId); - } + + float old_reputation = reputation.mReputation ; + + if(old_reputation != reputation.CalculateReputation(mAverageActiveFriends)) + mUpdatedReputations.insert(gxsId) ; mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId)); return true; @@ -891,12 +891,15 @@ 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::const_iterator it(mReputations.begin());it!=mReputations.end();++it) { - std::cerr << "ID=it->first, own: " << it->second.mOwnOpinion << ", global_score: " << it->second.mReputation << std::endl; + std::cerr << " ID=" << it->first << ", own: " << it->second.mOwnOpinion << ", global_score: " << it->second.mReputation + << ", last update: " << now - it->second.mOwnOpinionTs << std::endl; for(std::map::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2) - std::cerr << " " << it2->first << ": " << it2->second << std::endl; + std::cerr << " " << it2->first << ": " << it2->second << std::endl; } } diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 1443c4f61..afdd3ceec 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -682,16 +682,16 @@ void IdDialog::insertIdDetails(uint32_t token) ui->overallOpinion_TF->setText(QString::number(info.mOverallReputationScore)); - switch(data.mReputation.mOwnOpinion) + switch(info.mOwnOpinion) { 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: " << data.mReputation.mOwnOpinion << std::endl; + std::cerr << "Unexpected value in own opinion: " << info.mOwnOpinion << std::endl; } - ui->neighborNodesOpinion_TF->setText(QString::number(data.mReputation.mPeerOpinion)); + //ui->neighborNodesOpinion_TF->setText(QString::number(info.m)); } void IdDialog::modifyReputation() diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index 789dd66f6..06462cca3 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -534,7 +534,7 @@ p, li { white-space: pre-wrap; } - Positive + Negative @@ -544,7 +544,7 @@ p, li { white-space: pre-wrap; } - Negative + Positive From bb7a8f273272bffac29874e49716d5d6dd560976 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 8 Oct 2015 23:54:18 -0400 Subject: [PATCH 10/23] fixed some reputation sending bugs --- .../src/serialiser/rsgxsreputationitems.cc | 8 +- .../src/serialiser/rsgxsreputationitems.h | 2 +- libretroshare/src/services/p3gxsreputation.cc | 100 ++++++++---------- libretroshare/src/services/p3gxsreputation.h | 2 +- 4 files changed, 51 insertions(+), 61 deletions(-) diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.cc b/libretroshare/src/serialiser/rsgxsreputationitems.cc index 876d055f7..ac7c40bef 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.cc +++ b/libretroshare/src/serialiser/rsgxsreputationitems.cc @@ -109,7 +109,7 @@ std::ostream& RsGxsReputationUpdateItem::print(std::ostream &out, uint16_t inden uint16_t int_Indent = indent + 2; out << "from: " << PeerId() << std::endl; - out << "last update: " << time(NULL) - mLatestUpdate << " secs ago." << std::endl; + //out << "last update: " << time(NULL) - mLatestUpdate << " secs ago." << std::endl; for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) out << " " << it->first << ": " << it->second << std::endl; @@ -159,7 +159,7 @@ uint32_t RsGxsReputationUpdateItem::serial_size() const { uint32_t s = 8; /* header */ - s += 4 ; // mLatestUpdate + //s += 4 ; // mLatestUpdate s += 4 ; // mOpinions.size(); s += (RsGxsId::serial_size() + 4) * mOpinions.size() ; @@ -239,7 +239,7 @@ bool RsGxsReputationUpdateItem::serialise(void *data, uint32_t& pktsize) const bool ok = true; - ok &= setRawUInt32(data, tlvsize, &offset, mLatestUpdate); + //ok &= setRawUInt32(data, tlvsize, &offset, mLatestUpdate); ok &= setRawUInt32(data, tlvsize, &offset, mOpinions.size()); for(std::map::const_iterator it(mOpinions.begin());ok && it!=mOpinions.end();++it) @@ -349,7 +349,7 @@ RsGxsReputationUpdateItem *RsGxsReputationSerialiser::deserialiseReputationUpdat RsGxsReputationUpdateItem *item = new RsGxsReputationUpdateItem() ; /* add mandatory parts first */ - ok &= getRawUInt32(data, tlvsize, &offset, &item->mLatestUpdate); + //ok &= getRawUInt32(data, tlvsize, &offset, &item->mLatestUpdate); uint32_t S ; ok &= getRawUInt32(data, tlvsize, &offset, &S) ; diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.h b/libretroshare/src/serialiser/rsgxsreputationitems.h index 16b90847c..8855d5c1a 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.h +++ b/libretroshare/src/serialiser/rsgxsreputationitems.h @@ -105,7 +105,7 @@ public: virtual bool serialise(void *data,uint32_t& size) const ; virtual uint32_t serial_size() const ; - uint32_t mLatestUpdate; + //uint32_t mLatestUpdate; std::map mOpinions; // GxsId -> Opinion. }; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index b69f4fcd0..cf75ddf1b 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -39,16 +39,6 @@ ****/ #define DEBUG_REPUTATION 1 - -/* DEFINE INTERFACE POINTER! */ -//RsGxsReputation *rsGxsReputation = NULL; - -static const int kMaximumPeerAge = 180; // half a year. -static const int kMaximumSetSize = 100; - -static const int ACTIVE_FRIENDS_UPDATE_PERIOD = 600 ; // 10 minutes -static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. - /************ IMPLEMENTATION NOTES ********************************* * * p3GxsReputation shares opinions / reputations with peers. @@ -135,20 +125,26 @@ static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. * [X] Implement a system to allow not storing info when we don't have it */ -const uint32_t LOWER_LIMIT = 0; -const uint32_t UPPER_LIMIT = 2; -const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; +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 = 60;//600 ;// 10 minutes +static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. + p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) :p3Service(), p3Config(), mReputationMtx("p3GxsReputation"), mLinkMgr(lm) { - addSerialType(new RsGxsReputationSerialiser()); + addSerialType(new RsGxsReputationSerialiser()); - mRequestTime = 0; - mStoreTime = 0; - mReputationsUpdated = false; + mRequestTime = 0; + mStoreTime = 0; + mReputationsUpdated = false; mLastActiveFriendsUpdate = 0 ; + mAverageActiveFriends = 0 ; } const std::string GXS_REPUTATION_APP_NAME = "gxsreputation"; @@ -167,8 +163,6 @@ RsServiceInfo p3GxsReputation::getServiceInfo() GXS_REPUTATION_MIN_MINOR_VERSION); } - - int p3GxsReputation::tick() { processIncoming(); @@ -308,12 +302,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::iterator rit; - rit = mReputations.find(tit->second); + std::map::iterator rit = mReputations.find(tit->second); + if (rit == mReputations.end()) { std::cerr << "p3GxsReputation::SendReputations() ERROR Missing Reputation"; @@ -332,13 +327,14 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request) RsGxsId gxsId = rit->first; 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). - // then set Update back one second to ensure there are none missed. - pkt->mLatestUpdate--; - } + + //pkt->mLatestUpdate = rit->second.mOwnOpinionTs; + //if (pkt->mLatestUpdate == (uint32_t) now) + //{ + // // if we could possibly get another Update at this point (same second). + // // then set Update back one second to ensure there are none missed. + // pkt->mLatestUpdate--; + //} count++; totalcount++; @@ -349,6 +345,7 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request) std::cerr << std::endl; sendItem(pkt); + pkt = new RsGxsReputationUpdateItem(); pkt->PeerId(peerId); count = 0; @@ -477,16 +474,13 @@ bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item) locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second)); } - - updateLatestUpdate(peerid, item->mLatestUpdate); - - // now update all reputations of IDs for which some opinions have changed. + updateLatestUpdate(peerid); return true; } -bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid, time_t ts) +bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid) { RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ @@ -497,11 +491,12 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid, time_t ts) mConfig[peerid] = ReputationConfig(peerid); it = mConfig.find(peerid) ; } - it->second.mLatestUpdate = ts; + it->second.mLatestUpdate = time(NULL); mReputationsUpdated = true; // Switched to periodic save due to scale of data. - //IndicateConfigChanged(); + + IndicateConfigChanged(); return true; } @@ -758,7 +753,7 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: * Send Requests. ****/ -const int kReputationRequestPeriod = 3600; +const int kReputationRequestPeriod = 60; // 3600; // 1 hour const int kReputationStoreWait = 180; // 3 minutes. int p3GxsReputation::sendPackets() @@ -771,7 +766,7 @@ int p3GxsReputation::sendPackets() storeTime = mStoreTime; } - if (now - requestTime > kReputationRequestPeriod) + if (now > requestTime + kReputationRequestPeriod) { sendReputationRequests(); @@ -815,46 +810,41 @@ void p3GxsReputation::sendReputationRequests() mLinkMgr->getOnlineList(idList); -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::sendReputationRequests()"; - std::cerr << std::endl; -#endif - /* prepare packets */ std::list::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::iterator it; - it = mConfig.find(peerid); + std::map::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; } diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index d96f9b336..d71cb3848 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -111,7 +111,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / bool SendReputations(RsGxsReputationRequestItem *request); bool RecvReputations(RsGxsReputationUpdateItem *item); - bool updateLatestUpdate(RsPeerId peerid, time_t ts); + bool updateLatestUpdate(RsPeerId peerid); void updateActiveFriends() ; // internal update of data. Takes care of cleaning empty boxes. From ce96e889254a3d57bfb92d2554e1a875747deb6a Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 9 Oct 2015 17:51:10 -0400 Subject: [PATCH 11/23] debugging of reputation system --- .../src/serialiser/rsgxsreputationitems.cc | 8 +-- .../src/serialiser/rsgxsreputationitems.h | 2 +- libretroshare/src/services/p3gxsreputation.cc | 50 +++++++++++-------- libretroshare/src/services/p3gxsreputation.h | 4 +- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.cc b/libretroshare/src/serialiser/rsgxsreputationitems.cc index ac7c40bef..876d055f7 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.cc +++ b/libretroshare/src/serialiser/rsgxsreputationitems.cc @@ -109,7 +109,7 @@ std::ostream& RsGxsReputationUpdateItem::print(std::ostream &out, uint16_t inden uint16_t int_Indent = indent + 2; out << "from: " << PeerId() << std::endl; - //out << "last update: " << time(NULL) - mLatestUpdate << " secs ago." << std::endl; + out << "last update: " << time(NULL) - mLatestUpdate << " secs ago." << std::endl; for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) out << " " << it->first << ": " << it->second << std::endl; @@ -159,7 +159,7 @@ uint32_t RsGxsReputationUpdateItem::serial_size() const { uint32_t s = 8; /* header */ - //s += 4 ; // mLatestUpdate + s += 4 ; // mLatestUpdate s += 4 ; // mOpinions.size(); s += (RsGxsId::serial_size() + 4) * mOpinions.size() ; @@ -239,7 +239,7 @@ bool RsGxsReputationUpdateItem::serialise(void *data, uint32_t& pktsize) const bool ok = true; - //ok &= setRawUInt32(data, tlvsize, &offset, mLatestUpdate); + ok &= setRawUInt32(data, tlvsize, &offset, mLatestUpdate); ok &= setRawUInt32(data, tlvsize, &offset, mOpinions.size()); for(std::map::const_iterator it(mOpinions.begin());ok && it!=mOpinions.end();++it) @@ -349,7 +349,7 @@ RsGxsReputationUpdateItem *RsGxsReputationSerialiser::deserialiseReputationUpdat RsGxsReputationUpdateItem *item = new RsGxsReputationUpdateItem() ; /* add mandatory parts first */ - //ok &= getRawUInt32(data, tlvsize, &offset, &item->mLatestUpdate); + ok &= getRawUInt32(data, tlvsize, &offset, &item->mLatestUpdate); uint32_t S ; ok &= getRawUInt32(data, tlvsize, &offset, &S) ; diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.h b/libretroshare/src/serialiser/rsgxsreputationitems.h index 8855d5c1a..16b90847c 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.h +++ b/libretroshare/src/serialiser/rsgxsreputationitems.h @@ -105,7 +105,7 @@ public: virtual bool serialise(void *data,uint32_t& size) const ; virtual uint32_t serial_size() const ; - //uint32_t mLatestUpdate; + uint32_t mLatestUpdate; std::map mOpinions; // GxsId -> Opinion. }; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index cf75ddf1b..d7e815cae 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -206,16 +206,22 @@ void p3GxsReputation::updateActiveFriends() mLinkMgr->getFriendList(idList) ; mAverageActiveFriends = 0 ; +#ifdef DEBUG_REPUTATION + std::cerr << " counting recently online peers." << std::endl; +#endif for(std::list::const_iterator it(idList.begin());it!=idList.end();++it) { - peerConnectState state ; + RsPeerDetails details ; +#ifdef DEBUG_REPUTATION + std::cerr << " " << *it << ": last seen " << now - details.lastConnect << " secs ago" << std::endl; +#endif - if(mLinkMgr->getFriendNetStatus(*it, state) && now < state.lastavailable + ACTIVE_FRIENDS_ONLINE_DELAY) + if(rsPeers->getPeerDetails(*it, details) && now < details.lastConnect + ACTIVE_FRIENDS_ONLINE_DELAY) ++mAverageActiveFriends ; } #ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::updateActiveFriends(): new count: " << mAverageActiveFriends << std::endl; + std::cerr << " new count: " << mAverageActiveFriends << std::endl; #endif } @@ -327,14 +333,14 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request) RsGxsId gxsId = rit->first; pkt->mOpinions[gxsId] = rit->second.mOwnOpinion; + pkt->mLatestUpdate = rit->second.mOwnOpinionTs; - //pkt->mLatestUpdate = rit->second.mOwnOpinionTs; - //if (pkt->mLatestUpdate == (uint32_t) now) - //{ - // // if we could possibly get another Update at this point (same second). - // // then set Update back one second to ensure there are none missed. - // pkt->mLatestUpdate--; - //} + if (pkt->mLatestUpdate == (uint32_t) now) + { + // if we could possibly get another Update at this point (same second). + // then set Update back one second to ensure there are none missed. + pkt->mLatestUpdate--; + } count++; totalcount++; @@ -452,7 +458,7 @@ void p3GxsReputation::locked_updateOpinion(const RsPeerId& from,const RsGxsId& a #ifdef DEBUG_REPUTATION std::cerr << " reputation changed. re-calculating." << std::endl; #endif - reputation.CalculateReputation(mAverageActiveFriends) ; + reputation.updateReputation(mAverageActiveFriends) ; } if(updated) @@ -474,13 +480,13 @@ bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item) locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second)); } - updateLatestUpdate(peerid); + updateLatestUpdate(peerid,item->mLatestUpdate); return true; } -bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid) +bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid,time_t latest_update) { RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ @@ -491,7 +497,7 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid) mConfig[peerid] = ReputationConfig(peerid); it = mConfig.find(peerid) ; } - it->second.mLatestUpdate = time(NULL); + it->second.mLatestUpdate = latest_update ; mReputationsUpdated = true; // Switched to periodic save due to scale of data. @@ -598,7 +604,7 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O time_t now = time(NULL); reputation.mOwnOpinion = opinion; reputation.mOwnOpinionTs = now; - reputation.CalculateReputation(mAverageActiveFriends); + reputation.updateReputation(mAverageActiveFriends); mUpdated.insert(std::make_pair(now, gxsid)); mUpdatedReputations.insert(gxsid); @@ -741,7 +747,7 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: float old_reputation = reputation.mReputation ; - if(old_reputation != reputation.CalculateReputation(mAverageActiveFriends)) + if(old_reputation != reputation.updateReputation(mAverageActiveFriends)) mUpdatedReputations.insert(gxsId) ; mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId)); @@ -854,7 +860,7 @@ int p3GxsReputation::sendReputationRequest(RsPeerId peerid) return 1; } -float Reputation::CalculateReputation(uint32_t average_active_friends) +float Reputation::updateReputation(uint32_t average_active_friends) { // the calculation of reputation makes the whole thing @@ -868,12 +874,14 @@ float Reputation::CalculateReputation(uint32_t average_active_friends) friend_total += it->second - 1; if(mOpinions.empty()) // includes the case of no friends! - return 1.0f; + mReputation = 1.0f; else - return 1.0f + friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size())) ; + mReputation = 1.0f + friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size())) ; } else - return float(mOwnOpinion) ; + mReputation = (float)mOwnOpinion ; + + return float(mOwnOpinion) ; } void p3GxsReputation::debug_print() @@ -886,7 +894,7 @@ void p3GxsReputation::debug_print() for(std::map::const_iterator it(mReputations.begin());it!=mReputations.end();++it) { std::cerr << " ID=" << it->first << ", own: " << it->second.mOwnOpinion << ", global_score: " << it->second.mReputation - << ", last update: " << now - it->second.mOwnOpinionTs << std::endl; + << ", last own update: " << now - it->second.mOwnOpinionTs << " secs ago." << std::endl; for(std::map::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2) std::cerr << " " << it2->first << ": " << it2->second << std::endl; diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index d71cb3848..d69c8da89 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -64,7 +64,7 @@ public: Reputation(const RsGxsId& about) :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { } - float CalculateReputation(uint32_t average_active_friends); + float updateReputation(uint32_t average_active_friends); std::map mOpinions; int32_t mOwnOpinion; @@ -111,7 +111,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / bool SendReputations(RsGxsReputationRequestItem *request); bool RecvReputations(RsGxsReputationUpdateItem *item); - bool updateLatestUpdate(RsPeerId peerid); + bool updateLatestUpdate(RsPeerId peerid, time_t latest_update); void updateActiveFriends() ; // internal update of data. Takes care of cleaning empty boxes. From 338fcee86502549952280ea27140f68647fc8790 Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 9 Oct 2015 18:51:16 -0400 Subject: [PATCH 12/23] added button in forums to flag poster identity as bad --- libretroshare/src/retroshare/rsreputations.h | 1 + libretroshare/src/services/p3gxsreputation.cc | 14 +++++++++++--- libretroshare/src/services/p3gxsreputation.h | 1 + retroshare-gui/src/gui/Identity/IdDialog.cpp | 11 +++++------ retroshare-gui/src/gui/Identity/IdDialog.ui | 12 +++++++++++- .../gui/gxsforums/GxsForumThreadWidget.cpp | 18 ++++++++++++++++++ .../src/gui/gxsforums/GxsForumThreadWidget.h | 3 ++- retroshare-gui/src/gui/icons.qrc | 1 + .../src/gui/icons/yellow_biohazard64.png | Bin 0 -> 10182 bytes 9 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 retroshare-gui/src/gui/icons/yellow_biohazard64.png diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h index 7b227e70f..ee09458a8 100644 --- a/libretroshare/src/retroshare/rsreputations.h +++ b/libretroshare/src/retroshare/rsreputations.h @@ -40,6 +40,7 @@ public: { RsReputations::Opinion mOwnOpinion ; float mOverallReputationScore ; + float mFriendAverage ; RsReputations::Assessment mAssessment; // this should help clients in taking decisions }; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index d7e815cae..7de4165d2 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -524,6 +524,7 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::Rep 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 @@ -533,7 +534,8 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::Rep else { info.mOwnOpinion = RsReputations::Opinion(it->second.mOwnOpinion) ; - info.mOverallReputationScore = float(it->second.mReputation) ; + info.mOverallReputationScore = it->second.mReputation ; + info.mFriendAverage = it->second.mFriendAverage ; if(info.mOverallReputationScore > REPUTATION_ASSESSMENT_THRESHOLD_X1) info.mAssessment = RsReputations::ASSESSMENT_OK ; @@ -874,9 +876,15 @@ float Reputation::updateReputation(uint32_t average_active_friends) friend_total += it->second - 1; if(mOpinions.empty()) // includes the case of no friends! + { mReputation = 1.0f; + mFriendAverage = 1.0f ; + } else - mReputation = 1.0f + friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size())) ; + { + mFriendAverage = 1.0+friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size())); + mReputation = mFriendAverage ; + } } else mReputation = (float)mOwnOpinion ; @@ -893,7 +901,7 @@ void p3GxsReputation::debug_print() for(std::map::const_iterator it(mReputations.begin());it!=mReputations.end();++it) { - std::cerr << " ID=" << it->first << ", own: " << it->second.mOwnOpinion << ", global_score: " << it->second.mReputation + 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::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2) diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index d69c8da89..82f954b4d 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -70,6 +70,7 @@ public: int32_t mOwnOpinion; time_t mOwnOpinionTs; + float mFriendAverage ; float mReputation; }; diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index afdd3ceec..2d26c55b4 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -680,8 +680,11 @@ void IdDialog::insertIdDetails(uint32_t token) RsReputations::ReputationInfo info ; rsReputations->getReputationInfo(RsGxsId(data.mMeta.mGroupId),info) ; - ui->overallOpinion_TF->setText(QString::number(info.mOverallReputationScore)); + 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) { case RsReputations::OPINION_NEGATIVE: ui->ownOpinion_CB->setCurrentIndex(0); break ; @@ -690,8 +693,6 @@ void IdDialog::insertIdDetails(uint32_t token) default: std::cerr << "Unexpected value in own opinion: " << info.mOwnOpinion << std::endl; } - - //ui->neighborNodesOpinion_TF->setText(QString::number(info.m)); } void IdDialog::modifyReputation() @@ -740,11 +741,9 @@ void IdDialog::modifyReputation() std::cerr << std::endl; #endif -#ifdef SUSPENDED // trigger refresh when finished. // basic / anstype are not needed. - mIdQueue->queueRequest(token, 0, 0, IDDIALOG_REFRESH); -#endif + requestIdDetails(); return; } diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index 06462cca3..b6649e413 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -485,6 +485,9 @@ + + <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> + true @@ -530,12 +533,16 @@ p, li { white-space: pre-wrap; } <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> - 1 + 0 Negative + + + ../icons/yellow_biohazard64.png../icons/yellow_biohazard64.png + @@ -551,6 +558,9 @@ p, li { white-space: pre-wrap; } + + <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> + true diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index e51527860..0f2f656d3 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -41,6 +41,7 @@ #include "util/QtVersion.h" #include +#include #include // 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,9 @@ 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("Flag this person as bad"), &contextMnu); + 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 +489,8 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/) contextMnu.addAction(expandAll); contextMnu.addAction(collapseAll); + contextMnu.addSeparator(); + contextMnu.addAction(flagasbadAct); contextMnu.addSeparator(); contextMnu.addAction(replyauthorAct); @@ -1685,6 +1692,17 @@ static QString buildReplyHeader(const RsMsgMetaData &meta) return header; } +void GxsForumThreadWidget::flagpersonasbad() +{ + 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(). + rsReputations->setOwnOpinion(RsGxsId(groupId()),RsReputations::OPINION_NEGATIVE) ; +} + void GxsForumThreadWidget::replytomessage() { if (groupId().isNull() || mThreadId.isNull()) { diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h index 311024f07..293a8fb7b 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -101,6 +101,7 @@ private slots: void downloadAllFiles(); void changedViewBox(); + void flagpersonasbad(); void filterColumnChanged(int column); void filterItems(const QString &text); @@ -170,7 +171,7 @@ private: RsGxsMessageId mNavigatePendingMsgId; QList mIgnoredMsgId; - Ui::GxsForumThreadWidget *ui; + Ui::GxsForumThreadWidget *ui; }; #endif // GXSFORUMTHREADWIDGET_H diff --git a/retroshare-gui/src/gui/icons.qrc b/retroshare-gui/src/gui/icons.qrc index 8840c6087..3cee5d1d2 100644 --- a/retroshare-gui/src/gui/icons.qrc +++ b/retroshare-gui/src/gui/icons.qrc @@ -60,5 +60,6 @@ icons/user-busy_64.png icons/user-offline_64.png icons/user-online_64.png + icons/yellow_biohazard64.png diff --git a/retroshare-gui/src/gui/icons/yellow_biohazard64.png b/retroshare-gui/src/gui/icons/yellow_biohazard64.png new file mode 100644 index 0000000000000000000000000000000000000000..edb6fb3f24b36b67d7267e4d0d83fdd0bbcdc876 GIT binary patch literal 10182 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 Date: Fri, 9 Oct 2015 18:55:07 -0400 Subject: [PATCH 13/23] fixed bug causing uninitialised friend average reputation to be shown --- libretroshare/src/services/p3gxsreputation.cc | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 7de4165d2..2056e03f9 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -864,32 +864,26 @@ int p3GxsReputation::sendReputationRequest(RsPeerId peerid) float Reputation::updateReputation(uint32_t average_active_friends) { - // the calculation of reputation makes the whole thing - - if(mOwnOpinion == RsReputations::OPINION_NEUTRAL) - { - int friend_total = 0; - - // accounts for all friends. Neutral opinions count for 1-1=0 - - for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) - friend_total += it->second - 1; - - if(mOpinions.empty()) // includes the case of no friends! - { - mReputation = 1.0f; - mFriendAverage = 1.0f ; - } - else - { - mFriendAverage = 1.0+friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size())); - mReputation = mFriendAverage ; - } - } - else - mReputation = (float)mOwnOpinion ; - - return float(mOwnOpinion) ; + // 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::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() From 68ca57ce75958269efda1e89fe9e18c3fb0177df Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 10 Oct 2015 18:27:15 -0400 Subject: [PATCH 14/23] added removal of messages frm banned users --- libretroshare/src/gxs/rsgxsnetservice.cc | 5 +- libretroshare/src/services/p3gxsreputation.cc | 6 +++ retroshare-gui/src/gui/gxs/GxsIdDetails.h | 9 ++-- .../gui/gxsforums/GxsForumThreadWidget.cpp | 53 ++++++++++++++----- .../src/gui/gxsforums/GxsForumThreadWidget.h | 2 +- 5 files changed, 55 insertions(+), 20 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 8806b4e1c..c6503d3d4 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -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" @@ -2009,7 +2010,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(rsReputations->isIdentityOk(syncItem->authorId) && rep.score > (int)grpMeta->mReputationCutOff || noAuthor) { #ifdef NXS_NET_DEBUG std::cerr << ", passed! Adding message to req list." << std::endl; @@ -2225,7 +2226,7 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) GixsReputation rep; mReputations->getReputation(grpSyncItem->authorId, rep); - if(rep.score >= GIXS_CUT_OFF) + if(rep.score >= GIXS_CUT_OFF && rsReputations->isIdentityOk(grpSyncItem->authorId)) { addGroupItemToList(tr, grpId, transN, reqList); std::cerr << " reputation cut off: limit=" << GIXS_CUT_OFF << " value=" << rep.score << ": allowed." << std::endl; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 2056e03f9..fa53c5a8a 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -567,6 +567,12 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O #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::iterator rit; diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.h b/retroshare-gui/src/gui/gxs/GxsIdDetails.h index 06747e71e..53ce44729 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.h +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.h @@ -49,10 +49,11 @@ class GxsIdDetails : public QObject Q_OBJECT public: - static const int ICON_TYPE_AVATAR = 0x0001 ; - 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_AVATAR = 0x0001 ; + 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(); diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 0f2f656d3..8a3c1befe 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -83,6 +83,7 @@ #define ROLE_THREAD_READCHILDREN Qt::UserRole + 4 #define ROLE_THREAD_UNREADCHILDREN Qt::UserRole + 5 #define ROLE_THREAD_SORT Qt::UserRole + 6 +#define ROLE_THREAD_REDACTED Qt::UserRole + 7 #define ROLE_THREAD_COUNT 4 @@ -408,7 +409,8 @@ 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("Flag this person as bad"), &contextMnu); + QAction *flagasbadAct = new QAction(QIcon(IMAGE_BIOHAZARD), tr("Flag the author as bad"), &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); @@ -893,12 +895,21 @@ 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->isIdentityOk(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; - item->setText(COLUMN_THREAD_TITLE, QString::fromUtf8(msg.mMeta.mMsgName.c_str())); + 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; QString sort; @@ -968,9 +979,9 @@ 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); - + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_REDACTED, redacted); + return item; } @@ -1308,6 +1319,8 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg) return; } + bool redacted = !rsReputations->isIdentityOk(msg.mMeta.mAuthorId) ; + mStateHelper->setActive(mTokenTypeMessageData, true); QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); @@ -1341,9 +1354,18 @@ 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("

The author of this message (with ID %1) is banned.").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ; + extraTxt += "

  • Messages from this author are not forwarded.
  • " ; + extraTxt += "
    • Messages from this author are replaced by this text.
    • " ; + 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())); } @@ -1694,13 +1716,18 @@ static QString buildReplyHeader(const RsMsgMetaData &meta) void GxsForumThreadWidget::flagpersonasbad() { - if (groupId().isNull() || mThreadId.isNull()) { - QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to a non-existant Message")); - return; - } + // 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. - // Get Message ... then complete replyMessageData(). - rsReputations->setOwnOpinion(RsGxsId(groupId()),RsReputations::OPINION_NEGATIVE) ; + QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + + std::cerr << "Author string: \"" << item->data(COLUMN_THREAD_DATA, ROLE_THREAD_AUTHOR).toString().toStdString()<< std::endl; + RsGxsId gxsId(item->data(COLUMN_THREAD_DATA, ROLE_THREAD_AUTHOR).toString().toStdString()); + + // Get Message ... then complete replyMessageData(). + std::cerr << "GxsForumThreadWidget::flagpersonasbad(): setting opinion for peer " << gxsId << " to " << RsReputations::OPINION_NEGATIVE << std::endl; + rsReputations->setOwnOpinion(gxsId,RsReputations::OPINION_NEGATIVE) ; + + emit groupChanged(this); } void GxsForumThreadWidget::replytomessage() diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h index 293a8fb7b..4c3a85497 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -66,7 +66,7 @@ protected: /* GxsMessageFrameWidget */ virtual void setAllMessagesReadDo(bool read, uint32_t &token); - + private slots: /** Create the context popup menu and it's submenus */ void threadListCustomPopupMenu(QPoint point); From f7508184025d3510d7ffcf316d1bf55252ae08ae Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 10 Oct 2015 21:25:06 -0400 Subject: [PATCH 15/23] added proper icons and names for banned users --- retroshare-gui/src/gui/gxs/GxsIdChooser.cpp | 6 +++ retroshare-gui/src/gui/gxs/GxsIdDetails.cpp | 31 +++++++++++-- retroshare-gui/src/gui/gxs/GxsIdDetails.h | 3 +- .../src/gui/gxs/GxsIdTreeWidgetItem.cpp | 45 +++++++++++-------- .../gui/gxsforums/GxsForumThreadWidget.cpp | 10 ++--- 5 files changed, 67 insertions(+), 28 deletions(-) diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp index 7fb83f131..71554f31a 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp @@ -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); diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp index aab87ddf7..dc8667a84 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp @@ -29,6 +29,7 @@ #include #include "GxsIdDetails.h" #include "retroshare-gui/RsAutoUpdatePage.h" +#include "retroshare/rsreputations.h" #include @@ -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,7 +878,10 @@ bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, QLi QString GxsIdDetails::getName(const RsIdentityDetails &details) { - QString name = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE); + if(!rsReputations->isIdentityOk(details.mId)) + return tr("[Banned]") ; + + QString name = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE); std::list::const_iterator it; for (it = details.mRecognTags.begin(); it != details.mRecognTags.end(); ++it) @@ -887,9 +895,18 @@ QString GxsIdDetails::getName(const RsIdentityDetails &details) QString GxsIdDetails::getComment(const RsIdentityDetails &details) { QString comment; +QString nickname ; -QString nickname = details.mNickname.empty()?tr("[Unknown]"):QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE) ; + bool banned = !rsReputations->isIdentityOk(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) ; + comment = QString("%1:%2
      %3:%4").arg(QApplication::translate("GxsIdDetails", "Identity name"), nickname, QApplication::translate("GxsIdDetails", "Identity Id"), @@ -903,7 +920,8 @@ 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())); + + comment += QString("%1 [%2]").arg(QString::fromUtf8(authorName.c_str()), QString::fromStdString(details.mPgpId.toStdString())); } else comment += QApplication::translate("GxsIdDetails", "unknown Key"); @@ -918,6 +936,13 @@ void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icon { QPixmap pix ; + if(!rsReputations->isIdentityOk(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")) diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.h b/retroshare-gui/src/gui/gxs/GxsIdDetails.h index 53ce44729..3c9259ff3 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.h +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.h @@ -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); diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp index 56c225d6b..2726a1376 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp @@ -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(":/icons/yellow_biohazard64.png")) ; + break ; } int column = item->idColumn(); @@ -139,28 +146,28 @@ void GxsIdRSTreeWidgetItem::setAvatar(const RsGxsImage &avatar) QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const { - if (column == idColumn()) { - switch (role) { - case Qt::ToolTipRole: - { - QString t = RSTreeWidgetItem::data(column, role).toString(); + if (column == idColumn()) + { + if (role == Qt::ToolTipRole) + { + QString t = RSTreeWidgetItem::data(column, role).toString(); + QImage pix; - QImage pix; - if (mAvatar.mSize == 0 || !pix.loadFromData(mAvatar.mData, mAvatar.mSize, "PNG")) { - pix = GxsIdDetails::makeDefaultIcon(mId); - } + if(!rsReputations->isIdentityOk(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(); + int S = QFontMetricsF(font(column)).height(); - QString embeddedImage; - if (RsHtml::makeEmbeddedImage(pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, 8*S * 8*S)) { - t = "
      " + embeddedImage + "" + t + "
      "; - } + QString embeddedImage; + if (RsHtml::makeEmbeddedImage(pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, 8*S * 8*S)) { + t = "
      " + embeddedImage + "" + t + "
      "; + } - return t; - } - } - } + return t; + } + } - return RSTreeWidgetItem::data(column, role); + return RSTreeWidgetItem::data(column, role); } diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 8a3c1befe..f1a7d6204 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -83,7 +83,6 @@ #define ROLE_THREAD_READCHILDREN Qt::UserRole + 4 #define ROLE_THREAD_UNREADCHILDREN Qt::UserRole + 5 #define ROLE_THREAD_SORT Qt::UserRole + 6 -#define ROLE_THREAD_REDACTED Qt::UserRole + 7 #define ROLE_THREAD_COUNT 4 @@ -980,7 +979,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); - item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_REDACTED, redacted); return item; } @@ -1357,9 +1355,9 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg) if(redacted) { QString extraTxt = tr("

      The author of this message (with ID %1) is banned.").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ; - extraTxt += "

      • Messages from this author are not forwarded.
      • " ; - extraTxt += "
        • Messages from this author are replaced by this text.
        • " ; - ui->postText->setHtml(extraTxt); + extraTxt += "
          • Messages from this author are not forwarded.
          • " ; + extraTxt += "
          • Messages from this author are replaced by this text.
          " ; + ui->postText->setHtml(extraTxt); } else { @@ -1721,6 +1719,8 @@ void GxsForumThreadWidget::flagpersonasbad() QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); std::cerr << "Author string: \"" << item->data(COLUMN_THREAD_DATA, ROLE_THREAD_AUTHOR).toString().toStdString()<< std::endl; + std::cerr << "Messagestring: \"" << item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString()<< std::endl; + std::cerr << "Messagestring: \"" << item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toString().toStdString()<< std::endl; RsGxsId gxsId(item->data(COLUMN_THREAD_DATA, ROLE_THREAD_AUTHOR).toString().toStdString()); // Get Message ... then complete replyMessageData(). From e309dd6fed323c716cccfeca832f656aadbd6a07 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 11 Oct 2015 10:00:11 -0400 Subject: [PATCH 16/23] fixed banning users from forum threads --- libretroshare/src/retroshare/rsidentity.h | 1 + .../gui/gxsforums/GxsForumThreadWidget.cpp | 65 ++++++++++++++++--- .../src/gui/gxsforums/GxsForumThreadWidget.h | 2 + 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index 66957ee92..b7e9856c1 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -177,6 +177,7 @@ public: // reputation details. GxsReputation mReputation; + bool mBanned ; // avatar RsGxsImage mAvatar ; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index f1a7d6204..a542fa87f 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -733,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; @@ -1715,19 +1718,30 @@ static QString buildReplyHeader(const RsMsgMetaData &meta) 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; + } - QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + // Get Message ... then complete replyMessageData(). + RsGxsGrpMsgIdPair postId = std::make_pair(groupId(), mThreadId); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - std::cerr << "Author string: \"" << item->data(COLUMN_THREAD_DATA, ROLE_THREAD_AUTHOR).toString().toStdString()<< std::endl; - std::cerr << "Messagestring: \"" << item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString()<< std::endl; - std::cerr << "Messagestring: \"" << item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toString().toStdString()<< std::endl; - RsGxsId gxsId(item->data(COLUMN_THREAD_DATA, ROLE_THREAD_AUTHOR).toString().toStdString()); +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::requestMsgData_BanAuthor(" << postId.first << "," << postId.second << ")"; + std::cerr << std::endl; +#endif - // Get Message ... then complete replyMessageData(). - std::cerr << "GxsForumThreadWidget::flagpersonasbad(): setting opinion for peer " << gxsId << " to " << RsReputations::OPINION_NEGATIVE << std::endl; - rsReputations->setOwnOpinion(gxsId,RsReputations::OPINION_NEGATIVE) ; + GxsMsgReq msgIds; + std::vector &vect = msgIds[postId.first]; + vect.push_back(postId.second); + + uint32_t token; + mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeBanAuthor); - emit groupChanged(this); } void GxsForumThreadWidget::replytomessage() @@ -2011,6 +2025,34 @@ 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 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; + } + + emit groupChanged(this) ; +} /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ @@ -2038,6 +2080,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); diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h index 4c3a85497..7048e7925 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -141,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; @@ -160,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; From 1a76bea6ffc7ed8302b52e34a0792b7d21f05cb0 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 11 Oct 2015 21:41:35 -0400 Subject: [PATCH 17/23] enabled bannign button in forums, and disable message passing for banned users --- libretroshare/src/gxs/rsgxsnetservice.cc | 20 +++++++++++++++---- libretroshare/src/retroshare/rsidentity.h | 13 +++++++----- libretroshare/src/retroshare/rsreputations.h | 4 ++-- libretroshare/src/services/p3gxsreputation.cc | 6 +++--- libretroshare/src/services/p3gxsreputation.h | 2 +- libretroshare/src/services/p3idservice.cc | 13 ++++++++---- retroshare-gui/src/gui/gxs/GxsIdDetails.cpp | 6 +++--- .../src/gui/gxs/GxsIdTreeWidgetItem.cpp | 2 +- .../gui/gxsforums/GxsForumThreadWidget.cpp | 4 ++-- 9 files changed, 45 insertions(+), 25 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index c6503d3d4..14d09f3dc 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -1997,7 +1997,13 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr) std::cerr << ", no group meta found. Givign up." << std::endl; 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; @@ -2010,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(rsReputations->isIdentityOk(syncItem->authorId) && 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,7 +2217,13 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) haveItem = true; latestVersion = grpSyncItem->publishTs > metaIter->second->mPublishTs; } - + + if(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 @@ -2226,7 +2238,7 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) GixsReputation rep; mReputations->getReputation(grpSyncItem->authorId, rep); - if(rep.score >= GIXS_CUT_OFF && rsReputations->isIdentityOk(grpSyncItem->authorId)) + if(rep.score >= GIXS_CUT_OFF) { addGroupItemToList(tr, grpId, transN, reqList); std::cerr << " reputation cut off: limit=" << GIXS_CUT_OFF << " value=" << rep.score << ": allowed." << std::endl; diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index b7e9856c1..d3ee14041 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -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,9 +175,12 @@ public: // Recogn details. std::list mRecognTags; - // reputation details. - GxsReputation mReputation; - bool mBanned ; + // 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 ; diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h index ee09458a8..433eb8368 100644 --- a/libretroshare/src/retroshare/rsreputations.h +++ b/libretroshare/src/retroshare/rsreputations.h @@ -48,9 +48,9 @@ public: 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 ASSESSMENT_OK + // it basically returns true if assessment is not ASSESSMENT_OK - virtual bool isIdentityOk(const RsGxsId& id) =0; + virtual bool isIdentityBanned(const RsGxsId& id) =0; }; // To access reputations from anywhere diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index fa53c5a8a..25c7d0cfa 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -550,16 +550,16 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::Rep return true ; } -bool p3GxsReputation::isIdentityOk(const RsGxsId &id) +bool p3GxsReputation::isIdentityBanned(const RsGxsId &id) { RsReputations::ReputationInfo info ; getReputationInfo(id,info) ; #ifdef DEBUG_REPUTATION - std::cerr << "isIdentityOk(): returning " << (info.mAssessment == RsReputations::ASSESSMENT_OK) << " for GXS id " << id << std::endl; + std::cerr << "isIdentityBanned(): returning " << (info.mAssessment == RsReputations::ASSESSMENT_BAD) << " for GXS id " << id << std::endl; #endif - return info.mAssessment == RsReputations::ASSESSMENT_OK ; + return info.mAssessment == RsReputations::ASSESSMENT_BAD ; } bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::Opinion& opinion) diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index 82f954b4d..c5949dea1 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -90,7 +90,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / /***** Interface for RsReputations *****/ virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) ; virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) ; - virtual bool isIdentityOk(const RsGxsId& id) ; + virtual bool isIdentityBanned(const RsGxsId& id) ; /***** overloaded from p3Service *****/ virtual int tick(); diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 8eaa08928..f8683729b 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -412,6 +412,8 @@ bool p3IdService:: getIdDetails(const RsGxsId &id, RsIdentityDetails &details) // one utf8 symbol can be at most 4 bytes long - would be better to measure real unicode length !!! 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(); } } diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp index dc8667a84..400498823 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp @@ -878,7 +878,7 @@ bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, QLi QString GxsIdDetails::getName(const RsIdentityDetails &details) { - if(!rsReputations->isIdentityOk(details.mId)) + if(rsReputations->isIdentityBanned(details.mId)) return tr("[Banned]") ; QString name = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE); @@ -897,7 +897,7 @@ QString GxsIdDetails::getComment(const RsIdentityDetails &details) QString comment; QString nickname ; - bool banned = !rsReputations->isIdentityOk(details.mId) ; + bool banned = rsReputations->isIdentityBanned(details.mId) ; if(details.mNickname.empty()) nickname = tr("[Unknown]") ; @@ -936,7 +936,7 @@ void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList &icon { QPixmap pix ; - if(!rsReputations->isIdentityOk(details.mId)) + if(rsReputations->isIdentityBanned(details.mId)) { icons.clear() ; icons.push_back(QIcon(IMAGE_BANNED)) ; diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp index 2726a1376..4b933fd04 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp @@ -153,7 +153,7 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const QString t = RSTreeWidgetItem::data(column, role).toString(); QImage pix; - if(!rsReputations->isIdentityOk(mId)) + if(rsReputations->isIdentityBanned(mId)) pix = QImage(BANNED_IMAGE) ; else if (mAvatar.mSize == 0 || !pix.loadFromData(mAvatar.mData, mAvatar.mSize, "PNG")) pix = GxsIdDetails::makeDefaultIcon(mId); diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index a542fa87f..2bb84c485 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -901,7 +901,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum // is flagged with a bad reputation - bool redacted = !rsReputations->isIdentityOk(msg.mMeta.mAuthorId) ; + 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()); @@ -1320,7 +1320,7 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg) return; } - bool redacted = !rsReputations->isIdentityOk(msg.mMeta.mAuthorId) ; + bool redacted = rsReputations->isIdentityBanned(msg.mMeta.mAuthorId) ; mStateHelper->setActive(mTokenTypeMessageData, true); From 82c16c6a277fbee3952109c5c5fe0615e53c36a9 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 11 Oct 2015 22:08:19 -0400 Subject: [PATCH 18/23] fixed GUI tooltips over banned items. Added dropping of messages from banned identities in chat lobbies --- libretroshare/src/chat/distributedchat.cc | 12 ++++++++++++ retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp | 6 ++++-- .../src/gui/gxsforums/GxsForumThreadWidget.cpp | 9 +++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc index 7a683c2eb..aad26967c 100644 --- a/libretroshare/src/chat/distributedchat.cc +++ b/libretroshare/src/chat/distributedchat.cc @@ -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! diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp index 4b933fd04..6233b1e48 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp @@ -76,7 +76,7 @@ static void fillGxsIdRSTreeWidgetItemCallback(GxsIdDetailsType type, const RsIde break; case GXS_ID_DETAILS_TYPE_BANNED: - icons.push_back(QIcon(":/icons/yellow_biohazard64.png")) ; + icons.push_back(QIcon("BANNED_IMAGE")) ; break ; } @@ -153,7 +153,9 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const QString t = RSTreeWidgetItem::data(column, role).toString(); QImage pix; - if(rsReputations->isIdentityBanned(mId)) + 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); diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 2bb84c485..f0ea49fc7 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -989,9 +989,12 @@ 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; } @@ -1358,8 +1361,10 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg) if(redacted) { QString extraTxt = tr("

          The author of this message (with ID %1) is banned.").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ; - extraTxt += "

          • Messages from this author are not forwarded.
          • " ; - extraTxt += "
          • Messages from this author are replaced by this text.
          " ; + extraTxt += tr("
          • Messages from this author are not forwarded.
          • ") ; + extraTxt += tr("
          • Messages from this author are replaced by this text.
          ") ; + extraTxt += tr("

          You can still force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.

          ") ; + ui->postText->setHtml(extraTxt); } else From 36101a977dd9902c6bca9b3cd8b0e036097ad2e2 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 12 Oct 2015 00:28:21 -0400 Subject: [PATCH 19/23] fixed small bug preventing msg exchange --- libretroshare/src/gxs/rsgxsnetservice.cc | 4 ++-- libretroshare/src/services/p3gxsreputation.cc | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 14d09f3dc..64fe31f76 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -2016,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; @@ -2218,7 +2218,7 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) latestVersion = grpSyncItem->publishTs > metaIter->second->mPublishTs; } - if(rsReputations->isIdentityBanned(grpSyncItem->authorId)) + if(!grpSyncItem->authorId.isNull() && rsReputations->isIdentityBanned(grpSyncItem->authorId)) { std::cerr << " Identity " << grpSyncItem->authorId << " is banned. Not syncing group." << std::endl; continue ; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 25c7d0cfa..93bb9df87 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -727,6 +727,9 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: std::map::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); From 5a3756f058cd741d492b7c7ff3a373a31f8a720d Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 12 Oct 2015 10:41:48 -0400 Subject: [PATCH 20/23] fixed bug on reputation cutoff. Updated tooltips --- libretroshare/src/gxs/rsgxsnetutils.cc | 4 ++-- retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnetutils.cc b/libretroshare/src/gxs/rsgxsnetutils.cc index eb6dfb3d2..76dd8a68d 100644 --- a/libretroshare/src/gxs/rsgxsnetutils.cc +++ b/libretroshare/src/gxs/rsgxsnetutils.cc @@ -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++; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index f0ea49fc7..c298a86fc 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -408,7 +408,7 @@ 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("Flag the author as bad"), &contextMnu); + 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())); @@ -1363,7 +1363,7 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg) QString extraTxt = tr("

          The author of this message (with ID %1) is banned.").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ; extraTxt += tr("

          • Messages from this author are not forwarded.
          • ") ; extraTxt += tr("
          • Messages from this author are replaced by this text.
          ") ; - extraTxt += tr("

          You can still force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.

          ") ; + extraTxt += tr("

          You can force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.

          ") ; ui->postText->setHtml(extraTxt); } @@ -2056,7 +2056,7 @@ void GxsForumThreadWidget::loadMsgData_BanAuthor(const uint32_t &token) std::cerr << std::endl; } - emit groupChanged(this) ; + requestGroupData() ; } /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ From 7dc59845e96de501b6f6f6d125bc66d16ddf4d60 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 12 Oct 2015 14:03:53 -0400 Subject: [PATCH 21/23] added update for forum messages list when an author gets banned --- libretroshare/src/services/p3gxsreputation.cc | 49 +++++++++++++------ libretroshare/src/services/p3gxsreputation.h | 9 ++-- .../gui/gxsforums/GxsForumThreadWidget.cpp | 6 +-- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 93bb9df87..56aa79738 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -37,7 +37,6 @@ /**** * #define DEBUG_REPUTATION 1 ****/ -#define DEBUG_REPUTATION 1 /************ IMPLEMENTATION NOTES ********************************* * @@ -130,7 +129,7 @@ static const uint32_t UPPER_LIMIT = 2; // used to 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 = 60;//600 ;// 10 minutes +static const int ACTIVE_FRIENDS_UPDATE_PERIOD = 600 ; // 10 minutes static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. @@ -167,23 +166,25 @@ int p3GxsReputation::tick() { processIncoming(); sendPackets(); - - time_t now = time(NULL); - - if(mLastActiveFriendsUpdate + ACTIVE_FRIENDS_UPDATE_PERIOD < now) - { + + time_t now = time(NULL); + + if(mLastActiveFriendsUpdate + ACTIVE_FRIENDS_UPDATE_PERIOD < now) + { updateActiveFriends() ; - mLastActiveFriendsUpdate = now ; - } + 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() ; - } + static time_t last_debug_print = time(NULL) ; + + if(now > 10+last_debug_print) + { + last_debug_print = now ; + debug_print() ; + } #endif return 0; } @@ -193,6 +194,16 @@ 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 *******/ @@ -347,8 +358,10 @@ 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); @@ -360,8 +373,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); } @@ -370,8 +385,10 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request) delete pkt; } +#ifdef DEBUG_REPUTATION std::cerr << "p3GxsReputation::SendReputations() Total Count: " << totalcount; std::cerr << std::endl; +#endif return true; } diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index c5949dea1..076e14003 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -117,13 +117,12 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / // 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 &peerSet); - bool loadReputationSet(RsGxsReputationSetItem *item, - const std::set &peerSet); - - int sendPackets(); + int sendPackets(); + void cleanup(); void sendReputationRequests(); - int sendReputationRequest(RsPeerId peerid); + int sendReputationRequest(RsPeerId peerid); void debug_print() ; private: diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index c298a86fc..2079f7c29 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -1363,7 +1363,7 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg) QString extraTxt = tr("

          The author of this message (with ID %1) is banned.").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ; extraTxt += tr("

          • Messages from this author are not forwarded.
          • ") ; extraTxt += tr("
          • Messages from this author are replaced by this text.
          ") ; - extraTxt += tr("

          You can force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.

          ") ; + extraTxt += tr("

          You can force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.

          ") ; ui->postText->setHtml(extraTxt); } @@ -1746,7 +1746,6 @@ void GxsForumThreadWidget::flagpersonasbad() uint32_t token; mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeBanAuthor); - } void GxsForumThreadWidget::replytomessage() @@ -2055,8 +2054,7 @@ void GxsForumThreadWidget::loadMsgData_BanAuthor(const uint32_t &token) std::cerr << "GxsForumThreadWidget::loadMsgData_ReplyMessage() ERROR Missing Message Data..."; std::cerr << std::endl; } - - requestGroupData() ; + updateDisplay(true) ; } /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ From e6bb3073bde9d52a2ad9362ccf7357a6683413ba Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 12 Oct 2015 14:04:23 -0400 Subject: [PATCH 22/23] added update for forum messages list when an author gets banned --- retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 2079f7c29..16d7d5c6b 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -2055,6 +2055,10 @@ void GxsForumThreadWidget::loadMsgData_BanAuthor(const uint32_t &token) 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; } /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ From f18cc8295e8c81bb0489aedc34a7182ae5023677 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 12 Oct 2015 14:22:51 -0400 Subject: [PATCH 23/23] fixed up constants for reputation system, now that is has been tested --- libretroshare/src/services/p3gxsreputation.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index 56aa79738..2bcdf2498 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -131,6 +131,9 @@ static const int kMaximumPeerAge = 180; // half a 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. + p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) @@ -787,9 +790,6 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: * Send Requests. ****/ -const int kReputationRequestPeriod = 60; // 3600; // 1 hour -const int kReputationStoreWait = 180; // 3 minutes. - int p3GxsReputation::sendPackets() { time_t now = time(NULL);