mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Merge pull request #2030 from csoler/v0.6-Identity
Adding more info and statistics about GxsIds and fixing ID propagation bugs
This commit is contained in:
commit
b9a5606a25
@ -219,7 +219,13 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const
|
||||
|
||||
// network pre-request key to allow message authentication.
|
||||
|
||||
mGixs->requestKey(obj->signature.keyId,peer_list,RsIdentityUsage(RS_SERVICE_TYPE_CHAT,RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION,RsGxsGroupId(),RsGxsMessageId(),obj->lobby_id));
|
||||
mGixs->requestKey(obj->signature.keyId,peer_list,RsIdentityUsage(RsServiceType::CHAT,
|
||||
RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION,
|
||||
RsGxsGroupId(),
|
||||
RsGxsMessageId(),
|
||||
RsGxsMessageId(),
|
||||
RsGxsMessageId(),
|
||||
obj->lobby_id));
|
||||
|
||||
uint32_t size = RsChatSerialiser(RsSerializationFlags::SIGNATURE)
|
||||
.size(dynamic_cast<RsItem*>(obj));
|
||||
@ -238,7 +244,13 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const
|
||||
}
|
||||
|
||||
uint32_t error_status ;
|
||||
RsIdentityUsage use_info(RS_SERVICE_TYPE_CHAT,RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION,RsGxsGroupId(),RsGxsMessageId(),obj->lobby_id) ;
|
||||
RsIdentityUsage use_info(RsServiceType::CHAT,
|
||||
RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION,
|
||||
RsGxsGroupId(),
|
||||
RsGxsMessageId(),
|
||||
RsGxsMessageId(),
|
||||
RsGxsMessageId(),
|
||||
obj->lobby_id) ;
|
||||
|
||||
if(!mGixs->validateData(memory,size,obj->signature,false,use_info,error_status))
|
||||
{
|
||||
|
@ -450,7 +450,7 @@ void p3discovery2::recvIdentityList(const RsPeerId& pid,const std::list<RsGxsId>
|
||||
std::cerr << "p3discovery2::recvIdentityList(): from peer " << pid << ": " << ids.size() << " identities" << std::endl;
|
||||
#endif
|
||||
|
||||
RsIdentityUsage use_info(RS_SERVICE_TYPE_DISC,RsIdentityUsage::IDENTITY_DATA_UPDATE);
|
||||
RsIdentityUsage use_info(RsServiceType::GOSSIP_DISCOVERY,RsIdentityUsage::IDENTITY_NEW_FROM_DISCOVERY);
|
||||
|
||||
for(auto it(ids.begin());it!=ids.end();++it)
|
||||
{
|
||||
|
@ -2108,7 +2108,7 @@ bool p3GRouter::verifySignedDataItem(const RsGRouterAbstractMsgItem *item,const
|
||||
if(!signature_serializer.serialise(const_cast<RsGRouterAbstractMsgItem*>(item),data,&data_size))
|
||||
throw std::runtime_error("Cannot serialise signed data.");
|
||||
|
||||
RsIdentityUsage use(RS_SERVICE_TYPE_GROUTER,info);
|
||||
RsIdentityUsage use(RsServiceType::GROUTER,info);
|
||||
|
||||
if(!mGixs->validateData( data, data_size, item->signature, true, use, error_status ))
|
||||
{
|
||||
|
@ -502,6 +502,9 @@ RsGxsGrpMetaData* RsDataService::locked_getGrpMeta(RetroCursor &c, int colOffset
|
||||
RsGxsGrpMetaData* grpMeta ;
|
||||
RsGxsGroupId grpId(tempId) ;
|
||||
|
||||
if(grpId.isNull()) // not in the DB!
|
||||
return nullptr;
|
||||
|
||||
if(use_cache)
|
||||
grpMeta = mGrpMetaDataCache.getOrCreateMeta(grpId);
|
||||
else
|
||||
@ -659,8 +662,10 @@ RsGxsMsgMetaData* RsDataService::locked_getMsgMeta(RetroCursor &c, int colOffset
|
||||
std::string temp;
|
||||
c.getString(mColMsgMeta_MsgId + colOffset, temp);
|
||||
msg_id = RsGxsMessageId(temp);
|
||||
|
||||
// without these, a msg is meaningless
|
||||
ok &= (!group_id.isNull()) && (!msg_id.isNull());
|
||||
if(group_id.isNull() || msg_id.isNull())
|
||||
return nullptr;
|
||||
|
||||
RsGxsMsgMetaData* msgMeta = nullptr;
|
||||
|
||||
@ -1432,7 +1437,7 @@ int RsDataService::retrieveGxsGrpMetaData(RsGxsGrpMetaTemporaryMap& grp)
|
||||
RsGxsGrpMetaData *meta = mGrpMetaDataCache.getMeta(mit->first) ;
|
||||
|
||||
if(meta)
|
||||
grp[mit->first] = meta;
|
||||
mit->second = meta;
|
||||
else
|
||||
{
|
||||
#ifdef RS_DATA_SERVICE_DEBUG_CACHE
|
||||
@ -1446,7 +1451,7 @@ int RsDataService::retrieveGxsGrpMetaData(RsGxsGrpMetaTemporaryMap& grp)
|
||||
RsGxsGrpMetaData* meta = locked_getGrpMeta(*c, 0,true);
|
||||
|
||||
if(meta)
|
||||
grp[mit->first] = meta;
|
||||
mit->second = meta;
|
||||
|
||||
#ifdef RS_DATA_SERVICE_DEBUG_TIME
|
||||
++resultCount;
|
||||
|
@ -512,7 +512,7 @@ int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBin
|
||||
if(GxsSecurity::getSignature((char*)grpData.bin_data, grpData.bin_len, authorKey, sign))
|
||||
{
|
||||
id_ret = SIGN_SUCCESS;
|
||||
mGixs->timeStampKey(grpMeta.mAuthorId,RsIdentityUsage(mServType,RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION,grpMeta.mGroupId)) ;
|
||||
mGixs->timeStampKey(grpMeta.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION,grpMeta.mGroupId)) ;
|
||||
signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
|
||||
}
|
||||
else
|
||||
@ -680,7 +680,7 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar
|
||||
if(GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, authorKey, sign))
|
||||
{
|
||||
id_ret = SIGN_SUCCESS;
|
||||
mGixs->timeStampKey(msgMeta.mAuthorId,RsIdentityUsage(mServType,RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION,msgMeta.mGroupId,msgMeta.mMsgId)) ;
|
||||
mGixs->timeStampKey(msgMeta.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION,msgMeta.mGroupId,msgMeta.mMsgId,msgMeta.mParentId,msgMeta.mThreadId)) ;
|
||||
signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
|
||||
}
|
||||
else
|
||||
@ -905,7 +905,11 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
|
||||
{
|
||||
RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY];
|
||||
idValidate &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey);
|
||||
mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(mServType,RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId,metaData.mMsgId)) ;
|
||||
mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION,
|
||||
metaData.mGroupId,
|
||||
metaData.mMsgId,
|
||||
metaData.mParentId,
|
||||
metaData.mThreadId)) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -949,7 +953,12 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
|
||||
{
|
||||
std::list<RsPeerId> peers;
|
||||
peers.push_back(msg->PeerId());
|
||||
mGixs->requestKey(metaData.mAuthorId, peers, RsIdentityUsage(serviceType(),RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId,metaData.mMsgId));
|
||||
mGixs->requestKey(metaData.mAuthorId, peers, RsIdentityUsage((RsServiceType)serviceType(),
|
||||
RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION,
|
||||
metaData.mGroupId,
|
||||
metaData.mMsgId,
|
||||
metaData.mParentId,
|
||||
metaData.mThreadId));
|
||||
|
||||
#ifdef GEN_EXCH_DEBUG
|
||||
std::cerr << ", Key missing. Retry later." << std::endl;
|
||||
@ -1026,7 +1035,7 @@ int RsGenExchange::validateGrp(RsNxsGrp* grp)
|
||||
#ifdef GEN_EXCH_DEBUG
|
||||
std::cerr << " key ID validation result: " << idValidate << std::endl;
|
||||
#endif
|
||||
mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(mServType,RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId));
|
||||
mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1044,7 +1053,7 @@ int RsGenExchange::validateGrp(RsNxsGrp* grp)
|
||||
#endif
|
||||
std::list<RsPeerId> peers;
|
||||
peers.push_back(grp->PeerId());
|
||||
mGixs->requestKey(metaData.mAuthorId, peers,RsIdentityUsage(mServType,RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId));
|
||||
mGixs->requestKey(metaData.mAuthorId, peers,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId));
|
||||
return VALIDATE_FAIL_TRY_LATER;
|
||||
}
|
||||
}
|
||||
@ -3346,7 +3355,7 @@ bool RsGenExchange::updateValid(const RsGxsGrpMetaData& oldGrpMeta, const RsNxsG
|
||||
// also check this is the latest published group
|
||||
bool latest = newGrp.metaData->mPublishTs > oldGrpMeta.mPublishTs;
|
||||
|
||||
mGixs->timeStampKey(newGrp.metaData->mAuthorId, RsIdentityUsage(mServType,RsIdentityUsage::GROUP_ADMIN_SIGNATURE_CREATION, oldGrpMeta.mGroupId)) ;
|
||||
mGixs->timeStampKey(newGrp.metaData->mAuthorId, RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_ADMIN_SIGNATURE_CREATION, oldGrpMeta.mGroupId)) ;
|
||||
|
||||
return GxsSecurity::validateNxsGrp(newGrp, adminSign, keyMit->second) && latest;
|
||||
}
|
||||
|
@ -275,7 +275,7 @@
|
||||
NXS_NET_DEBUG_9 gxs distant search
|
||||
|
||||
***/
|
||||
#define NXS_NET_DEBUG_0 1
|
||||
//#define NXS_NET_DEBUG_0 1
|
||||
//#define NXS_NET_DEBUG_1 1
|
||||
//#define NXS_NET_DEBUG_2 1
|
||||
//#define NXS_NET_DEBUG_3 1
|
||||
@ -324,8 +324,8 @@ static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ;
|
||||
|| defined(NXS_NET_DEBUG_8) || defined(NXS_NET_DEBUG_9)
|
||||
|
||||
static const RsPeerId peer_to_print = RsPeerId();//std::string("a97fef0e2dc82ddb19200fb30f9ac575")) ;
|
||||
static const RsGxsGroupId group_id_to_print = RsGxsGroupId(std::string("66052380f5d1d0c5992e2b55dc402ce6")) ; // use this to allow to this group id only, or "" for all IDs
|
||||
static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_GXSCIRCLE; // use this to allow to this service id only, or 0 for all services
|
||||
static const RsGxsGroupId group_id_to_print = RsGxsGroupId();//std::string("66052380f5d1d0c5992e2b55dc402ce6")) ; // use this to allow to this group id only, or "" for all IDs
|
||||
static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_GXSID; // use this to allow to this service id only, or 0 for all services
|
||||
// warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums)
|
||||
|
||||
class nullstream: public std::ostream {};
|
||||
@ -593,32 +593,30 @@ void RsGxsNetService::syncWithPeers()
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<RsPeerId>::iterator sit = peers.begin();
|
||||
// for now just grps
|
||||
for(auto sit = peers.begin(); sit != peers.end(); ++sit)
|
||||
{
|
||||
|
||||
// for now just grps
|
||||
for(; sit != peers.end(); ++sit)
|
||||
{
|
||||
const RsPeerId peerId = *sit;
|
||||
|
||||
const RsPeerId peerId = *sit;
|
||||
ClientGrpMap::const_iterator cit = mClientGrpUpdateMap.find(peerId);
|
||||
uint32_t updateTS = 0;
|
||||
|
||||
ClientGrpMap::const_iterator cit = mClientGrpUpdateMap.find(peerId);
|
||||
uint32_t updateTS = 0;
|
||||
|
||||
if(cit != mClientGrpUpdateMap.end())
|
||||
{
|
||||
const RsGxsGrpUpdate *gui = &cit->second;
|
||||
updateTS = gui->grpUpdateTS;
|
||||
}
|
||||
RsNxsSyncGrpReqItem *grp = new RsNxsSyncGrpReqItem(mServType);
|
||||
grp->clear();
|
||||
grp->PeerId(*sit);
|
||||
grp->updateTS = updateTS;
|
||||
if(cit != mClientGrpUpdateMap.end())
|
||||
{
|
||||
const RsGxsGrpUpdate *gui = &cit->second;
|
||||
updateTS = gui->grpUpdateTS;
|
||||
}
|
||||
RsNxsSyncGrpReqItem *grp = new RsNxsSyncGrpReqItem(mServType);
|
||||
grp->clear();
|
||||
grp->PeerId(*sit);
|
||||
grp->updateTS = updateTS;
|
||||
|
||||
#ifdef NXS_NET_DEBUG_5
|
||||
GXSNETDEBUG_P_(*sit) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global group TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) to himself" << std::endl;
|
||||
GXSNETDEBUG_P_(*sit) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global group TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) to himself" << std::endl;
|
||||
#endif
|
||||
generic_sendItem(grp);
|
||||
}
|
||||
generic_sendItem(grp);
|
||||
}
|
||||
|
||||
if(!mAllowMsgSync)
|
||||
return ;
|
||||
@ -644,15 +642,13 @@ void RsGxsNetService::syncWithPeers()
|
||||
}
|
||||
}
|
||||
|
||||
sit = peers.begin();
|
||||
|
||||
// Synchronise group msg for groups which we're subscribed to
|
||||
// For each peer and each group, we send to the peer the time stamp of the most
|
||||
// recent modification the peer has sent. If the peer has more recent messages he will send them, because its latest
|
||||
// modifications will be more recent. This ensures that we always compare timestamps all taken in the same
|
||||
// computer (the peer's computer in this case)
|
||||
|
||||
for(; sit != peers.end(); ++sit)
|
||||
for(auto sit = peers.begin(); sit != peers.end(); ++sit)
|
||||
{
|
||||
const RsPeerId& peerId = *sit;
|
||||
|
||||
@ -3183,7 +3179,8 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr)
|
||||
{
|
||||
grpItemL.push_back(item);
|
||||
grpMetaMap[item->grpId] = NULL;
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NXS_NET_DEBUG_0
|
||||
GXSNETDEBUG_PG(tr->mTransaction->PeerId(),item->grpId) << "RsGxsNetService::genReqGrpTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl;
|
||||
@ -3226,7 +3223,7 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr)
|
||||
RsNxsSyncGrpItem*& grpSyncItem = *llit;
|
||||
const RsGxsGroupId& grpId = grpSyncItem->grpId;
|
||||
|
||||
std::map<RsGxsGroupId, RsGxsGrpMetaData*>::const_iterator metaIter = grpMetaMap.find(grpId);
|
||||
std::map<RsGxsGroupId, RsGxsGrpMetaData*>::const_iterator metaIter = grpMetaMap.find(grpId);
|
||||
bool haveItem = false;
|
||||
bool latestVersion = false;
|
||||
|
||||
@ -3237,19 +3234,21 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr)
|
||||
}
|
||||
// FIXTESTS global variable rsReputations not available in unittests!
|
||||
|
||||
#warning csoler 2016-12-23: Update the code below to correctly send/recv dependign on reputation
|
||||
if( !grpSyncItem->authorId.isNull() &&
|
||||
mReputations->overallReputationLevel(grpSyncItem->authorId) ==
|
||||
RsReputationLevel::LOCALLY_NEGATIVE )
|
||||
if( mReputations->overallReputationLevel(RsGxsId(grpSyncItem->grpId)) == RsReputationLevel::LOCALLY_NEGATIVE )
|
||||
{
|
||||
#ifdef NXS_NET_DEBUG_0
|
||||
GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpSyncItem->authorId << " is banned. Not syncing group." << std::endl;
|
||||
GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpSyncItem->grpId << " is banned. Not GXS-syncing group." << std::endl;
|
||||
#endif
|
||||
continue ;
|
||||
}
|
||||
|
||||
if( (mGrpAutoSync && !haveItem) || latestVersion)
|
||||
{
|
||||
#ifdef NXS_NET_DEBUG_0
|
||||
GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpId << " will be sync-ed using GXS. mGrpAutoSync:" << mGrpAutoSync << " haveItem:" << haveItem << " latest_version: " << latestVersion << std::endl;
|
||||
#endif
|
||||
addGroupItemToList(tr, grpId, transN, reqList);
|
||||
}
|
||||
}
|
||||
|
||||
if(!reqList.empty())
|
||||
|
@ -215,7 +215,8 @@ bool RsGxsIntegrityCheck::check()
|
||||
rsReputations->overallReputationLevel(
|
||||
grp->metaData->mAuthorId ) >
|
||||
RsReputationLevel::LOCALLY_NEGATIVE )
|
||||
used_gxs_ids.insert(std::make_pair(grp->metaData->mAuthorId, RsIdentityUsage(mGenExchangeClient->serviceType(), RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE,grp->grpId)));
|
||||
used_gxs_ids.insert(std::make_pair(grp->metaData->mAuthorId, RsIdentityUsage(RsServiceType(mGenExchangeClient->serviceType()),
|
||||
RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE,grp->grpId)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -404,7 +405,12 @@ bool RsGxsIntegrityCheck::check()
|
||||
rsReputations->overallReputationLevel(
|
||||
msg->metaData->mAuthorId ) >
|
||||
RsReputationLevel::LOCALLY_NEGATIVE )
|
||||
used_gxs_ids.insert(std::make_pair(msg->metaData->mAuthorId,RsIdentityUsage(mGenExchangeClient->serviceType(),RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE,msg->metaData->mGroupId,msg->metaData->mMsgId))) ;
|
||||
used_gxs_ids.insert(std::make_pair(msg->metaData->mAuthorId,RsIdentityUsage(RsServiceType(mGenExchangeClient->serviceType()),
|
||||
RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE,
|
||||
msg->metaData->mGroupId,
|
||||
msg->metaData->mMsgId,
|
||||
msg->metaData->mParentId,
|
||||
msg->metaData->mThreadId))) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -976,7 +976,7 @@ void p3GxsTunnelService::handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item)
|
||||
std::cerr << "(SS) Signature was verified and it doesn't check! This is a security issue!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
mGixs->timeStampKey(item->signature.keyId,RsIdentityUsage(RS_SERVICE_TYPE_GXS_TUNNEL,RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CHECK));
|
||||
mGixs->timeStampKey(item->signature.keyId,RsIdentityUsage(RsServiceType::GXS_TUNNEL,RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CHECK));
|
||||
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << " Signature checks! Sender's ID = " << senders_id << std::endl;
|
||||
|
@ -234,31 +234,30 @@ struct RsIdentityUsage : RsSerializable
|
||||
GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c,
|
||||
GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d,
|
||||
|
||||
/// Identity received through GXS sync
|
||||
IDENTITY_NEW_FROM_GXS_SYNC = 0x0e,
|
||||
/// Group update on that identity data. Can be avatar, name, etc.
|
||||
IDENTITY_DATA_UPDATE = 0x0e,
|
||||
IDENTITY_NEW_FROM_DISCOVERY = 0x0f,
|
||||
/// Explicit request to friend
|
||||
IDENTITY_NEW_FROM_EXPLICIT_REQUEST = 0x10,
|
||||
|
||||
/// Any signature verified for that identity
|
||||
IDENTITY_GENERIC_SIGNATURE_CHECK = 0x0f,
|
||||
IDENTITY_GENERIC_SIGNATURE_CHECK = 0x11,
|
||||
|
||||
/// Any signature made by that identity
|
||||
IDENTITY_GENERIC_SIGNATURE_CREATION = 0x10,
|
||||
IDENTITY_GENERIC_SIGNATURE_CREATION = 0x12,
|
||||
|
||||
IDENTITY_GENERIC_ENCRYPTION = 0x11,
|
||||
IDENTITY_GENERIC_DECRYPTION = 0x12,
|
||||
CIRCLE_MEMBERSHIP_CHECK = 0x13
|
||||
IDENTITY_GENERIC_ENCRYPTION = 0x13,
|
||||
IDENTITY_GENERIC_DECRYPTION = 0x14,
|
||||
CIRCLE_MEMBERSHIP_CHECK = 0x15
|
||||
} ;
|
||||
|
||||
RS_DEPRECATED
|
||||
RsIdentityUsage( uint16_t service, const RsIdentityUsage::UsageCode& code,
|
||||
const RsGxsGroupId& gid = RsGxsGroupId(),
|
||||
const RsGxsMessageId& mid = RsGxsMessageId(),
|
||||
uint64_t additional_id=0,
|
||||
const std::string& comment = std::string() );
|
||||
|
||||
RsIdentityUsage( RsServiceType service,
|
||||
RsIdentityUsage::UsageCode code,
|
||||
const RsGxsGroupId& gid = RsGxsGroupId(),
|
||||
const RsGxsMessageId& mid = RsGxsMessageId(),
|
||||
const RsGxsMessageId& message_id = RsGxsMessageId(),
|
||||
const RsGxsMessageId& parent_id = RsGxsMessageId(),
|
||||
const RsGxsMessageId& thread_id = RsGxsMessageId(),
|
||||
uint64_t additional_id=0,
|
||||
const std::string& comment = std::string() );
|
||||
|
||||
@ -275,6 +274,12 @@ struct RsIdentityUsage : RsSerializable
|
||||
/// Message ID using the identity
|
||||
RsGxsMessageId mMsgId;
|
||||
|
||||
/// Reference message ID. Useful for votes/comments
|
||||
RsGxsMessageId mParentId;
|
||||
|
||||
/// Reference message ID. Useful for votes/comments
|
||||
RsGxsMessageId mThreadId;
|
||||
|
||||
/// Some additional ID. Can be used for e.g. chat lobbies.
|
||||
uint64_t mAdditionalId;
|
||||
|
||||
|
@ -1463,12 +1463,14 @@ bool p3GxsCircles::locked_processLoadingCacheEntry(RsGxsCircleCache& cache)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
std::cerr << " (WW) cache entry for circle " << cache.mCircleId << " has empty originator. Asking info for GXS id " << pit->first << " to all connected friends." << std::endl;
|
||||
#endif
|
||||
|
||||
rsPeers->getOnlineList(peers) ;
|
||||
}
|
||||
|
||||
mIdentities->requestKey(pit->first, peers,RsIdentityUsage(serviceType(),RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK,RsGxsGroupId(cache.mCircleId)));
|
||||
mIdentities->requestKey(pit->first, peers,RsIdentityUsage(RsServiceType::GXSCIRCLE,RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK,RsGxsGroupId(cache.mCircleId)));
|
||||
|
||||
all_ids_here = false;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@
|
||||
#define ID_REQUEST_REPUTATION 0x0003
|
||||
#define ID_REQUEST_OPINION 0x0004
|
||||
|
||||
#define GXSID_MAX_CACHE_SIZE 5000
|
||||
#define GXSID_MAX_CACHE_SIZE 15000
|
||||
|
||||
// unused keys are deleted according to some heuristic that should favor known keys, signed keys etc.
|
||||
|
||||
@ -616,11 +616,11 @@ void p3IdService::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
std::cerr << "p3IdService::notifyChanges() Found Group Change Notification";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
const RsGxsGroupId& gid(groupChange->mGroupId);
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "p3IdService::notifyChanges() Auto Subscribe to Incoming Groups: " << *git;
|
||||
std::cerr << "p3IdService::notifyChanges() Auto Subscribe to Incoming Groups: " << gid;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
const RsGxsGroupId& gid(groupChange->mGroupId);
|
||||
|
||||
if(!rsReputations->isIdentityBanned(RsGxsId(gid)))
|
||||
{
|
||||
@ -641,7 +641,7 @@ void p3IdService::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
rsEvents->postEvent(ev);
|
||||
|
||||
// also time_stamp the key that this group represents
|
||||
timeStampKey(RsGxsId(gid),RsIdentityUsage(serviceType(),RsIdentityUsage::IDENTITY_DATA_UPDATE)) ;
|
||||
timeStampKey(RsGxsId(gid),RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC)) ;
|
||||
should_subscribe = true;
|
||||
}
|
||||
break;
|
||||
@ -654,8 +654,10 @@ void p3IdService::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
rsEvents->postEvent(ev);
|
||||
|
||||
// also time_stamp the key that this group represents
|
||||
timeStampKey(RsGxsId(gid),RsIdentityUsage(serviceType(),RsIdentityUsage::IDENTITY_DATA_UPDATE)) ;
|
||||
timeStampKey(RsGxsId(gid),RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC)) ;
|
||||
should_subscribe = true;
|
||||
|
||||
std::cerr << "Received new identity " << gid << " and subscribing to it" << std::endl;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1214,8 +1216,7 @@ bool p3IdService::requestIdentity(
|
||||
return false;
|
||||
}
|
||||
|
||||
RsIdentityUsage usageInfo( RsServiceType::GXSID,
|
||||
RsIdentityUsage::IDENTITY_DATA_UPDATE );
|
||||
RsIdentityUsage usageInfo( RsServiceType::GXSID, RsIdentityUsage::IDENTITY_NEW_FROM_EXPLICIT_REQUEST );
|
||||
|
||||
return requestKey(id, askPeersList, usageInfo);
|
||||
}
|
||||
@ -1250,8 +1251,9 @@ bool p3IdService::requestKey(const RsGxsId &id, const std::list<RsPeerId>& peers
|
||||
|
||||
if( info.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE )
|
||||
{
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " not requesting Key " << id
|
||||
<< " because it has been banned." << std::endl;
|
||||
#ifdef DEBUG_IDS
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " not requesting Key " << id << " because it has been banned." << std::endl;
|
||||
#endif
|
||||
|
||||
RS_STACK_MUTEX(mIdMtx);
|
||||
mIdsNotPresent.erase(id);
|
||||
@ -1360,7 +1362,7 @@ bool p3IdService::signData(const uint8_t *data,uint32_t data_size,const RsGxsId&
|
||||
return false ;
|
||||
}
|
||||
error_status = RS_GIXS_ERROR_NO_ERROR ;
|
||||
timeStampKey(own_gxs_id,RsIdentityUsage(serviceType(),RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CREATION)) ;
|
||||
timeStampKey(own_gxs_id,RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CREATION)) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@ -1433,7 +1435,7 @@ bool p3IdService::encryptData( const uint8_t *decrypted_data,
|
||||
return false ;
|
||||
}
|
||||
error_status = RS_GIXS_ERROR_NO_ERROR ;
|
||||
timeStampKey(encryption_key_id,RsIdentityUsage(serviceType(),RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION)) ;
|
||||
timeStampKey(encryption_key_id,RsIdentityUsage(RsServiceType::GXSID,RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION)) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@ -1522,7 +1524,7 @@ bool p3IdService::encryptData( const uint8_t* decrypted_data,
|
||||
{
|
||||
timeStampKey( *it,
|
||||
RsIdentityUsage(
|
||||
serviceType(),
|
||||
RsServiceType::GXSID,
|
||||
RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION ) );
|
||||
}
|
||||
|
||||
@ -1563,7 +1565,7 @@ bool p3IdService::decryptData( const uint8_t *encrypted_data,
|
||||
error_status = RS_GIXS_ERROR_NO_ERROR;
|
||||
timeStampKey( key_id,
|
||||
RsIdentityUsage(
|
||||
serviceType(),
|
||||
RsServiceType::GXSID,
|
||||
RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION) );
|
||||
|
||||
return true ;
|
||||
@ -1656,7 +1658,7 @@ bool p3IdService::decryptData( const uint8_t* encrypted_data,
|
||||
{
|
||||
timeStampKey( *it,
|
||||
RsIdentityUsage(
|
||||
serviceType(),
|
||||
RsServiceType::GXSID,
|
||||
RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION ) );
|
||||
}
|
||||
|
||||
@ -2292,7 +2294,7 @@ bool SSGxsIdGroup::load(const std::string &input)
|
||||
char scorestr[RSGXSID_MAX_SERVICE_STRING];
|
||||
|
||||
// split into parts.
|
||||
if (3 != sscanf(input.c_str(), "v2 {P:%[^}]} {T:%[^}]} {R:%[^}]}", pgpstr, recognstr, scorestr))
|
||||
if (3 != sscanf(input.c_str(), "v2 {P:%[^}]}{T:%[^}]}{R:%[^}]}", pgpstr, recognstr, scorestr))
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "SSGxsIdGroup::load() Failed to extract 4 Parts";
|
||||
@ -2954,9 +2956,21 @@ void p3IdService::requestIdsFromNet()
|
||||
for(cit = mIdsNotPresent.begin(); cit != mIdsNotPresent.end();)
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
Dbg2() << __PRETTY_FUNCTION__ << " Processing missing key RsGxsId: "
|
||||
<< cit->first << std::endl;
|
||||
Dbg2() << __PRETTY_FUNCTION__ << " Processing missing key RsGxsId: " << cit->first << std::endl;
|
||||
#endif
|
||||
RsGxsIdCache data;
|
||||
|
||||
if(mKeyCache.fetch(cit->first,data))
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << __PRETTY_FUNCTION__ << ". Dropping request for ID " << cit->first << " at last minute, because it was found in cache"<< std::endl;
|
||||
#endif
|
||||
auto tmp(cit);
|
||||
++tmp;
|
||||
mIdsNotPresent.erase(cit);
|
||||
cit = tmp;
|
||||
continue;
|
||||
}
|
||||
|
||||
const RsGxsId& gxsId = cit->first;
|
||||
const std::list<RsPeerId>& peers = cit->second;
|
||||
@ -3011,8 +3025,7 @@ void p3IdService::requestIdsFromNet()
|
||||
{
|
||||
const RsPeerId& peer = cit2->first;
|
||||
std::list<RsGxsGroupId> grpIds;
|
||||
for( std::list<RsGxsId>::const_iterator gxs_id_it = cit2->second.begin();
|
||||
gxs_id_it != cit2->second.end(); ++gxs_id_it )
|
||||
for( std::list<RsGxsId>::const_iterator gxs_id_it = cit2->second.begin(); gxs_id_it != cit2->second.end(); ++gxs_id_it )
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
Dbg2() << __PRETTY_FUNCTION__ << " passing RsGxsId: " << *gxs_id_it
|
||||
@ -3223,7 +3236,7 @@ bool p3IdService::cachetest_handlerequest(uint32_t token)
|
||||
if (!haveKey(*vit))
|
||||
{
|
||||
std::list<RsPeerId> nullpeers;
|
||||
requestKey(*vit, nullpeers,RsIdentityUsage(serviceType(),RsIdentityUsage::UNKNOWN_USAGE));
|
||||
requestKey(*vit, nullpeers,RsIdentityUsage(RsServiceType::GXSID,RsIdentityUsage::UNKNOWN_USAGE));
|
||||
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "p3IdService::cachetest_request() Requested Key Id: " << *vit;
|
||||
@ -4819,11 +4832,10 @@ void RsGxsIdGroup::serial_process(
|
||||
RS_SERIAL_PROCESS(mReputation);
|
||||
}
|
||||
|
||||
RsIdentityUsage::RsIdentityUsage(
|
||||
RsServiceType service, RsIdentityUsage::UsageCode code,
|
||||
const RsGxsGroupId& gid, const RsGxsMessageId& mid,
|
||||
RsIdentityUsage::RsIdentityUsage(RsServiceType service, RsIdentityUsage::UsageCode code,
|
||||
const RsGxsGroupId& gid, const RsGxsMessageId& mid, const RsGxsMessageId &pid, const RsGxsMessageId &tid,
|
||||
uint64_t additional_id, const std::string& comment ) :
|
||||
mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),
|
||||
mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),mParentId(pid),mThreadId(tid),
|
||||
mAdditionalId(additional_id), mComment(comment)
|
||||
{
|
||||
/* This is a hack, since it will hash also mHash, but because it is
|
||||
@ -4841,42 +4853,6 @@ RsIdentityUsage::RsIdentityUsage(
|
||||
mHash = hs.hash();
|
||||
}
|
||||
|
||||
RsIdentityUsage::RsIdentityUsage(
|
||||
uint16_t service, const RsIdentityUsage::UsageCode& code,
|
||||
const RsGxsGroupId& gid, const RsGxsMessageId& mid,
|
||||
uint64_t additional_id,const std::string& comment ) :
|
||||
mServiceId(static_cast<RsServiceType>(service)), mUsageCode(code),
|
||||
mGrpId(gid), mMsgId(mid), mAdditionalId(additional_id), mComment(comment)
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "New identity usage: " << std::endl;
|
||||
std::cerr << " service=" << std::hex << service << std::endl;
|
||||
std::cerr << " code =" << std::hex << code << std::endl;
|
||||
std::cerr << " grpId =" << std::hex << gid << std::endl;
|
||||
std::cerr << " msgId =" << std::hex << mid << std::endl;
|
||||
std::cerr << " add id =" << std::hex << additional_id << std::endl;
|
||||
std::cerr << " commnt =\"" << std::hex << comment << "\"" << std::endl;
|
||||
#endif
|
||||
|
||||
/* This is a hack, since it will hash also mHash, but because it is
|
||||
* initialized to 0, and only computed in the constructor here, it should
|
||||
* be ok. */
|
||||
librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1) ;
|
||||
|
||||
hs << (uint32_t)service ; // G10h4ck: Why uint32 if it's 16 bits?
|
||||
hs << (uint8_t)code ;
|
||||
hs << gid ;
|
||||
hs << mid ;
|
||||
hs << (uint64_t)additional_id ;
|
||||
hs << comment ;
|
||||
|
||||
mHash = hs.hash();
|
||||
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << " hash =\"" << std::hex << mHash << "\"" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
RsIdentityUsage::RsIdentityUsage() :
|
||||
mServiceId(RsServiceType::NONE), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0)
|
||||
{}
|
||||
|
@ -1862,10 +1862,17 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
||||
{
|
||||
case RsServiceType::CHANNELS: service_name = tr("Channels") ;service_type = RetroShareLink::TYPE_CHANNEL ; break ;
|
||||
case RsServiceType::FORUMS: service_name = tr("Forums") ; service_type = RetroShareLink::TYPE_FORUM ; break ;
|
||||
case RsServiceType::POSTED: service_name = tr("Posted") ; service_type = RetroShareLink::TYPE_POSTED ; break ;
|
||||
case RsServiceType::POSTED: service_name = tr("Boards") ; service_type = RetroShareLink::TYPE_POSTED ; break ;
|
||||
case RsServiceType::CHAT: service_name = tr("Chat") ; service_type = RetroShareLink::TYPE_CHAT_ROOM ; break ;
|
||||
|
||||
case RsServiceType::GXS_TRANS: return tr("GxsMail author ");
|
||||
#ifdef TODO
|
||||
// We need a RS link for circles if we want to do that.
|
||||
//
|
||||
case RsServiceType::GXSCIRCLE: service_name = tr("GxsCircles"); service_type = RetroShareLink::TYPE_CIRCLES; break ;
|
||||
#endif
|
||||
default:
|
||||
service_name = tr("Unknown"); service_type = RetroShareLink::TYPE_UNKNOWN ;
|
||||
service_name = tr("Unknown (service=")+QString::number((int)u.mServiceId,16)+")"; service_type = RetroShareLink::TYPE_UNKNOWN ;
|
||||
}
|
||||
|
||||
switch(u.mUsageCode)
|
||||
@ -1885,10 +1892,25 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
||||
return tr("Group author for group %1 in service %2").arg(QString::fromStdString(u.mGrpId.toStdString())).arg(service_name);
|
||||
break ;
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION:
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand.
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawling the set of messages for all groups. That helps keepign the useful identities in hand.
|
||||
{
|
||||
RetroShareLink l = RetroShareLink::createGxsMessageLink(service_type,u.mGrpId,u.mMsgId,tr("Message/vote/comment"));
|
||||
return tr("%1 in %2 tab").arg(l.toHtml()).arg(service_name) ;
|
||||
RetroShareLink l;
|
||||
|
||||
std::cerr << "Signature validation/keep alive signature:" << std::endl;
|
||||
std::cerr << " service ID = " << std::hex << (uint16_t)u.mServiceId << std::dec << std::endl;
|
||||
std::cerr << " u.mGrpId = " << u.mGrpId << std::endl;
|
||||
std::cerr << " u.mMsgId = " << u.mMsgId << std::endl;
|
||||
std::cerr << " u.mParentId = " << u.mParentId << std::endl;
|
||||
std::cerr << " u.mThreadId = " << u.mThreadId << std::endl;
|
||||
|
||||
if(service_type == RetroShareLink::TYPE_CHANNEL && !u.mThreadId.isNull())
|
||||
l = RetroShareLink::createGxsMessageLink(service_type,u.mGrpId,u.mThreadId,tr("Vote/comment"));
|
||||
else if(service_type == RetroShareLink::TYPE_POSTED && !u.mThreadId.isNull())
|
||||
l = RetroShareLink::createGxsMessageLink(service_type,u.mGrpId,u.mThreadId,tr("Vote"));
|
||||
else
|
||||
l = RetroShareLink::createGxsMessageLink(service_type,u.mGrpId,u.mMsgId,tr("Message"));
|
||||
|
||||
return tr("%1 in %2 service").arg(l.toHtml()).arg(service_name) ;
|
||||
}
|
||||
case RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION: // Chat lobby msgs are signed, so each time one comes, or a chat lobby event comes, a signature verificaiton happens.
|
||||
{
|
||||
@ -1914,9 +1936,13 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
||||
{
|
||||
return tr("Signature in distant tunnel system.");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_DATA_UPDATE: // Group update on that identity data. Can be avatar, name, etc.
|
||||
case RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC: // Group update on that identity data. Can be avatar, name, etc.
|
||||
{
|
||||
return tr("Update of identity data.");
|
||||
return tr("Received from GXS sync.");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_NEW_FROM_DISCOVERY: // Own friend sended his own ids
|
||||
{
|
||||
return tr("Friend node identity received through discovery.");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CHECK: // Any signature verified for that identity
|
||||
{
|
||||
@ -1924,11 +1950,18 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CREATION: // Any signature made by that identity
|
||||
{
|
||||
return tr("Generic signature.");
|
||||
return tr("Generic signature creation (e.g. chat room message, global router,...).");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION: return tr("Generic encryption.");
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION: return tr("Generic decryption.");
|
||||
case RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK: return tr("Membership verification in circle %1.").arg(QString::fromStdString(u.mGrpId.toStdString()));
|
||||
case RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK:
|
||||
{
|
||||
RsGxsCircleDetails det;
|
||||
if(rsGxsCircles->getCircleDetails(RsGxsCircleId(u.mGrpId),det))
|
||||
return tr("Membership verification in circle \"%1\" (%2).").arg(QString::fromUtf8(det.mCircleName.c_str())).arg(QString::fromStdString(u.mGrpId.toStdString()));
|
||||
else
|
||||
return tr("Membership verification in circle (ID=%1).").arg(QString::fromStdString(u.mGrpId.toStdString()));
|
||||
}
|
||||
|
||||
#warning TODO! csoler 2017-01-03: Add the different strings and translations here.
|
||||
default:
|
||||
|
588
retroshare-gui/src/gui/statistics/GxsIdStatistics.cpp
Normal file
588
retroshare-gui/src/gui/statistics/GxsIdStatistics.cpp
Normal file
@ -0,0 +1,588 @@
|
||||
/*******************************************************************************
|
||||
* gui/statistics/GlobalRouterStatistics.cpp *
|
||||
* *
|
||||
* Copyright (c) 2011 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
#include <QFontMetrics>
|
||||
#include <QWheelEvent>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QStylePainter>
|
||||
#include <QLayout>
|
||||
#include <QHeaderView>
|
||||
|
||||
#include <retroshare/rsidentity.h>
|
||||
#include <retroshare/rsservicecontrol.h>
|
||||
|
||||
#include "GxsIdStatistics.h"
|
||||
|
||||
#include "util/DateTime.h"
|
||||
#include "util/QtVersion.h"
|
||||
#include "util/misc.h"
|
||||
#include "util/qtthreadsutils.h"
|
||||
|
||||
static QColor colorScale(float f)
|
||||
{
|
||||
if(f == 0)
|
||||
return QColor::fromHsv(0,0,192) ;
|
||||
else
|
||||
return QColor::fromHsv((int)((1.0-f)*280),200,255) ;
|
||||
}
|
||||
|
||||
GxsIdStatistics::GxsIdStatistics(QWidget *parent)
|
||||
: RsAutoUpdatePage(4000,parent)
|
||||
{
|
||||
setupUi(this) ;
|
||||
|
||||
_stats_F->setWidget(_tst_CW = new GxsIdStatisticsWidget);
|
||||
m_bProcessSettings = false;
|
||||
|
||||
// load settings
|
||||
processSettings(true);
|
||||
}
|
||||
|
||||
GxsIdStatistics::~GxsIdStatistics()
|
||||
{
|
||||
// save settings
|
||||
processSettings(false);
|
||||
}
|
||||
|
||||
void GxsIdStatistics::processSettings(bool bLoad)
|
||||
{
|
||||
m_bProcessSettings = true;
|
||||
|
||||
Settings->beginGroup(QString("GlobalRouterStatistics"));
|
||||
|
||||
if (bLoad) {
|
||||
// load settings
|
||||
|
||||
// state of splitter
|
||||
//splitter->restoreState(Settings->value("Splitter").toByteArray());
|
||||
} else {
|
||||
// save settings
|
||||
|
||||
// state of splitter
|
||||
//Settings->setValue("Splitter", splitter->saveState());
|
||||
|
||||
}
|
||||
|
||||
Settings->endGroup();
|
||||
|
||||
m_bProcessSettings = false;
|
||||
}
|
||||
|
||||
void GxsIdStatistics::updateDisplay()
|
||||
{
|
||||
_tst_CW->updateContent() ;
|
||||
|
||||
static rstime_t last_data_update_time = 0;
|
||||
rstime_t now = time(NULL);
|
||||
|
||||
if(now > last_data_update_time + 60)
|
||||
{
|
||||
last_data_update_time = now;
|
||||
_tst_CW->updateData();
|
||||
}
|
||||
}
|
||||
|
||||
static QString getServiceName(uint32_t s)
|
||||
{
|
||||
switch(s)
|
||||
{
|
||||
default:
|
||||
case 0x0011 /* GOSSIP_DISCOVERY */ : return QObject::tr("Discovery");
|
||||
case 0x0012 /* CHAT */ : return QObject::tr("Chat");
|
||||
case 0x0013 /* MSG */ : return QObject::tr("Messages");
|
||||
case 0x0014 /* TURTLE */ : return QObject::tr("Turtle");
|
||||
case 0x0016 /* HEARTBEAT */ : return QObject::tr("Heartbeat");
|
||||
case 0x0017 /* FILE_TRANSFER */ : return QObject::tr("File transfer");
|
||||
case 0x0018 /* GROUTER */ : return QObject::tr("Global router");
|
||||
case 0x0019 /* FILE_DATABASE */ : return QObject::tr("File database");
|
||||
case 0x0020 /* SERVICEINFO */ : return QObject::tr("Service info");
|
||||
case 0x0021 /* BANDWIDTH_CONTROL */ : return QObject::tr("Bandwidth control");
|
||||
case 0x0022 /* MAIL */ : return QObject::tr("Mail");
|
||||
case 0x0023 /* DIRECT_MAIL */ : return QObject::tr("Mail");
|
||||
case 0x0024 /* DISTANT_MAIL */ : return QObject::tr("Distant mail");
|
||||
case 0x0026 /* SERVICE_CONTROL */ : return QObject::tr("Service control");
|
||||
case 0x0027 /* DISTANT_CHAT */ : return QObject::tr("Distant chat");
|
||||
case 0x0028 /* GXS_TUNNEL */ : return QObject::tr("GXS Tunnel");
|
||||
case 0x0101 /* BANLIST */ : return QObject::tr("Ban list");
|
||||
case 0x0102 /* STATUS */ : return QObject::tr("Status");
|
||||
case 0x0200 /* NXS */ : return QObject::tr("NXS");
|
||||
case 0x0211 /* GXSID */ : return QObject::tr("Identities");
|
||||
case 0x0212 /* PHOTO */ : return QObject::tr("GXS Photo");
|
||||
case 0x0213 /* WIKI */ : return QObject::tr("GXS Wiki");
|
||||
case 0x0214 /* WIRE */ : return QObject::tr("GXS TheWire");
|
||||
case 0x0215 /* FORUMS */ : return QObject::tr("Forums");
|
||||
case 0x0216 /* POSTED */ : return QObject::tr("Boards");
|
||||
case 0x0217 /* CHANNELS */ : return QObject::tr("Channels");
|
||||
case 0x0218 /* GXSCIRCLE */ : return QObject::tr("Circles");
|
||||
/// entiti not gxs, but used with :dentities.
|
||||
case 0x0219 /* REPUTATION */ : return QObject::tr("Reputation");
|
||||
case 0x0220 /* GXS_RECOGN */ : return QObject::tr("Recogn");
|
||||
case 0x0230 /* GXS_TRANS */ : return QObject::tr("GXS Transport");
|
||||
case 0x0240 /* JSONAPI */ : return QObject::tr("JSon API");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static QString getUsageStatisticsName(RsIdentityUsage::UsageCode code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
default:
|
||||
case RsIdentityUsage::UNKNOWN_USAGE : return QObject::tr("Unknown");
|
||||
case RsIdentityUsage::GROUP_ADMIN_SIGNATURE_CREATION : return QObject::tr("Group admin signature creation");
|
||||
case RsIdentityUsage::GROUP_ADMIN_SIGNATURE_VALIDATION : return QObject::tr("Group admin signature validation");
|
||||
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION : return QObject::tr("Group author signature creation");
|
||||
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION : return QObject::tr("Group author signature validation");
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION : return QObject::tr("Message author signature creation");
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION : return QObject::tr("Message author signature validation");
|
||||
case RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE : return QObject::tr("Routine group author signature check.");
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE : return QObject::tr("Routine message author signature check");
|
||||
case RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION : return QObject::tr("Chat room signature validation");
|
||||
case RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK : return QObject::tr("Global router message validation");
|
||||
case RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CREATION : return QObject::tr("Global router message creation");
|
||||
case RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CHECK : return QObject::tr("DH Key exchange validation for GXS tunnel");
|
||||
case RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CREATION : return QObject::tr("DH Key exchange creation for GXS tunnel");
|
||||
case RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC : return QObject::tr("New identity from GXS sync");
|
||||
case RsIdentityUsage::IDENTITY_NEW_FROM_DISCOVERY : return QObject::tr("New friend identity from discovery");
|
||||
case RsIdentityUsage::IDENTITY_NEW_FROM_EXPLICIT_REQUEST : return QObject::tr("New identity requested from friend node");
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CHECK : return QObject::tr("Generic signature validation");
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CREATION : return QObject::tr("Generic signature creation");
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION : return QObject::tr("Generic data decryption");
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION : return QObject::tr("Generic data encryption");
|
||||
case RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK : return QObject::tr("Circle membership checking");
|
||||
}
|
||||
}
|
||||
|
||||
void GxsIdStatisticsWidget::updateData()
|
||||
{
|
||||
// get the info, stats, histograms and pass them
|
||||
|
||||
RsThread::async([this]()
|
||||
{
|
||||
// 1 - get group data
|
||||
|
||||
#ifdef DEBUG_FORUMS
|
||||
std::cerr << "Retrieving post data for post " << mThreadId << std::endl;
|
||||
#endif
|
||||
|
||||
auto pids = new std::list<RsGroupMetaData>() ;
|
||||
rsIdentity->getIdentitiesSummaries(*pids) ;
|
||||
|
||||
RsQThreadUtils::postToObject( [pids,this]()
|
||||
{
|
||||
/* Here it goes any code you want to be executed on the Qt Gui
|
||||
* thread, for example to update the data model with new information
|
||||
* after a blocking call to RetroShare API complete */
|
||||
|
||||
const auto& ids(*pids);
|
||||
|
||||
time_t now = time(NULL);
|
||||
mPublishDateHist = Histogram(now - mNbWeeks*7*86400,now,mNbWeeks);
|
||||
mLastUsedHist = Histogram(now - 3600*mNbHours,now,mNbHours);
|
||||
mTotalIdentities = 0;
|
||||
mUsageMap.clear();
|
||||
mPerServiceUsageMap.clear();
|
||||
|
||||
for(auto& meta:ids)
|
||||
{
|
||||
RsIdentityDetails det;
|
||||
|
||||
if(!rsIdentity->getIdDetails(RsGxsId(meta.mGroupId),det))
|
||||
continue;
|
||||
|
||||
mPublishDateHist.insert((double)meta.mPublishTs);
|
||||
mLastUsedHist.insert((double)det.mLastUsageTS);
|
||||
|
||||
for(auto it:det.mUseCases)
|
||||
{
|
||||
auto it2 = mUsageMap.find(it.first.mUsageCode);
|
||||
if(it2 == mUsageMap.end())
|
||||
mUsageMap[it.first.mUsageCode] = 0 ;
|
||||
|
||||
++mUsageMap[it.first.mUsageCode];
|
||||
|
||||
uint32_t s = static_cast<uint32_t>(it.first.mServiceId);
|
||||
auto it3 = mPerServiceUsageMap.find(s);
|
||||
if(it3 == mPerServiceUsageMap.end())
|
||||
mPerServiceUsageMap[s] = 0;
|
||||
|
||||
++mPerServiceUsageMap[s];
|
||||
}
|
||||
|
||||
++mTotalIdentities;
|
||||
}
|
||||
|
||||
delete pids;
|
||||
|
||||
}, this );
|
||||
});
|
||||
}
|
||||
|
||||
void GxsIdStatisticsWidget::updateContent()
|
||||
{
|
||||
// Now draw the info int the widget's pixmap
|
||||
|
||||
float size = QFontMetricsF(font()).height() ;
|
||||
float fact = size/14.0 ;
|
||||
|
||||
QPixmap tmppixmap(mMaxWidth, mMaxHeight);
|
||||
tmppixmap.fill(Qt::transparent);
|
||||
setFixedHeight(mMaxHeight);
|
||||
|
||||
QPainter painter(&tmppixmap);
|
||||
painter.initFrom(this);
|
||||
painter.setPen(QColor::fromRgb(0,0,0)) ;
|
||||
|
||||
QFont times_f(font());//"Times") ;
|
||||
QFont monospace_f("Monospace") ;
|
||||
monospace_f.setStyleHint(QFont::TypeWriter) ;
|
||||
monospace_f.setPointSize(font().pointSize()) ;
|
||||
|
||||
QFontMetricsF fm_monospace(monospace_f) ;
|
||||
QFontMetricsF fm_times(times_f) ;
|
||||
|
||||
int cellx = fm_monospace.width(QString(" ")) ;
|
||||
int celly = fm_monospace.height() ;
|
||||
|
||||
// Display general statistics
|
||||
|
||||
int ox=5*fact,oy=15*fact ;
|
||||
|
||||
painter.setFont(times_f) ;
|
||||
painter.drawText(ox,oy,tr("Total identities: ")+QString::number(mTotalIdentities)) ; oy += celly*2 ;
|
||||
|
||||
uint32_t total_per_type = 0;
|
||||
for(auto it:mUsageMap)
|
||||
total_per_type += it.second;
|
||||
|
||||
painter.setFont(times_f) ;
|
||||
painter.drawText(ox,oy,tr("Usage types") + "(" + QString::number(total_per_type) + " hits): ") ; oy += 2*celly;
|
||||
|
||||
for(auto it:mUsageMap)
|
||||
{
|
||||
painter.drawText(ox+2*cellx,oy, getUsageStatisticsName(it.first) + ": " + QString::number(it.second)) ;
|
||||
oy += celly ;
|
||||
}
|
||||
oy += celly ;
|
||||
|
||||
// Display per-service statistics
|
||||
|
||||
uint32_t total_per_service = 0;
|
||||
for(auto it:mPerServiceUsageMap)
|
||||
total_per_service += it.second;
|
||||
|
||||
painter.setFont(times_f) ;
|
||||
painter.drawText(ox,oy,tr("Usage per service") + "(" + QString::number(total_per_service) + " hits): ") ; oy += 2*celly;
|
||||
|
||||
for(auto it:mPerServiceUsageMap)
|
||||
{
|
||||
painter.drawText(ox+2*cellx,oy, getServiceName(it.first) + ": " + QString::number(it.second)) ;
|
||||
oy += celly ;
|
||||
}
|
||||
oy += celly ;
|
||||
|
||||
// Draw the creation time histogram
|
||||
|
||||
painter.setFont(times_f) ;
|
||||
painter.drawText(ox,oy,tr("Identity age (in weeks):")) ; oy += celly ;
|
||||
|
||||
uint32_t hist_height = 10;
|
||||
oy += hist_height*celly;
|
||||
|
||||
painter.drawLine(QPoint(ox+4*cellx,oy),QPoint(ox+4*cellx+cellx*mNbWeeks*2,oy));
|
||||
painter.drawLine(QPoint(ox+4*cellx,oy),QPoint(ox+4*cellx,oy-celly*hist_height));
|
||||
|
||||
uint32_t max_entry=0;
|
||||
for(int i=0;i<mPublishDateHist.entries().size();++i)
|
||||
max_entry = std::max(max_entry,mPublishDateHist.entries()[i]);
|
||||
|
||||
for(int i=0;i<mPublishDateHist.entries().size();++i)
|
||||
{
|
||||
float h = floor(celly*mPublishDateHist.entries()[i]/(float)max_entry*hist_height);
|
||||
int I = mPublishDateHist.entries().size() - 1 - i;
|
||||
|
||||
painter.fillRect(ox+4*cellx+I*2*cellx+cellx, oy-h, cellx, h,QColor::fromRgbF(0.9,0.6,0.2));
|
||||
painter.setPen(QColor::fromRgb(0,0,0));
|
||||
painter.drawRect(ox+4*cellx+I*2*cellx+cellx, oy-h, cellx, h);
|
||||
}
|
||||
for(int i=0;i<mPublishDateHist.entries().size();++i)
|
||||
{
|
||||
QString txt = QString::number(i);
|
||||
painter.drawText(ox+4*cellx+i*2*cellx+cellx*1.5 - 0.5*fm_times.width(txt),oy+celly,txt);
|
||||
}
|
||||
|
||||
for(int i=0;i<5;++i)
|
||||
{
|
||||
QString txt = QString::number((int)rint(max_entry*i/5.0));
|
||||
painter.drawText(ox + 4*cellx - cellx - fm_times.width(txt),oy - i*hist_height/5.0 * celly,txt );
|
||||
}
|
||||
|
||||
oy += 2*celly;
|
||||
oy += celly;
|
||||
|
||||
// Last used histogram
|
||||
|
||||
painter.setFont(times_f) ;
|
||||
painter.drawText(ox,oy,tr("Last used (hours ago): ")) ; oy += celly ;
|
||||
|
||||
oy += hist_height*celly;
|
||||
|
||||
painter.drawLine(QPoint(ox+4*cellx,oy),QPoint(ox+4*cellx+cellx*mNbHours*2,oy));
|
||||
painter.drawLine(QPoint(ox+4*cellx,oy),QPoint(ox+4*cellx,oy-celly*hist_height));
|
||||
|
||||
max_entry=0;
|
||||
for(int i=0;i<mLastUsedHist.entries().size();++i)
|
||||
max_entry = std::max(max_entry,mLastUsedHist.entries()[i]);
|
||||
|
||||
for(int i=0;i<mLastUsedHist.entries().size();++i)
|
||||
{
|
||||
float h = floor(celly*mLastUsedHist.entries()[i]/(float)max_entry*hist_height);
|
||||
int I = mLastUsedHist.entries().size() - 1 - i;
|
||||
|
||||
painter.fillRect(ox+4*cellx+I*2*cellx+cellx, oy-h, cellx, h,QColor::fromRgbF(0.6,0.9,0.4));
|
||||
painter.setPen(QColor::fromRgb(0,0,0));
|
||||
painter.drawRect(ox+4*cellx+I*2*cellx+cellx, oy-h, cellx, h);
|
||||
}
|
||||
for(int i=0;i<mLastUsedHist.entries().size();++i)
|
||||
{
|
||||
QString txt = QString::number(i);
|
||||
painter.drawText(ox+4*cellx+i*2*cellx+cellx*1.5 - 0.5*fm_times.width(txt),oy+celly,txt);
|
||||
}
|
||||
|
||||
for(int i=0;i<5;++i)
|
||||
{
|
||||
QString txt = QString::number((int)rint(max_entry*i/5.0));
|
||||
painter.drawText(ox + 4*cellx - cellx - fm_times.width(txt),oy - i*hist_height/5.0 * celly,txt );
|
||||
}
|
||||
|
||||
oy += 2*celly;
|
||||
|
||||
|
||||
// set the pixmap
|
||||
|
||||
pixmap = tmppixmap;
|
||||
mMaxHeight = oy;
|
||||
}
|
||||
|
||||
|
||||
GxsIdStatisticsWidget::GxsIdStatisticsWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
float size = QFontMetricsF(font()).height() ;
|
||||
float fact = size/14.0 ;
|
||||
|
||||
mNbWeeks = 52;
|
||||
mNbHours = 52;
|
||||
|
||||
mMaxWidth = 400*fact ;
|
||||
mMaxHeight = 0 ;
|
||||
//mCurrentN = PARTIAL_VIEW_SIZE/2+1 ;
|
||||
}
|
||||
|
||||
#ifdef TODO
|
||||
void GxsIdStatisticsWidget::updateContent()
|
||||
{
|
||||
// 1 - get info
|
||||
|
||||
// 2 - draw histograms
|
||||
|
||||
float size = QFontMetricsF(font()).height() ;
|
||||
float fact = size/14.0 ;
|
||||
|
||||
// What do we need to draw?
|
||||
//
|
||||
// Routing matrix
|
||||
// Key [][][][][][][][][][]
|
||||
//
|
||||
// -> each [] shows a square (one per friend node) that is the routing probabilities for all connected friends
|
||||
// computed using the "computeRoutingProbabilitites()" method.
|
||||
//
|
||||
// Own key ids
|
||||
// key service id description
|
||||
//
|
||||
// Data items
|
||||
// Msg id Local origin Destination Time Status
|
||||
//
|
||||
QPixmap tmppixmap(maxWidth, maxHeight);
|
||||
tmppixmap.fill(Qt::transparent);
|
||||
setFixedHeight(maxHeight);
|
||||
|
||||
QPainter painter(&tmppixmap);
|
||||
painter.initFrom(this);
|
||||
painter.setPen(QColor::fromRgb(0,0,0)) ;
|
||||
|
||||
QFont times_f(font());//"Times") ;
|
||||
QFont monospace_f("Monospace") ;
|
||||
monospace_f.setStyleHint(QFont::TypeWriter) ;
|
||||
monospace_f.setPointSize(font().pointSize()) ;
|
||||
|
||||
QFontMetricsF fm_monospace(monospace_f) ;
|
||||
QFontMetricsF fm_times(times_f) ;
|
||||
|
||||
static const int cellx = fm_monospace.width(QString(" ")) ;
|
||||
static const int celly = fm_monospace.height() ;
|
||||
|
||||
maxHeight = 500*fact ;
|
||||
|
||||
// std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl;
|
||||
// draw...
|
||||
int ox=5*fact,oy=5*fact ;
|
||||
|
||||
|
||||
painter.setFont(times_f) ;
|
||||
painter.drawText(ox,oy+celly,tr("Managed keys")+":" + QString::number(matrix_info.published_keys.size())) ; oy += celly*2 ;
|
||||
|
||||
painter.setFont(monospace_f) ;
|
||||
for(std::map<Sha1CheckSum,RsGRouter::GRouterPublishedKeyInfo>::const_iterator it(matrix_info.published_keys.begin());it!=matrix_info.published_keys.end();++it)
|
||||
{
|
||||
QString packet_string ;
|
||||
packet_string += QString::fromStdString(it->second.authentication_key.toStdString()) ;
|
||||
packet_string += tr(" : Service ID =")+" "+QString::number(it->second.service_id,16) ;
|
||||
packet_string += " \""+QString::fromUtf8(it->second.description_string.c_str()) + "\"" ;
|
||||
|
||||
painter.drawText(ox+2*cellx,oy+celly,packet_string ) ; oy += celly ;
|
||||
}
|
||||
oy += celly ;
|
||||
|
||||
|
||||
std::map<QString, std::vector<QString> > tos ;
|
||||
|
||||
// Now draw the matrix
|
||||
|
||||
QString prob_string ;
|
||||
painter.setFont(times_f) ;
|
||||
QString Q = tr("Routing matrix (") ;
|
||||
|
||||
painter.drawText(ox+0*cellx,oy+fm_times.height(),Q) ;
|
||||
|
||||
// draw scale
|
||||
|
||||
for(int i=0;i<100*fact;++i)
|
||||
{
|
||||
painter.setPen(colorScale(i/100.0/fact)) ;
|
||||
painter.drawLine(ox+fm_times.width(Q)+i,oy+fm_times.height()*0.5,ox+fm_times.width(Q)+i,oy+fm_times.height()) ;
|
||||
}
|
||||
painter.setPen(QColor::fromRgb(0,0,0)) ;
|
||||
|
||||
painter.drawText(ox+fm_times.width(Q) + 102*fact,oy+celly,")") ;
|
||||
|
||||
oy += celly ;
|
||||
oy += celly ;
|
||||
|
||||
//static const int MaxKeySize = 20*fact ;
|
||||
painter.setFont(monospace_f) ;
|
||||
|
||||
int n=0;
|
||||
QString ids;
|
||||
std::vector<float> current_probs ;
|
||||
int current_oy = 0 ;
|
||||
|
||||
mMinWheelZoneX = ox+2*cellx ;
|
||||
mMinWheelZoneY = oy ;
|
||||
|
||||
RsGxsId current_id ;
|
||||
float current_width=0 ;
|
||||
|
||||
for(std::map<GRouterKeyId,std::vector<float> >::const_iterator it(matrix_info.per_friend_probabilities.begin());it!=matrix_info.per_friend_probabilities.end();++it,++n)
|
||||
if(n >= mCurrentN-PARTIAL_VIEW_SIZE/2 && n <= mCurrentN+PARTIAL_VIEW_SIZE/2)
|
||||
{
|
||||
ids = QString::fromStdString(it->first.toStdString())+" : " ;
|
||||
painter.drawText(ox+2*cellx,oy+celly,ids) ;
|
||||
|
||||
for(uint32_t i=0;i<matrix_info.friend_ids.size();++i)
|
||||
painter.fillRect(ox+i*cellx+fm_monospace.width(ids),oy+0.15*celly,cellx,celly,colorScale(it->second[i])) ;
|
||||
|
||||
if(n == mCurrentN)
|
||||
{
|
||||
current_probs = it->second ;
|
||||
current_oy = oy ;
|
||||
current_id = it->first ;
|
||||
current_width = ox+matrix_info.friend_ids.size()*cellx+fm_monospace.width(ids);
|
||||
}
|
||||
|
||||
oy += celly ;
|
||||
}
|
||||
mMaxWheelZoneX = ox+matrix_info.friend_ids.size()*cellx + fm_monospace.width(ids);
|
||||
|
||||
RsIdentityDetails iddetails ;
|
||||
if(rsIdentity->getIdDetails(current_id,iddetails))
|
||||
painter.drawText(current_width+cellx, current_oy+celly, QString::fromUtf8(iddetails.mNickname.c_str())) ;
|
||||
else
|
||||
painter.drawText(current_width+cellx, current_oy+celly, tr("[Unknown identity]")) ;
|
||||
|
||||
mMaxWheelZoneY = oy+celly ;
|
||||
|
||||
painter.setPen(QColor::fromRgb(0,0,0)) ;
|
||||
|
||||
painter.setPen(QColor::fromRgb(127,127,127));
|
||||
painter.drawRect(ox+2*cellx,current_oy+0.15*celly,fm_monospace.width(ids)+cellx*matrix_info.friend_ids.size()- 2*cellx,celly) ;
|
||||
|
||||
float total_length = (matrix_info.friend_ids.size()+2)*cellx ;
|
||||
|
||||
if(!current_probs.empty())
|
||||
for(uint32_t i=0;i<matrix_info.friend_ids.size();++i)
|
||||
{
|
||||
float x1 = ox+(i+0.5)*cellx+fm_monospace.width(ids) ;
|
||||
float y1 = oy+0.15*celly ;
|
||||
float y2 = y1+(matrix_info.friend_ids.size()-1-i+1)*celly;
|
||||
|
||||
RsPeerDetails peer_ssl_details;
|
||||
rsPeers->getPeerDetails(matrix_info.friend_ids[i], peer_ssl_details);
|
||||
|
||||
painter.drawLine(x1,y1,x1,y2);
|
||||
painter.drawLine(x1,y2,x1 + total_length - i*cellx,y2) ;
|
||||
painter.drawText(cellx+ x1 + total_length - i*cellx,y2+(0.35)*celly, QString::fromUtf8(peer_ssl_details.name.c_str()) + " - " + QString::fromUtf8(peer_ssl_details.location.c_str()) + " ("+QString::number(current_probs[i])+")");
|
||||
}
|
||||
oy += celly * (2+matrix_info.friend_ids.size());
|
||||
|
||||
oy += celly ;
|
||||
oy += celly ;
|
||||
|
||||
// update the pixmap
|
||||
//
|
||||
pixmap = tmppixmap;
|
||||
maxHeight = oy ;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GxsIdStatisticsWidget::paintEvent(QPaintEvent */*event*/)
|
||||
{
|
||||
QStylePainter(this).drawPixmap(0, 0, pixmap);
|
||||
}
|
||||
|
||||
void GxsIdStatisticsWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QRect rect = geometry();
|
||||
|
||||
mMaxWidth = rect.width();
|
||||
mMaxHeight = rect.height() ;
|
||||
|
||||
QWidget::resizeEvent(event);
|
||||
updateContent();
|
||||
}
|
94
retroshare-gui/src/gui/statistics/GxsIdStatistics.h
Normal file
94
retroshare-gui/src/gui/statistics/GxsIdStatistics.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*******************************************************************************
|
||||
* gui/statistics/GxsIdStatistics.h *
|
||||
* *
|
||||
* Copyright (c) 2011 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPoint>
|
||||
#include <retroshare/rsidentity.h>
|
||||
#include <retroshare/rstypes.h>
|
||||
|
||||
#include "RsAutoUpdatePage.h"
|
||||
#include "Histogram.h"
|
||||
#include "ui_GxsIdStatistics.h"
|
||||
|
||||
// In this statistics panel we show:
|
||||
//
|
||||
// - histograms
|
||||
// * age histogram of GXS ids (creation time)
|
||||
// * last usage histogram
|
||||
// * number of IDs used in each service as reported by UsageStatistics
|
||||
//
|
||||
// (note: we could use that histogram class for packets statistics, so we made a separate class)
|
||||
//
|
||||
// And general statistics:
|
||||
//
|
||||
// - total number of IDs
|
||||
// - total number of signed IDs
|
||||
// - total number of own IDs
|
||||
//
|
||||
class GxsIdStatisticsWidget ;
|
||||
|
||||
class GxsIdStatistics: public RsAutoUpdatePage, public Ui::GxsIdStatistics
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GxsIdStatistics(QWidget *parent = NULL) ;
|
||||
~GxsIdStatistics();
|
||||
|
||||
void updateContent() ;
|
||||
|
||||
private:
|
||||
|
||||
void processSettings(bool bLoad);
|
||||
bool m_bProcessSettings;
|
||||
|
||||
virtual void updateDisplay() ;
|
||||
|
||||
GxsIdStatisticsWidget *_tst_CW ;
|
||||
} ;
|
||||
|
||||
class GxsIdStatisticsWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GxsIdStatisticsWidget(QWidget *parent = NULL) ;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *event) ;
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
|
||||
void updateContent() ;
|
||||
void updateData();
|
||||
private:
|
||||
static QString speedString(float f) ;
|
||||
|
||||
QPixmap pixmap ;
|
||||
int mMaxWidth,mMaxHeight ;
|
||||
uint32_t mNbWeeks;
|
||||
uint32_t mNbHours;
|
||||
uint32_t mTotalIdentities;
|
||||
Histogram mPublishDateHist ;
|
||||
Histogram mLastUsedHist ;
|
||||
|
||||
std::map<RsIdentityUsage::UsageCode,int> mUsageMap;
|
||||
std::map<uint32_t,int> mPerServiceUsageMap;
|
||||
};
|
||||
|
49
retroshare-gui/src/gui/statistics/GxsIdStatistics.ui
Normal file
49
retroshare-gui/src/gui/statistics/GxsIdStatistics.ui
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GxsIdStatistics</class>
|
||||
<widget class="QWidget" name="GxsIdStatistics">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1468</width>
|
||||
<height>659</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Router Statistics</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QScrollArea" name="_stats_F">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1450</width>
|
||||
<height>641</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
55
retroshare-gui/src/gui/statistics/Histogram.cpp
Normal file
55
retroshare-gui/src/gui/statistics/Histogram.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*******************************************************************************
|
||||
* gui/statistics/Histogram.cpp *
|
||||
* *
|
||||
* Copyright (c) 2020 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "Histogram.h"
|
||||
|
||||
Histogram::Histogram()
|
||||
: mStart(0),mEnd(1.0),mBins(10,0)
|
||||
{}
|
||||
|
||||
Histogram::Histogram(double start, double end, int bins)
|
||||
: mStart(start),mEnd(end),mBins(bins,0)
|
||||
{
|
||||
if(mEnd <= mStart)
|
||||
std::cerr << "Null histogram created! Please check your parameters" << std::endl;
|
||||
}
|
||||
|
||||
void Histogram::draw(QPainter *painter) const
|
||||
{
|
||||
}
|
||||
|
||||
void Histogram::insert(double val)
|
||||
{
|
||||
long int bin = (uint32_t)floor((val - mStart)/(mEnd - mStart) * mBins.size());
|
||||
|
||||
if(bin >= 0 && bin < mBins.size())
|
||||
++mBins[bin];
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o,const Histogram& h)
|
||||
{
|
||||
o << "Histogram: [" << h.mStart << "..." << h.mEnd << "] " << h.mBins.size() << " bins." << std::endl;
|
||||
for(uint32_t i=0;i<h.mBins.size();++i)
|
||||
o << " " << h.mStart + i*(double)(h.mEnd - h.mStart)/(double)h.mBins.size() << " : " << h.mBins[i] << std::endl;
|
||||
|
||||
return o;
|
||||
}
|
45
retroshare-gui/src/gui/statistics/Histogram.h
Normal file
45
retroshare-gui/src/gui/statistics/Histogram.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* gui/statistics/Histogram.h *
|
||||
* *
|
||||
* Copyright (c) 2020 Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
class QPainter;
|
||||
|
||||
class Histogram
|
||||
{
|
||||
public:
|
||||
Histogram();
|
||||
Histogram(double start, double end, int bins);
|
||||
|
||||
void draw(QPainter *painter) const ;
|
||||
void insert(double val);
|
||||
|
||||
const std::vector<uint32_t>& entries() const { return mBins; }
|
||||
|
||||
private:
|
||||
double mStart;
|
||||
double mEnd;
|
||||
|
||||
std::vector<uint32_t> mBins;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& o,const Histogram& h);
|
||||
};
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include <gui/statistics/TurtleRouterStatistics.h>
|
||||
#include <gui/statistics/GlobalRouterStatistics.h>
|
||||
#include <gui/statistics/GxsIdStatistics.h>
|
||||
#include <gui/statistics/GxsTransportStatistics.h>
|
||||
#include <gui/statistics/BwCtrlWindow.h>
|
||||
#include <gui/statistics/DhtWindow.h>
|
||||
@ -52,6 +53,7 @@
|
||||
|
||||
#define IMAGE_DHT ":/icons/DHT128.png"
|
||||
#define IMAGE_TURTLE ":/icons/turtle128.png"
|
||||
#define IMAGE_IDENTITIES ":/icons/avatar_128.png"
|
||||
#define IMAGE_BWGRAPH ":/icons/bandwidth128.png"
|
||||
#define IMAGE_GLOBALROUTER ":/icons/GRouter128.png"
|
||||
#define IMAGE_GXSTRANSPORT ":/icons/transport128.png"
|
||||
@ -143,6 +145,9 @@ void StatisticsWindow::initStackedPage()
|
||||
ui->stackPages->add(trsdlg = new TurtleRouterStatistics(ui->stackPages),
|
||||
action = createPageAction(QIcon(IMAGE_TURTLE), tr("Turtle Router"), grp));
|
||||
|
||||
ui->stackPages->add(gxsiddlg = new GxsIdStatistics(ui->stackPages),
|
||||
action = createPageAction(QIcon(IMAGE_IDENTITIES), tr("Identities"), grp));
|
||||
|
||||
ui->stackPages->add(grsdlg = new GlobalRouterStatistics(ui->stackPages),
|
||||
action = createPageAction(QIcon(IMAGE_GLOBALROUTER), tr("Global Router"), grp));
|
||||
|
||||
@ -150,7 +155,7 @@ void StatisticsWindow::initStackedPage()
|
||||
action = createPageAction(QIcon(IMAGE_GXSTRANSPORT), tr("Gxs Transport"), grp));
|
||||
|
||||
ui->stackPages->add(rttdlg = new RttStatistics(ui->stackPages),
|
||||
action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp));
|
||||
action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp));
|
||||
|
||||
bool showdht = true;
|
||||
RsPeerDetails detail;
|
||||
|
@ -38,6 +38,7 @@ class TurtleRouterStatistics;
|
||||
class GlobalRouterStatistics;
|
||||
class GxsTransportStatistics;
|
||||
class RttStatistics;
|
||||
class GxsIdStatistics;
|
||||
|
||||
class StatisticsWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
@ -57,6 +58,7 @@ public:
|
||||
BwCtrlWindow *bwdlg;
|
||||
TurtleRouterStatistics *trsdlg;
|
||||
RttStatistics *rttdlg;
|
||||
GxsIdStatistics *gxsiddlg;
|
||||
|
||||
|
||||
public slots:
|
||||
|
@ -437,7 +437,9 @@ HEADERS += rshare.h \
|
||||
gui/FileTransfer/BannedFilesDialog.h \
|
||||
gui/statistics/TurtleRouterDialog.h \
|
||||
gui/statistics/TurtleRouterStatistics.h \
|
||||
gui/statistics/GxsIdStatistics.h \
|
||||
gui/statistics/dhtgraph.h \
|
||||
gui/statistics/Histogram.h \
|
||||
gui/statistics/BandwidthGraphWindow.h \
|
||||
gui/statistics/turtlegraph.h \
|
||||
gui/statistics/BandwidthStatsWidget.h \
|
||||
@ -755,6 +757,7 @@ FORMS += gui/StartDialog.ui \
|
||||
gui/statistics/DhtWindow.ui \
|
||||
gui/statistics/TurtleRouterDialog.ui \
|
||||
gui/statistics/TurtleRouterStatistics.ui \
|
||||
gui/statistics/GxsIdStatistics.ui \
|
||||
gui/statistics/GlobalRouterStatistics.ui \
|
||||
gui/statistics/GxsTransportStatistics.ui \
|
||||
gui/statistics/StatisticsWindow.ui \
|
||||
@ -995,8 +998,10 @@ SOURCES += main.cpp \
|
||||
gui/statistics/BandwidthGraphWindow.cpp \
|
||||
gui/statistics/BandwidthStatsWidget.cpp \
|
||||
gui/statistics/DhtWindow.cpp \
|
||||
gui/statistics/Histogram.cpp \
|
||||
gui/statistics/TurtleRouterDialog.cpp \
|
||||
gui/statistics/TurtleRouterStatistics.cpp \
|
||||
gui/statistics/GxsIdStatistics.cpp \
|
||||
gui/statistics/GlobalRouterStatistics.cpp \
|
||||
gui/statistics/GxsTransportStatistics.cpp \
|
||||
gui/statistics/StatisticsWindow.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user