From 2d8fd0764b70dcffa5748ecbecc36326c6562088 Mon Sep 17 00:00:00 2001 From: RetroPooh Date: Mon, 5 Jun 2017 14:25:09 +0300 Subject: [PATCH 01/24] stats tunnels rearranged columns for better readablilty --- retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp b/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp index a76b5b5c3..8f35f6d57 100644 --- a/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp +++ b/retroshare-gui/src/gui/statistics/TurtleRouterDialog.cpp @@ -142,7 +142,7 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector [" + QString::fromUtf8(tunnels_info[i][1].c_str()) + "]\t\t " + tr("last transfer") + ": " + QString::fromStdString(tunnels_info[i][4]) + " " + "\t " + tr("Speed") + ": " + QString::fromStdString(tmp) ; + QString str = tr("Tunnel id") + ": " + QString::fromUtf8(tunnels_info[i][0].c_str()) + "\t" + tr("Speed") + ": " + QString::fromStdString(tmp) + "\t " + tr("last transfer") + ": " + QString::fromStdString(tunnels_info[i][4])+ "\t" + QString::fromUtf8(tunnels_info[i][2].c_str()) + " -> " + QString::fromUtf8(tunnels_info[i][1].c_str()); stl.clear() ; stl.push_back(str) ; QTreeWidgetItem *item = new QTreeWidgetItem(stl); From b7c09bd6cf5419e95711876acbeea8b914a19cb5 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 5 Jun 2017 21:15:42 +0200 Subject: [PATCH 02/24] added calls to indicateConfigChanged() to force saving GxsTrans outgoing records when updated --- libretroshare/src/gxstrans/p3gxstrans.cc | 61 +++++++++++++++++------- libretroshare/src/gxstrans/p3gxstrans.h | 2 +- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index 0a67bb879..2e47553aa 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -100,6 +100,8 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId, } mailId = pr.mailItem.mailId; + + IndicateConfigChanged(); // This causes the saving of the message after all data has been filled in. return true; } @@ -228,6 +230,7 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) { RS_STACK_MUTEX(mIngoingMutex); mIngoingQueue.insert(inMap::value_type(mb->mailId, mb)); + IndicateConfigChanged(); } else std::cerr << "p3GxsTrans::handleResponse(...) " @@ -392,11 +395,20 @@ void p3GxsTrans::service_tick() { OutgoingRecord& pr(it->second); GxsTransSendStatus oldStatus = pr.status; - processOutgoingRecord(pr); + + locked_processOutgoingRecord(pr); + bool changed = false ; + if (oldStatus != pr.status) notifyClientService(pr); if( pr.status >= GxsTransSendStatus::RECEIPT_RECEIVED ) + { it = mOutgoingQueue.erase(it); + changed = true ; + } else ++it; + + if(changed) + IndicateConfigChanged(); } } @@ -410,8 +422,8 @@ void p3GxsTrans::service_tick() { case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: { - RsGxsTransMailItem* msg = - dynamic_cast(it->second); + RsGxsTransMailItem* msg = dynamic_cast(it->second); + if(!msg) { std::cerr << "p3GxsTrans::service_tick() (EE) " @@ -436,8 +448,8 @@ void p3GxsTrans::service_tick() } case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: { - RsGxsTransPresignedReceipt* rcpt = - dynamic_cast(it->second); + RsGxsTransPresignedReceipt* rcpt = dynamic_cast(it->second); + if(!rcpt) { std::cerr << "p3GxsTrans::service_tick() (EE) " @@ -468,6 +480,8 @@ void p3GxsTrans::service_tick() } delete it->second; it = mIngoingQueue.erase(it); + + IndicateConfigChanged(); } } } @@ -678,7 +692,7 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId, } } -void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr) +void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) { //std::cout << "p3GxsTrans::processRecord(...)" << std::endl; @@ -807,6 +821,8 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr) uint32_t token; publishMsg(token, new RsGxsTransMailItem(pr.mailItem)); pr.status = GxsTransSendStatus::PENDING_RECEIPT_RECEIVE; + + IndicateConfigChanged(); // This causes the saving of the message after all data has been filled in. break; } //case GxsTransSendStatus::PENDING_TRANSFER: @@ -814,17 +830,24 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr) { RS_STACK_MUTEX(mIngoingMutex); auto range = mIngoingQueue.equal_range(pr.mailItem.mailId); + bool changed = false ; + for( auto it = range.first; it != range.second; ++it) { - RsGxsTransPresignedReceipt* rt = - dynamic_cast(it->second); + RsGxsTransPresignedReceipt* rt = dynamic_cast(it->second); + if(rt && mIdService.isOwnId(rt->meta.mAuthorId)) { mIngoingQueue.erase(it); delete rt; pr.status = GxsTransSendStatus::RECEIPT_RECEIVED; + + changed = true ; break; } } + if(changed) + IndicateConfigChanged(); + // TODO: Resend message if older then treshold break; } @@ -875,19 +898,23 @@ RsSerialiser* p3GxsTrans::setupSerialiser() bool p3GxsTrans::saveList(bool &cleanup, std::list& saveList) { - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " - << mIngoingQueue.size() << " " << mOutgoingQueue.size() - << std::endl; + std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIngoingQueue.size() << " " << mOutgoingQueue.size() << std::endl; mOutgoingMutex.lock(); mIngoingMutex.lock(); - for ( auto& kv : mOutgoingQueue ) saveList.push_back(&kv.second); - for ( auto& kv : mIngoingQueue ) saveList.push_back(kv.second); + for ( auto& kv : mOutgoingQueue ) + { + std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.mailItem.meta.mGroupId << ", TS=" << kv.second.mailItem.meta.mPublishTs << std::endl; + saveList.push_back(&kv.second); + } + for ( auto& kv : mIngoingQueue ) + { + std::cerr << "Saving incoming item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::endl; + saveList.push_back(kv.second); + } - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " - << mIngoingQueue.size() << " " << mOutgoingQueue.size() - << std::endl; + std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIngoingQueue.size() << " " << mOutgoingQueue.size() << std::endl; cleanup = false; return true; @@ -927,6 +954,8 @@ bool p3GxsTrans::loadList(std::list&loadList) RS_STACK_MUTEX(mOutgoingMutex); mOutgoingQueue.insert( prMap::value_type(ot->mailItem.mailId, *ot)); + + std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->mailItem.meta.mGroupId << ", TS=" << ot->mailItem.meta.mPublishTs << std::endl; } delete v; break; diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h index e12b3c303..1f45608e1 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ b/libretroshare/src/gxstrans/p3gxstrans.h @@ -193,7 +193,7 @@ private: typedef std::map prMap; prMap mOutgoingQueue; RsMutex mOutgoingMutex; - void processOutgoingRecord(OutgoingRecord& r); + void locked_processOutgoingRecord(OutgoingRecord& r); /** * @brief Ingoing mail and receipt processing queue. From 1e652d657778d6cb9fcb673c79778a57a87277e2 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 5 Jun 2017 22:27:54 +0200 Subject: [PATCH 03/24] reduced number of calls to indicateConfigChanged(), and renamed mIngoingQueue into mIncomingQueue in GxsTrans --- libretroshare/src/gxstrans/p3gxstrans.cc | 54 +++++++++++++----------- libretroshare/src/gxstrans/p3gxstrans.h | 2 +- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index 2e47553aa..1ea445465 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -30,7 +30,7 @@ p3GxsTrans::~p3GxsTrans() { RS_STACK_MUTEX(mIngoingMutex); - for ( auto& kv : mIngoingQueue ) delete kv.second; + for ( auto& kv : mIncomingQueue) delete kv.second; } } @@ -126,8 +126,9 @@ void p3GxsTrans::registerGxsTransClient( void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) { - std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type - << ")" << std::endl; + std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type << ")" << std::endl; + bool changed = false ; + switch (req_type) { case GROUPS_LIST: @@ -224,13 +225,14 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: { - RsGxsTransBaseItem* mb = - dynamic_cast(*mIt); + RsGxsTransBaseItem* mb = dynamic_cast(*mIt); + if(mb) { RS_STACK_MUTEX(mIngoingMutex); - mIngoingQueue.insert(inMap::value_type(mb->mailId, mb)); - IndicateConfigChanged(); + mIncomingQueue.insert(inMap::value_type(mb->mailId,mb)); + + changed = true ; } else std::cerr << "p3GxsTrans::handleResponse(...) " @@ -256,6 +258,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) << req_type << std::endl; break; } + + if(changed) + IndicateConfigChanged(); } void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq& m) @@ -357,6 +362,7 @@ void p3GxsTrans::service_tick() GxsTokenQueue::checkRequests(); time_t now = time(NULL); + bool changed = false ; if(mLastMsgCleanup + MAX_DELAY_BETWEEN_CLEANUPS < now) { @@ -397,7 +403,6 @@ void p3GxsTrans::service_tick() GxsTransSendStatus oldStatus = pr.status; locked_processOutgoingRecord(pr); - bool changed = false ; if (oldStatus != pr.status) notifyClientService(pr); if( pr.status >= GxsTransSendStatus::RECEIPT_RECEIVED ) @@ -406,19 +411,15 @@ void p3GxsTrans::service_tick() changed = true ; } else ++it; - - if(changed) - IndicateConfigChanged(); } } { RS_STACK_MUTEX(mIngoingMutex); - for( auto it = mIngoingQueue.begin(); it != mIngoingQueue.end(); ) + for( auto it = mIncomingQueue.begin(); it != mIncomingQueue.end(); ) { - switch(static_cast( - it->second->PacketSubType())) + switch(static_cast( it->second->PacketSubType())) { case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: { @@ -479,11 +480,14 @@ void p3GxsTrans::service_tick() break; } - delete it->second; it = mIngoingQueue.erase(it); - - IndicateConfigChanged(); + delete it->second ; + it = mIncomingQueue.erase(it); + changed = true ; } } + + if(changed) + IndicateConfigChanged(); } RsGenExchange::ServiceCreate_Return p3GxsTrans::service_CreateGroup( @@ -829,7 +833,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) case GxsTransSendStatus::PENDING_RECEIPT_RECEIVE: { RS_STACK_MUTEX(mIngoingMutex); - auto range = mIngoingQueue.equal_range(pr.mailItem.mailId); + auto range = mIncomingQueue.equal_range(pr.mailItem.mailId); bool changed = false ; for( auto it = range.first; it != range.second; ++it) @@ -838,7 +842,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) if(rt && mIdService.isOwnId(rt->meta.mAuthorId)) { - mIngoingQueue.erase(it); delete rt; + mIncomingQueue.erase(it); delete rt; pr.status = GxsTransSendStatus::RECEIPT_RECEIVED; changed = true ; @@ -898,7 +902,7 @@ RsSerialiser* p3GxsTrans::setupSerialiser() bool p3GxsTrans::saveList(bool &cleanup, std::list& saveList) { - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIngoingQueue.size() << " " << mOutgoingQueue.size() << std::endl; + std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; mOutgoingMutex.lock(); mIngoingMutex.lock(); @@ -908,13 +912,13 @@ bool p3GxsTrans::saveList(bool &cleanup, std::list& saveList) std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.mailItem.meta.mGroupId << ", TS=" << kv.second.mailItem.meta.mPublishTs << std::endl; saveList.push_back(&kv.second); } - for ( auto& kv : mIngoingQueue ) + for ( auto& kv : mIncomingQueue ) { std::cerr << "Saving incoming item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::endl; saveList.push_back(kv.second); } - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIngoingQueue.size() << " " << mOutgoingQueue.size() << std::endl; + std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; cleanup = false; return true; @@ -929,7 +933,7 @@ void p3GxsTrans::saveDone() bool p3GxsTrans::loadList(std::list&loadList) { std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " - << mIngoingQueue.size() << " " << mOutgoingQueue.size() + << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; for(auto& v : loadList) @@ -942,7 +946,7 @@ bool p3GxsTrans::loadList(std::list&loadList) if(mi) { RS_STACK_MUTEX(mIngoingMutex); - mIngoingQueue.insert(inMap::value_type(mi->mailId, mi)); + mIncomingQueue.insert(inMap::value_type(mi->mailId, mi)); } break; } @@ -971,7 +975,7 @@ bool p3GxsTrans::loadList(std::list&loadList) } std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " - << mIngoingQueue.size() << " " << mOutgoingQueue.size() + << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; return true; diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h index 1f45608e1..d4574ee5b 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ b/libretroshare/src/gxstrans/p3gxstrans.h @@ -205,7 +205,7 @@ private: * for incoming queue. */ typedef std::unordered_multimap inMap; - inMap mIngoingQueue; + inMap mIncomingQueue; RsMutex mIngoingMutex; /// @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type) From f62028b2c161ecbcbf03e121ad5ccd8a912cbac5 Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 6 Jun 2017 00:15:06 +0200 Subject: [PATCH 04/24] moved metadata info to members of OutgoingRecord, so that the un-serialized meta is not lost when saved. Ensured backward compatibility when reloading old items. --- libretroshare/src/gxstrans/p3gxstrans.cc | 71 +++++++++++++++---- libretroshare/src/gxstrans/p3gxstrans.h | 2 +- libretroshare/src/gxstrans/p3gxstransitems.cc | 26 +++++-- libretroshare/src/gxstrans/p3gxstransitems.h | 57 ++++++++++++--- libretroshare/src/retroshare/rsgxstrans.h | 9 +-- 5 files changed, 129 insertions(+), 36 deletions(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index 1ea445465..41a100e4c 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -48,8 +48,8 @@ bool p3GxsTrans::getStatistics(GxsTransStatistics& stats) RsGxsTransOutgoingRecord rec ; rec.status = pr.status ; - rec.send_TS = pr.mailItem.meta.mPublishTs ; - rec.group_id = pr.mailItem.meta.mGroupId ; + rec.send_TS = pr.sent_ts ; + rec.group_id = pr.group_id ; rec.trans_id = pr.mailItem.mailId ; rec.recipient = pr.recipient ; rec.data_size = pr.mailData.size(); @@ -89,8 +89,7 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId, OutgoingRecord pr( recipient, service, data, size ); pr.mailItem.clear(); - pr.mailItem.meta.mAuthorId = own_gxsid; - pr.mailItem.meta.mMsgId.clear(); + pr.author = own_gxsid; //pr.mailItem.meta.mAuthorId = own_gxsid; pr.mailItem.cryptoType = cm; pr.mailItem.mailId = RSRandom::random_u64(); @@ -225,7 +224,7 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: { - RsGxsTransBaseItem* mb = dynamic_cast(*mIt); + RsGxsTransBaseMsgItem* mb = dynamic_cast(*mIt); if(mb) { @@ -706,7 +705,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) { pr.mailItem.saltRecipientHint(pr.recipient); pr.mailItem.saltRecipientHint(RsGxsId::random()); - pr.mailItem.meta.mPublishTs = time(NULL); + pr.sent_ts = time(NULL) ; //pr.mailItem.meta.mPublishTs = time(NULL); } case GxsTransSendStatus::PENDING_PREFERRED_GROUP: { @@ -717,12 +716,16 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) break; } - pr.mailItem.meta.mGroupId = mPreferredGroupId; + pr.group_id = mPreferredGroupId ; //pr.mailItem.meta.mGroupId = mPreferredGroupId; } case GxsTransSendStatus::PENDING_RECEIPT_CREATE: { RsGxsTransPresignedReceipt grcpt; - grcpt.meta = pr.mailItem.meta; + grcpt.meta.mAuthorId = pr.author ; //grcpt.meta = pr.mailItem.meta; + grcpt.meta.mGroupId = pr.group_id ; //grcpt.meta = pr.mailItem.meta; + grcpt.meta.mMsgId.clear() ; + grcpt.meta.mParentId.clear() ; + grcpt.meta.mOrigMsgId.clear() ; grcpt.meta.mPublishTs = time(NULL); grcpt.mailId = pr.mailItem.mailId; uint32_t grsz = RsGxsTransSerializer().size(&grcpt); @@ -735,7 +738,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) *pr.presignedReceipt.metaData = grcpt.meta; pr.presignedReceipt.msg.setBinData(&grsrz[0], grsz); } - case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE: + case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE: // (cyril) This step is never actually used. { switch (RsGenExchange::createMessage(&pr.presignedReceipt)) { @@ -822,11 +825,23 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) << " payload size: " << pr.mailItem.payload.size() << std::endl; + RsGxsTransMailItem *mail_item = new RsGxsTransMailItem(pr.mailItem); + + // pr.mailItem.meta is *not* serialised. So it is important to not rely on what's in it! + + mail_item->meta.mGroupId = pr.group_id ; + mail_item->meta.mAuthorId = pr.author ; + + mail_item->meta.mMsgId.clear(); + mail_item->meta.mParentId.clear(); + mail_item->meta.mOrigMsgId.clear(); + uint32_t token; - publishMsg(token, new RsGxsTransMailItem(pr.mailItem)); + publishMsg(token, mail_item) ; + pr.status = GxsTransSendStatus::PENDING_RECEIPT_RECEIVE; - IndicateConfigChanged(); // This causes the saving of the message after all data has been filled in. + IndicateConfigChanged(); // This causes the saving of the message after pr.status has changed. break; } //case GxsTransSendStatus::PENDING_TRANSFER: @@ -909,7 +924,7 @@ bool p3GxsTrans::saveList(bool &cleanup, std::list& saveList) for ( auto& kv : mOutgoingQueue ) { - std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.mailItem.meta.mGroupId << ", TS=" << kv.second.mailItem.meta.mPublishTs << std::endl; + std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.group_id << ", TS=" << kv.second.sent_ts << std::endl; saveList.push_back(&kv.second); } for ( auto& kv : mIncomingQueue ) @@ -942,7 +957,7 @@ bool p3GxsTrans::loadList(std::list&loadList) case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: { - RsGxsTransBaseItem* mi = dynamic_cast(v); + RsGxsTransBaseMsgItem* mi = dynamic_cast(v); if(mi) { RS_STACK_MUTEX(mIngoingMutex); @@ -950,6 +965,34 @@ bool p3GxsTrans::loadList(std::list&loadList) } break; } + case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: + { + OutgoingRecord_deprecated* dot = dynamic_cast(v); + + if(dot) + { + std::cerr << "(EE) Read a deprecated GxsTrans outgoing item. Converting to new format..." << std::endl; + + OutgoingRecord ot(dot->recipient,dot->clientService,&dot->mailData[0],dot->mailData.size()) ; + + ot.status = dot->status ; + + ot.author.clear(); // These 3 fields cannot be stored in mailItem.meta, which is not serialised, so they are lost. + ot.group_id.clear() ; + ot.sent_ts = 0; + + ot.mailItem = dot->mailItem ; + ot.presignedReceipt = dot->presignedReceipt; + + RS_STACK_MUTEX(mOutgoingMutex); + mOutgoingQueue.insert(prMap::value_type(ot.mailItem.mailId, ot)); + + std::cerr << "Loaded outgoing item (converted), ID " << std::hex << std::setfill('0') << std::setw(16) << ot.mailItem.mailId<< std::dec << ", Group id: " << ot.group_id << ", TS=" << ot.sent_ts << std::endl; + } + delete v; + break; + } + case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: { OutgoingRecord* ot = dynamic_cast(v); @@ -959,7 +1002,7 @@ bool p3GxsTrans::loadList(std::list&loadList) mOutgoingQueue.insert( prMap::value_type(ot->mailItem.mailId, *ot)); - std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->mailItem.meta.mGroupId << ", TS=" << ot->mailItem.meta.mPublishTs << std::endl; + std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->group_id << ", TS=" << ot->sent_ts << std::endl; } delete v; break; diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h index d4574ee5b..fb205409d 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ b/libretroshare/src/gxstrans/p3gxstrans.h @@ -204,7 +204,7 @@ private: * item to not being processed and memleaked multimap is used instead of map * for incoming queue. */ - typedef std::unordered_multimap inMap; + typedef std::unordered_multimap inMap; inMap mIncomingQueue; RsMutex mIngoingMutex; diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc index cab1e2dfb..cebbd9e69 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ b/libretroshare/src/gxstrans/p3gxstransitems.cc @@ -21,10 +21,11 @@ const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); -OutgoingRecord::OutgoingRecord() : - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, - static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) -{ clear();} +OutgoingRecord_deprecated::OutgoingRecord_deprecated() + : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated) ) { clear();} + +OutgoingRecord::OutgoingRecord() + : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) { clear();} OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, const uint8_t* data, uint32_t size ) : @@ -41,8 +42,7 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, RS_REGISTER_ITEM_TYPE(RsGxsTransMailItem) // for mailItem RS_REGISTER_ITEM_TYPE(RsNxsTransPresignedReceipt) // for presignedReceipt -void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) +void OutgoingRecord_deprecated::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) { RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); RS_REGISTER_SERIAL_MEMBER(recipient); @@ -51,3 +51,17 @@ void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t); RS_REGISTER_SERIAL_MEMBER(presignedReceipt); } + +void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) +{ + RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); + RS_REGISTER_SERIAL_MEMBER(recipient); + RS_REGISTER_SERIAL_MEMBER(author); + RS_REGISTER_SERIAL_MEMBER(group_id); + RS_REGISTER_SERIAL_MEMBER(sent_ts); + RS_REGISTER_SERIAL_MEMBER(mailItem); + RS_REGISTER_SERIAL_MEMBER(mailData); + RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t); + RS_REGISTER_SERIAL_MEMBER(presignedReceipt); +} diff --git a/libretroshare/src/gxstrans/p3gxstransitems.h b/libretroshare/src/gxstrans/p3gxstransitems.h index e6c65e504..bfaa98474 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.h +++ b/libretroshare/src/gxstrans/p3gxstransitems.h @@ -36,14 +36,14 @@ public: virtual ~RsNxsTransPresignedReceipt() {} }; -class RsGxsTransBaseItem : public RsGxsMsgItem +class RsGxsTransBaseMsgItem : public RsGxsMsgItem { public: - RsGxsTransBaseItem(GxsTransItemsSubtypes subtype) : + RsGxsTransBaseMsgItem(GxsTransItemsSubtypes subtype) : RsGxsMsgItem( RS_SERVICE_TYPE_GXS_TRANS, static_cast(subtype) ), mailId(0) {} - virtual ~RsGxsTransBaseItem() {} + virtual ~RsGxsTransBaseMsgItem() {} RsGxsTransId mailId; @@ -58,10 +58,10 @@ public: { RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); } }; -class RsGxsTransPresignedReceipt : public RsGxsTransBaseItem +class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem { public: - RsGxsTransPresignedReceipt() : RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {} + RsGxsTransPresignedReceipt() : RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {} virtual ~RsGxsTransPresignedReceipt() {} }; @@ -72,11 +72,11 @@ enum class RsGxsTransEncryptionMode : uint8_t UNDEFINED_ENCRYPTION = 250 }; -class RsGxsTransMailItem : public RsGxsTransBaseItem +class RsGxsTransMailItem : public RsGxsTransBaseMsgItem { public: RsGxsTransMailItem() : - RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL), + RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL), cryptoType(RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION) {} virtual ~RsGxsTransMailItem() {} @@ -139,7 +139,7 @@ public: void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RsGxsTransBaseItem::serial_process(j, ctx); + RsGxsTransBaseMsgItem::serial_process(j, ctx); RS_REGISTER_SERIAL_MEMBER_TYPED(cryptoType, uint8_t); RS_REGISTER_SERIAL_MEMBER(recipientHint); RS_REGISTER_SERIAL_MEMBER(payload); @@ -147,7 +147,7 @@ public: void clear() { - RsGxsTransBaseItem::clear(); + RsGxsTransBaseMsgItem::clear(); cryptoType = RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION; recipientHint.clear(); payload.clear(); @@ -183,6 +183,33 @@ public: class RsGxsTransSerializer; +class OutgoingRecord_deprecated : public RsItem +{ +public: + OutgoingRecord_deprecated( RsGxsId rec, GxsTransSubServices cs, const uint8_t* data, uint32_t size ); + + virtual ~OutgoingRecord_deprecated() {} + + GxsTransSendStatus status; + RsGxsId recipient; + /// Don't use a pointer would be invalid after publish + RsGxsTransMailItem mailItem; + + std::vector mailData; + GxsTransSubServices clientService; + + RsNxsTransPresignedReceipt presignedReceipt; + + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ); + + void clear() {} + +private: + friend class RsGxsTransSerializer; + OutgoingRecord_deprecated(); +}; + class OutgoingRecord : public RsItem { public: @@ -191,12 +218,19 @@ public: virtual ~OutgoingRecord() {} - GxsTransSendStatus status; - RsGxsId recipient; + GxsTransSendStatus status; + RsGxsId recipient; + + RsGxsId author; // These 3 fields cannot be stored in mailItem.meta, which is not serialised. + RsGxsGroupId group_id ; + uint32_t sent_ts ; + /// Don't use a pointer would be invalid after publish RsGxsTransMailItem mailItem; + std::vector mailData; GxsTransSubServices clientService; + RsNxsTransPresignedReceipt presignedReceipt; void serial_process( RsGenericSerializer::SerializeJob j, @@ -225,6 +259,7 @@ public: case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: return new RsGxsTransMailItem(); case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: return new RsGxsTransPresignedReceipt(); case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: return new RsGxsTransGroupItem(); + case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: return new OutgoingRecord_deprecated(); case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: return new OutgoingRecord(); default: return NULL; } diff --git a/libretroshare/src/retroshare/rsgxstrans.h b/libretroshare/src/retroshare/rsgxstrans.h index b5dad5451..b78191d97 100644 --- a/libretroshare/src/retroshare/rsgxstrans.h +++ b/libretroshare/src/retroshare/rsgxstrans.h @@ -16,10 +16,11 @@ enum class GxsTransSubServices : uint16_t /// Values must fit into uint8_t enum class GxsTransItemsSubtypes : uint8_t { - GXS_TRANS_SUBTYPE_MAIL = 0x01, - GXS_TRANS_SUBTYPE_RECEIPT = 0x02, - GXS_TRANS_SUBTYPE_GROUP = 0x03, - OUTGOING_RECORD_ITEM = 0x04 + GXS_TRANS_SUBTYPE_MAIL = 0x01, + GXS_TRANS_SUBTYPE_RECEIPT = 0x02, + GXS_TRANS_SUBTYPE_GROUP = 0x03, + OUTGOING_RECORD_ITEM_deprecated = 0x04, + OUTGOING_RECORD_ITEM = 0x05 }; enum class GxsTransSendStatus : uint8_t From e726bd1061bd819ee51027190fc6e354282f0a6e Mon Sep 17 00:00:00 2001 From: cyril soler Date: Wed, 7 Jun 2017 13:37:38 +0200 Subject: [PATCH 05/24] attempt to fix the crash in DataStore by not calling deleteMsgs directly --- libretroshare/src/gxstrans/p3gxstrans.cc | 11 +++++++++-- libretroshare/src/gxstrans/p3gxstrans.h | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index 41a100e4c..057e0fc64 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -354,8 +354,14 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() RS_STACK_MUTEX(mMtx) ; mMsgToDel = msgsToDel ; + mDone = true; } +bool p3GxsTrans::GxsTransIntegrityCleanupThread::isDone() +{ + RS_STACK_MUTEX(mMtx) ; + return mDone ; +} void p3GxsTrans::service_tick() { GxsTokenQueue::checkRequests(); @@ -381,7 +387,7 @@ void p3GxsTrans::service_tick() // now grab collected messages to delete - if(mCleanupThread != NULL && !mCleanupThread->isRunning()) + if(mCleanupThread != NULL && !mCleanupThread->isDone()) { GxsMsgReq msgToDel ; @@ -390,7 +396,8 @@ void p3GxsTrans::service_tick() if(!msgToDel.empty()) { std::cerr << "p3GxsTrans::service_tick(): deleting messages." << std::endl; - getDataStore()->removeMsgs(msgToDel); + uint32_t token ; + deleteMsgs(token,msgToDel); } } diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h index fb205409d..d068827cd 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ b/libretroshare/src/gxstrans/p3gxstrans.h @@ -159,7 +159,7 @@ private: * Two weeks seems fair ATM. */ static const uint32_t GXS_STORAGE_PERIOD = 0x127500; - static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS = 1203; // every 20 mins. Could be less. + static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS = 1203; // every 20 mins. Could be less. time_t mLastMsgCleanup ; @@ -282,7 +282,7 @@ private: enum CheckState { CheckStart, CheckChecking }; public: - GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService),mMtx("GxsTransIntegrityCheck") {} + GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService),mMtx("GxsTransIntegrityCheck") { mDone=false;} bool isDone(); void run(); @@ -296,6 +296,7 @@ private: RsMutex mMtx ; GxsMsgReq mMsgToDel ; + bool mDone ; }; GxsTransIntegrityCleanupThread *mCleanupThread ; From 23156ab4b1bd122b5257e541fff72e388c796dbc Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 3 Jun 2017 10:30:02 +0200 Subject: [PATCH 06/24] fixed malloc problem when chat avatar is missing --- libretroshare/src/chat/p3chatservice.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libretroshare/src/chat/p3chatservice.cc b/libretroshare/src/chat/p3chatservice.cc index 851b2983d..64c4e9534 100644 --- a/libretroshare/src/chat/p3chatservice.cc +++ b/libretroshare/src/chat/p3chatservice.cc @@ -169,6 +169,12 @@ class p3ChatService::AvatarInfo void toUnsignedChar(unsigned char *& data,uint32_t& size) const { + if(_image_size == 0) + { + size = 0 ; + data = NULL ; + return ; + } data = (unsigned char *)rs_malloc(_image_size) ; size = _image_size ; memcpy(data,_image_data,size*sizeof(unsigned char)) ; From 318ea310f8473c63aeb87791a5636607e2bd8bbb Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 3 Jun 2017 10:30:22 +0200 Subject: [PATCH 07/24] fixed layout of GxsTrans stats --- .../gui/statistics/GxsTransportStatistics.ui | 96 ++++++++++--------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.ui b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.ui index 2fe43f576..78653b5ae 100644 --- a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.ui +++ b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.ui @@ -13,51 +13,8 @@ Router Statistics - - - - - Gxs Transport Groups: - - - - - - Qt::Vertical - - - - - Group ID / Author - - - - - Number of messages / Publish TS - - - - - Total size of messages - - - - - Subscribed - - - - - Popularity - - - - - - - - - + + GroupBox @@ -65,6 +22,12 @@ + + + 0 + 0 + + Qt::CustomContextMenu @@ -114,6 +77,49 @@ + + + + Gxs Transport Groups: + + + + + + Qt::Vertical + + + + + Group ID / Author + + + + + Number of messages / Publish TS + + + + + Total size of messages + + + + + Subscribed + + + + + Popularity + + + + + + + + From 4cb7522feb0ef261d0e053a218cafcccdf2c0bbc Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 7 Jun 2017 21:41:00 +0200 Subject: [PATCH 08/24] added deleted gxs messages to the reject list of GxsNetService to avoid re-downloading them right away --- libretroshare/src/gxs/rsgenexchange.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 5845a2887..32ddaa7e6 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -1752,8 +1752,18 @@ void RsGenExchange::deleteGroup(uint32_t& token, const RsGxsGroupId& grpId) } void RsGenExchange::deleteMsgs(uint32_t& token, const GxsMsgReq& msgs) { + RS_STACK_MUTEX(mGenMtx) ; + token = mDataAccess->generatePublicToken(); mMsgDeletePublish.push_back(MsgDeletePublish(msgs, token)); + + // This code below will suspend any requests of the deleted messages for 24 hrs. This of course only works + // if all friend nodes consistently delete the messages in the mean time. + + if(mNetService != NULL) + for(GxsMsgReq::const_iterator it(msgs.begin());it!=msgs.end();++it) + for(uint32_t i=0;isecond.size();++i) + mNetService->rejectMessage(it->second[i]) ; } void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem) From 7691a8ef2f861e1c82891f96e7ec0e373e239f6c Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 7 Jun 2017 21:41:20 +0200 Subject: [PATCH 09/24] removed debug info --- retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp index 2c0e1af84..46a3943e5 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp @@ -185,8 +185,9 @@ bool GxsChannelPostItem::setGroup(const RsGxsChannelGroup &group, bool doFill) mGroup = group; // if not publisher, hide the edit button. Without the publish key, there's no way to edit a message. - +#ifdef DEBUG_ITEM std::cerr << "Group subscribe flags = " << std::hex << mGroup.mMeta.mSubscribeFlags << std::dec << std::endl; +#endif if(!IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) ui->editButton->hide(); From 9853b53f8b749c07124f94f47e915d6a6a93ad15 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 7 Jun 2017 23:10:24 +0200 Subject: [PATCH 10/24] fixed debug output in GxsNetService --- libretroshare/src/gxs/rsgxsnetservice.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 789a77441..91a915f40 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -268,7 +268,7 @@ static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ; static const RsPeerId peer_to_print = RsPeerId(std::string("")) ; static const RsGxsGroupId group_id_to_print = RsGxsGroupId(std::string("")) ; // use this to allow to this group id only, or "" for all IDs -static const uint32_t service_to_print = 0x215 ; // use this to allow to this service id only, or 0 for all services +static const uint32_t service_to_print = RS_SERVICE_TYPE_GXS_TRANS ; // 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 {}; @@ -447,6 +447,9 @@ void RsGxsNetService::rejectMessage(const RsGxsMessageId& msg_id) { RS_STACK_MUTEX(mNxsMutex) ; +#ifdef NXS_NET_DEBUG_0 + GXSNETDEBUG___ << "adding message " << msg_id << " to rejection list for 24hrs." << std::endl; +#endif mRejectedMessages[msg_id] = time(NULL) ; } void RsGxsNetService::cleanRejectedMessages() @@ -595,9 +598,9 @@ void RsGxsNetService::syncWithPeers() #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_PG(peerId,grpId) << " peer can send messages for group " << grpId ; if(!encrypt_to_this_circle_id.isNull()) - std::cerr << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl; + GXSNETDEBUG_PG(peerId,grpId) << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl; else - std::cerr << " request should be sent in clear." << std::endl; + GXSNETDEBUG_PG(peerId,grpId) << " request should be sent in clear." << std::endl; #endif // On default, the info has never been received so the TS is 0, meaning the peer has sent that it had no information. @@ -1839,7 +1842,7 @@ void RsGxsNetService::debugDump() GXSNETDEBUG_PG(it->first,it2->first) << " group " << it2->first << " - last updated at peer (secs ago): " << nice_time_stamp(time(NULL),it2->second.time_stamp) << ". Message count=" << it2->second.message_count << std::endl; } - GXSNETDEBUG___<< " List of rejected message ids: " << mRejectedMessages.size() << std::endl; + GXSNETDEBUG___<< " List of rejected message ids: " << std::dec << mRejectedMessages.size() << std::endl; #endif } From 1766087f7124d571cd5dc1d2dfa692051e5551af Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 7 Jun 2017 23:10:59 +0200 Subject: [PATCH 11/24] fixed update notification and display in GxsTransStatistics --- libretroshare/src/gxstrans/p3gxstrans.cc | 3 ++- .../gui/statistics/GxsTransportStatistics.cpp | 20 +++++++++---------- .../gui/statistics/GxsTransportStatistics.h | 6 +++--- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index 057e0fc64..3fde5beb7 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -387,7 +387,7 @@ void p3GxsTrans::service_tick() // now grab collected messages to delete - if(mCleanupThread != NULL && !mCleanupThread->isDone()) + if(mCleanupThread != NULL && mCleanupThread->isDone()) { GxsMsgReq msgToDel ; @@ -543,6 +543,7 @@ void p3GxsTrans::notifyChanges(std::vector& changes) } } } + RsGxsIfaceHelper::receiveChanges(changes); } uint32_t p3GxsTrans::AuthenPolicy() diff --git a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp index 39c6b1c84..7233b6981 100644 --- a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp +++ b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp @@ -73,7 +73,7 @@ static const int GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ = 30 ; // never req #define DEBUG_GXSTRANS_STATS 1 GxsTransportStatistics::GxsTransportStatistics(QWidget *parent) - : RsAutoUpdatePage(2000,parent) + : RsGxsUpdateBroadcastPage(rsGxsTrans,parent) { setupUi(this) ; @@ -93,6 +93,7 @@ GxsTransportStatistics::GxsTransportStatistics(QWidget *parent) // load settings processSettings(true); + updateDisplay(true); } GxsTransportStatistics::~GxsTransportStatistics() @@ -139,19 +140,14 @@ void GxsTransportStatistics::CustomPopupMenu( QPoint ) contextMnu.exec(QCursor::pos()); } -void GxsTransportStatistics::updateDisplay() +void GxsTransportStatistics::updateDisplay(bool) { - time_t now = time(NULL) ; + time_t now = time(NULL) ; - if(mLastGroupReqTS + GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ < now) - { - requestGroupMeta(); - mLastGroupReqTS = now ; - } + std::cerr << "GxsTransportStatistics::updateDisplay()" << std::endl; - //_tst_CW->updateContent() ; - - updateContent(); + requestGroupMeta(); + mLastGroupReqTS = now ; } QString GxsTransportStatistics::getPeerName(const RsPeerId &peer_id) @@ -319,6 +315,8 @@ void GxsTransportStatistics::loadRequest(const TokenQueue *queue, const TokenReq std::cerr << std::endl; break; } + + updateContent(); } void GxsTransportStatistics::requestGroupMeta() diff --git a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.h b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.h index 576aadd26..c57d63c11 100644 --- a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.h +++ b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.h @@ -30,6 +30,7 @@ #include "util/TokenQueue.h" #include "RsAutoUpdatePage.h" #include "ui_GxsTransportStatistics.h" +#include "gui/gxs/RsGxsUpdateBroadcastPage.h" class GxsTransportStatisticsWidget ; class UIStateHelper; @@ -45,7 +46,7 @@ public: std::vector messages_metas ; }; -class GxsTransportStatistics: public RsAutoUpdatePage, public TokenResponse, public Ui::GxsTransportStatistics +class GxsTransportStatistics: public RsGxsUpdateBroadcastPage, public TokenResponse, public Ui::GxsTransportStatistics { Q_OBJECT @@ -66,6 +67,7 @@ private slots: void personDetails(); private: + void updateDisplay(bool complete) ; void loadGroupMeta(const uint32_t& token); void loadGroupStat(const uint32_t& token); void loadMsgMeta(const uint32_t& token); @@ -77,8 +79,6 @@ private: void processSettings(bool bLoad); bool m_bProcessSettings; - virtual void updateDisplay() ; - GxsTransportStatisticsWidget *_tst_CW ; TokenQueue *mTransQueue ; UIStateHelper *mStateHelper; From aa64c4d3c5d401e42e5bd1742cfbf412ba8e168f Mon Sep 17 00:00:00 2001 From: Phenom Date: Tue, 30 May 2017 22:23:31 +0200 Subject: [PATCH 12/24] Add Circle Feed Item. --- libretroshare/src/retroshare/rsgxscircles.h | 1 + libretroshare/src/retroshare/rsnotify.h | 10 +- libretroshare/src/rsitems/rsgxscircleitems.cc | 5 +- libretroshare/src/rsitems/rsgxscircleitems.h | 2 +- libretroshare/src/services/p3gxscircles.cc | 136 +++++--- libretroshare/src/services/p3gxscircles.h | 1 + retroshare-gui/src/gui/NewsFeed.cpp | 324 +++++++++++++++--- retroshare-gui/src/gui/NewsFeed.h | 11 +- .../src/gui/feeds/GxsCircleItem.cpp | 284 +++++++++++++++ retroshare-gui/src/gui/feeds/GxsCircleItem.h | 98 ++++++ retroshare-gui/src/gui/feeds/GxsCircleItem.ui | 298 ++++++++++++++++ .../src/gui/settings/NotifyPage.cpp | 4 + retroshare-gui/src/gui/settings/NotifyPage.ui | 7 + retroshare-gui/src/retroshare-gui.pro | 5 +- 14 files changed, 1094 insertions(+), 92 deletions(-) create mode 100644 retroshare-gui/src/gui/feeds/GxsCircleItem.cpp create mode 100644 retroshare-gui/src/gui/feeds/GxsCircleItem.h create mode 100644 retroshare-gui/src/gui/feeds/GxsCircleItem.ui diff --git a/libretroshare/src/retroshare/rsgxscircles.h b/libretroshare/src/retroshare/rsgxscircles.h index a760c008e..8ce446200 100644 --- a/libretroshare/src/retroshare/rsgxscircles.h +++ b/libretroshare/src/retroshare/rsgxscircles.h @@ -142,6 +142,7 @@ public: /* standard load */ virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; + virtual bool getMsgData(const uint32_t &token, std::vector &msgs) = 0; /* make new group */ virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group) = 0; diff --git a/libretroshare/src/retroshare/rsnotify.h b/libretroshare/src/retroshare/rsnotify.h index 8a2dfff8b..d5a208379 100644 --- a/libretroshare/src/retroshare/rsnotify.h +++ b/libretroshare/src/retroshare/rsnotify.h @@ -77,6 +77,7 @@ const uint32_t RS_FEED_TYPE_FILES = 0x0400; const uint32_t RS_FEED_TYPE_SECURITY = 0x0800; const uint32_t RS_FEED_TYPE_POSTED = 0x1000; const uint32_t RS_FEED_TYPE_SECURITY_IP = 0x2000; +const uint32_t RS_FEED_TYPE_CIRCLE = 0x4000; const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001; const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002; @@ -114,9 +115,12 @@ const uint32_t RS_FEED_ITEM_POSTED_NEW = RS_FEED_TYPE_POSTED | 0x0001; //const uint32_t RS_FEED_ITEM_POSTED_UPDATE = RS_FEED_TYPE_POSTED | 0x0002; const uint32_t RS_FEED_ITEM_POSTED_MSG = RS_FEED_TYPE_POSTED | 0x0003; -const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001; -const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001; -const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001; +const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001; +const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001; +const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001; + +const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REQ = RS_FEED_TYPE_CIRCLE | 0x0001; +const uint32_t RS_FEED_ITEM_CIRCLE_INVIT_REC = RS_FEED_TYPE_CIRCLE | 0x0002; const uint32_t RS_MESSAGE_CONNECT_ATTEMPT = 0x0001; diff --git a/libretroshare/src/rsitems/rsgxscircleitems.cc b/libretroshare/src/rsitems/rsgxscircleitems.cc index 40ae6cf5f..a468f483f 100644 --- a/libretroshare/src/rsitems/rsgxscircleitems.cc +++ b/libretroshare/src/rsitems/rsgxscircleitems.cc @@ -55,7 +55,8 @@ void RsGxsCircleSubscriptionRequestItem::clear() void RsGxsCircleMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,msg.stuff,"msg.stuff") ; + //RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"mMsg.stuff") ;//Should be this but not retrocompatible... + RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"msg.stuff") ; } void RsGxsCircleSubscriptionRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) @@ -74,7 +75,7 @@ void RsGxsCircleGroupItem::serial_process(RsGenericSerializer::SerializeJob j,Rs void RsGxsCircleMsgItem::clear() { - msg.stuff.clear(); + mMsg.stuff.clear(); } void RsGxsCircleGroupItem::clear() diff --git a/libretroshare/src/rsitems/rsgxscircleitems.h b/libretroshare/src/rsitems/rsgxscircleitems.h index 5734b34cd..8e57b478c 100644 --- a/libretroshare/src/rsitems/rsgxscircleitems.h +++ b/libretroshare/src/rsitems/rsgxscircleitems.h @@ -78,7 +78,7 @@ public: virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - RsGxsCircleMsg msg; + RsGxsCircleMsg mMsg; }; class RsGxsCircleSubscriptionRequestItem: public RsGxsMsgItem diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc index 0daa3d24e..2e2796747 100644 --- a/libretroshare/src/services/p3gxscircles.cc +++ b/libretroshare/src/services/p3gxscircles.cc @@ -35,6 +35,7 @@ #include "pgp/pgpauxutils.h" #include "retroshare/rsgxscircles.h" #include "retroshare/rspeers.h" +#include "rsserver/p3face.h" #include #include @@ -194,30 +195,38 @@ void p3GxsCircles::service_tick() void p3GxsCircles::notifyChanges(std::vector &changes) { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges()"; - std::cerr << std::endl; + std::cerr << "p3GxsCircles::notifyChanges()"; + std::cerr << std::endl; #endif - std::vector::iterator it; - for(it = changes.begin(); it != changes.end(); ++it) - { - RsGxsGroupChange *groupChange = dynamic_cast(*it); - RsGxsMsgChange *msgChange = dynamic_cast(*it); + p3Notify *notify = RsServer::notify(); + std::vector::iterator it; + for(it = changes.begin(); it != changes.end(); ++it) + { + RsGxsGroupChange *groupChange = dynamic_cast(*it); + RsGxsMsgChange *msgChange = dynamic_cast(*it); + RsGxsNotify *c = *it; - if (msgChange && !msgChange->metaChange()) - { + if (msgChange && !msgChange->metaChange()) + { #ifdef DEBUG_CIRCLES - std::cerr << " Found circle Message Change Notification" << std::endl; + std::cerr << " Found circle Message Change Notification" << std::endl; #endif - for(std::map >::iterator mit = msgChange->msgChangeMap.begin(); mit != msgChange->msgChangeMap.end(); ++mit) - { + for(std::map >::iterator mit = msgChange->msgChangeMap.begin(); mit != msgChange->msgChangeMap.end(); ++mit) + { #ifdef DEBUG_CIRCLES - std::cerr << " Msgs for Group: " << mit->first << std::endl; + std::cerr << " Msgs for Group: " << mit->first << std::endl; #endif - for(std::map >::const_iterator it2(msgChange->msgChangeMap.begin());it2!=msgChange->msgChangeMap.end();++it2) - force_cache_reload(RsGxsCircleId(it2->first)) ; - } - } + force_cache_reload(RsGxsCircleId(mit->first)); + if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVE) ) + for (std::vector::const_iterator msgIdIt(mit->second.begin()), end(mit->second.end()); msgIdIt != end; ++msgIdIt) + { + const RsGxsMessageId& msgId = *msgIdIt; + notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_MEMB_REQ,RsGxsCircleId(mit->first).toStdString(),msgId.toStdString()); + } + + } + } /* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */ if (groupChange && !groupChange->metaChange()) @@ -245,16 +254,19 @@ void p3GxsCircles::notifyChanges(std::vector &changes) } } - if(groupChange) - for(std::list::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git) - { + if(groupChange) + for(std::list::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git) + { #ifdef DEBUG_CIRCLES - std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl; + std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl; #endif - force_cache_reload(RsGxsCircleId(*git)) ; - } - } - RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements + force_cache_reload(RsGxsCircleId(*git)) ; + if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVE) ) + notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_INVIT_REC,RsGxsCircleId(*git).toStdString(),""); + } + + } + RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements } /********************************************************************************/ @@ -496,6 +508,62 @@ bool p3GxsCircles::getGroupData(const uint32_t &token, std::vector &msgs) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); ++mit) + { + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); ++vit) + { + RsGxsCircleMsgItem* item = dynamic_cast(*vit); + RsGxsCircleSubscriptionRequestItem* rsItem = dynamic_cast(*vit); + if(item) + { + RsGxsCircleMsg msg = item->mMsg; + msg.mMeta = item->meta; + msgs.push_back(msg); + delete item; + } + else if (rsItem) + { + RsGxsCircleMsg msg ;//= rsItem->mMsg; + msg.mMeta = rsItem->meta; + switch (rsItem->subscription_type) + { + case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNKNOWN: + msg.stuff.clear(); + break; + case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE: + msg.stuff="SUBSCRIPTION_REQUEST_SUBSCRIBE"; + break; + case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE: + msg.stuff="SUBSCRIPTION_REQUEST_UNSUBSCRIBE"; + break; + } + msgs.push_back(msg); + delete rsItem; + } + else + { + std::cerr << "Not a GxsCircleMsgItem, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + void p3GxsCircles::createGroup(uint32_t& token, RsGxsCircleGroup &group) { #ifdef DEBUG_CIRCLES @@ -2065,21 +2133,3 @@ bool p3GxsCircles::processMembershipRequests(uint32_t token) return true ; } - - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/services/p3gxscircles.h b/libretroshare/src/services/p3gxscircles.h index 06ddad407..4e011eea0 100644 --- a/libretroshare/src/services/p3gxscircles.h +++ b/libretroshare/src/services/p3gxscircles.h @@ -199,6 +199,7 @@ virtual RsServiceInfo getServiceInfo(); virtual bool getGroupData(const uint32_t &token, std::vector &groups); + virtual bool getMsgData(const uint32_t &token, std::vector &msgs); virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group); virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group); diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index 4b08caec9..6051510a5 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -25,45 +25,43 @@ #include "NewsFeed.h" #include "ui_NewsFeed.h" -#include -#include +#include #include #include -#include #include +#include +#include #include -#include - -#include "feeds/GxsChannelGroupItem.h" -#include "feeds/GxsChannelPostItem.h" -#include "feeds/GxsForumGroupItem.h" -#include "feeds/GxsForumMsgItem.h" -#include "feeds/PostedGroupItem.h" -#include "Posted/PostedItem.h" -#include "feeds/GxsForumMsgItem.h" - -#include "settings/rsettingswin.h" +#include +#include "feeds/ChatMsgItem.h" #ifdef BLOGS #include "feeds/BlogNewItem.h" #include "feeds/BlogMsgItem.h" #endif - +#include "feeds/GxsCircleItem.h" +#include "feeds/GxsChannelGroupItem.h" +#include "feeds/GxsChannelPostItem.h" +#include "feeds/GxsForumGroupItem.h" +#include "feeds/GxsForumMsgItem.h" #include "feeds/MsgItem.h" +#include "feeds/NewsFeedUserNotify.h" #include "feeds/PeerItem.h" -#include "feeds/ChatMsgItem.h" +#include "feeds/PostedGroupItem.h" #include "feeds/SecurityItem.h" #include "feeds/SecurityIpItem.h" -#include "feeds/NewsFeedUserNotify.h" +#include "settings/rsettingswin.h" #include "settings/rsharesettings.h" + #include "chat/ChatDialog.h" +#include "Posted/PostedItem.h" #include "msgs/MessageComposer.h" +#include "msgs/MessageInterface.h" + #include "common/FeedNotify.h" #include "notifyqt.h" -#include "gui/msgs/MessageInterface.h" - const uint32_t NEWSFEED_PEERLIST = 0x0001; const uint32_t NEWSFEED_FORUMNEWLIST = 0x0002; @@ -80,6 +78,7 @@ const uint32_t NEWSFEED_CHATMSGLIST = 0x0009; const uint32_t NEWSFEED_SECLIST = 0x000a; const uint32_t NEWSFEED_POSTEDNEWLIST = 0x000b; const uint32_t NEWSFEED_POSTEDMSGLIST = 0x000c; +const uint32_t NEWSFEED_CIRCLELIST = 0x000d; #define ROLE_RECEIVED FEED_TREEWIDGET_SORTROLE @@ -102,6 +101,7 @@ NewsFeed::NewsFeed(QWidget *parent) : ui->setupUi(this); mTokenQueueChannel = NULL; + mTokenQueueCircle = NULL; mTokenQueueForum = NULL; mTokenQueuePosted = NULL; @@ -156,6 +156,9 @@ NewsFeed::~NewsFeed() if (mTokenQueueChannel) { delete(mTokenQueueChannel); } + if (mTokenQueueCircle) { + delete(mTokenQueueCircle); + } if (mTokenQueueForum) { delete(mTokenQueueForum); } @@ -370,6 +373,52 @@ void NewsFeed::updateDisplay() if (flags & RS_FEED_TYPE_FILES) addFeedItemFilesNew(fi); break; + + case RS_FEED_ITEM_CIRCLE_MEMB_REQ: + if (flags & RS_FEED_TYPE_CIRCLE) + { + if (!mTokenQueueCircle) { + mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance); + } + + RsGxsGroupId grpId(fi.mId1); + RsGxsMessageId msgId(fi.mId2); + if (!grpId.isNull() && !msgId.isNull()) { + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + + GxsMsgReq msgIds; + std::vector &vect_msgIds = msgIds[grpId]; + vect_msgIds.push_back(msgId); + + uint32_t token; + mTokenQueueCircle->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_MESSAGE); + } + } + // addFeedItemCircleMembReq(fi); + break; + case RS_FEED_ITEM_CIRCLE_INVIT_REC: + if (flags & RS_FEED_TYPE_CIRCLE) + { + if (!mTokenQueueCircle) { + mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance); + } + + RsGxsGroupId grpId(fi.mId1); + if (!grpId.isNull()) { + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::list grpIds; + grpIds.push_back(grpId); + + uint32_t token; + mTokenQueueCircle->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds, TOKEN_TYPE_GROUP); + } + } + // addFeedItemCircleInvitRec(fi); + break; + default: std::cerr << "(EE) Unknown type " << std::hex << fi.mType << std::dec << " in news feed." << std::endl; break; @@ -534,6 +583,24 @@ void NewsFeed::testFeeds(uint notifyFlags) // not used // instance->addFeedItemFilesNew(fi); break; + + case RS_FEED_TYPE_CIRCLE: + { + if (!instance->mTokenQueueCircle) { + instance->mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance); + } + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token; + instance->mTokenQueueCircle->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, TOKEN_TYPE_GROUP); + + break; + } +// instance->addFeedItemCircleMembReq(fi); +// instance->addFeedItemCircleInvitRec(fi); + break; + } } @@ -542,6 +609,78 @@ void NewsFeed::testFeeds(uint notifyFlags) instance->sendNewsFeedChanged(); } +void NewsFeed::loadCircleGroup(const uint32_t &token) +{ + std::vector groups; + if (!rsGxsCircles->getGroupData(token, groups)) { + std::cerr << "NewsFeed::loadCircleGroup() ERROR getting data"; + std::cerr << std::endl; + return; + } + + std::list own_identities; + rsIdentity->getOwnIds(own_identities); + + std::vector::const_iterator circleIt; + for (circleIt = groups.begin(); circleIt != groups.end(); ++circleIt) { + RsGxsCircleGroup group = *(circleIt); + RsGxsCircleDetails details; + if(rsGxsCircles->getCircleDetails(group.mMeta.mCircleId,details)) + { + for(std::list::const_iterator it(own_identities.begin());it!=own_identities.end();++it) { + std::map::const_iterator vit = details.mSubscriptionFlags.find(*it); + uint32_t subscribe_flags = (vit == details.mSubscriptionFlags.end())?0:(vit->second); + + if( !(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED) + && (subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ) { + + RsFeedItem fi; + fi.mId1 = group.mMeta.mGroupId.toStdString(); + fi.mId2 = it->toStdString(); + + instance->addFeedItemCircleInvitRec(fi); + + } + } + } + } +} + +void NewsFeed::loadCircleMessage(const uint32_t &token) +{ + std::vector msgs; + if (!rsGxsCircles->getMsgData(token, msgs)) { + std::cerr << "NewsFeed::loadCircleMessage() ERROR getting data"; + std::cerr << std::endl; + return; + } + + std::list own_identities; + rsIdentity->getOwnIds(own_identities); + + std::vector::iterator msgIt; + for (msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) { + RsGxsCircleMsg msg = *(msgIt); + RsGxsCircleDetails details; + if(rsGxsCircles->getCircleDetails(RsGxsCircleId(msg.mMeta.mGroupId),details)) { + //for(std::list::const_iterator it(own_identities.begin());it!=own_identities.end();++it) { + // std::map::const_iterator vit = details.mSubscriptionFlags.find(*it); + // if (vit != details.mSubscriptionFlags.end()) { + RsFeedItem fi; + fi.mId1 = msgIt->mMeta.mGroupId.toStdString(); + fi.mId2 = msgIt->mMeta.mAuthorId.toStdString(); + + if (msgIt->stuff == "SUBSCRIPTION_REQUEST_UNSUBSCRIBE") + instance->remFeedItemCircleMembReq(fi); + else + instance->addFeedItemCircleMembReq(fi); + + //} + //} + } + } +} + void NewsFeed::loadChannelGroup(const uint32_t &token) { std::vector groups; @@ -821,7 +960,24 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req) break; default: - std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE"; + std::cerr << "NewsFeed::loadRequest() ERROR: INVALID CHANNEL TYPE"; + std::cerr << std::endl; + break; + } + } + + if (queue == mTokenQueueCircle) { + switch (req.mUserType) { + case TOKEN_TYPE_GROUP: + loadCircleGroup(req.mToken); + break; + + case TOKEN_TYPE_MESSAGE: + loadCircleMessage(req.mToken); + break; + + default: + std::cerr << "NewsFeed::loadRequest() ERROR: INVALID CIRCLE TYPE"; std::cerr << std::endl; break; } @@ -842,7 +998,7 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req) break; default: - std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE"; + std::cerr << "NewsFeed::loadRequest() ERROR: INVALID FORUM TYPE"; std::cerr << std::endl; break; } @@ -859,7 +1015,7 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req) break; default: - std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE"; + std::cerr << "NewsFeed::loadRequest() ERROR: INVALID POSTED TYPE"; std::cerr << std::endl; break; } @@ -908,18 +1064,24 @@ void NewsFeed::addFeedItem(FeedItem *item) struct AddFeedItemIfUniqueData { - AddFeedItemIfUniqueData(FeedItem *feedItem, int type, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported) - : mType(type), mSslId(sslId), mIpAddr(ipAddr), mIpAddrReported(ipAddrReported) + AddFeedItemIfUniqueData(FeedItem *feedItem, int type + , const std::string& id1, const std::string& id2 + , const std::string& id3, const std::string& id4) + : mType(type), mId1(id1), mId2(id2), mId3(id3), mId4(id4) { + mGxsCircleItem = dynamic_cast(feedItem); mPeerItem = dynamic_cast(feedItem); mSecItem = dynamic_cast(feedItem); mSecurityIpItem = dynamic_cast(feedItem); } int mType; - const RsPeerId &mSslId; - const std::string& mIpAddr; - const std::string& mIpAddrReported; + const std::string& mId1; + const std::string& mId2; + const std::string& mId3; + const std::string& mId4; + + GxsCircleItem *mGxsCircleItem; PeerItem *mPeerItem; SecurityItem *mSecItem; SecurityIpItem *mSecurityIpItem; @@ -928,13 +1090,21 @@ struct AddFeedItemIfUniqueData static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data) { AddFeedItemIfUniqueData *findData = (AddFeedItemIfUniqueData*) data; - if (!findData || findData->mSslId.isNull()) { + if (!findData || findData->mId1.empty()) { + return false; + } + + if (findData->mGxsCircleItem) { + GxsCircleItem *gxsCircleItem = dynamic_cast(feedItem); + if (gxsCircleItem && gxsCircleItem->isSame(RsGxsCircleId(findData->mId1), RsGxsId(findData->mId2), findData->mType)) { + return true; + } return false; } if (findData->mPeerItem) { PeerItem *peerItem = dynamic_cast(feedItem); - if (peerItem && peerItem->isSame(findData->mSslId, findData->mType)) { + if (peerItem && peerItem->isSame(RsPeerId(findData->mId1), findData->mType)) { return true; } return false; @@ -942,7 +1112,7 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data) if (findData->mSecItem) { SecurityItem *secitem = dynamic_cast(feedItem); - if (secitem && secitem->isSame(findData->mSslId, findData->mType)) { + if (secitem && secitem->isSame(RsPeerId(findData->mId1), findData->mType)) { return true; } return false; @@ -950,7 +1120,7 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data) if (findData->mSecurityIpItem) { SecurityIpItem *securityIpItem = dynamic_cast(feedItem); - if (securityIpItem && securityIpItem->isSame(findData->mIpAddr, findData->mIpAddrReported, findData->mType)) { + if (securityIpItem && securityIpItem->isSame(findData->mId1, findData->mId2, findData->mType)) { return true; } return false; @@ -959,9 +1129,9 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data) return false; } -void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, bool replace) +void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, bool replace) { - AddFeedItemIfUniqueData data(item, itemType, sslId, ipAddr, ipAddrReported); + AddFeedItemIfUniqueData data(item, itemType, id1, id2, id3, id4); FeedItem *feedItem = ui->feedWidget->findFeedItem(addFeedItemIfUniqueCallback, &data); if (feedItem) { @@ -976,6 +1146,18 @@ void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId addFeedItem(item); } +void NewsFeed::remUniqueFeedItem(FeedItem *item, int itemType, const std::string &id1, const std::string &id2, const std::string &id3, const std::string &id4) +{ + AddFeedItemIfUniqueData data(item, itemType, id1, id2, id3, id4); + FeedItem *feedItem = ui->feedWidget->findFeedItem(addFeedItemIfUniqueCallback, &data); + + if (feedItem) { + delete item; + + ui->feedWidget->removeFeedItem(feedItem); + } +} + void NewsFeed::addFeedItemPeerConnect(const RsFeedItem &fi) { /* make new widget */ @@ -1038,7 +1220,7 @@ void NewsFeed::addFeedItemPeerOffset(const RsFeedItem &fi) PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, RsPeerId(fi.mId1), PEER_TYPE_OFFSET, false); /* add to layout */ - addFeedItemIfUnique(pi, PEER_TYPE_OFFSET, RsPeerId(fi.mId1), "", "", false); + addFeedItemIfUnique(pi, PEER_TYPE_OFFSET, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false); #ifdef NEWS_DEBUG std::cerr << "NewsFeed::addFeedItemPeerOffset()"; @@ -1052,7 +1234,7 @@ void NewsFeed::addFeedItemSecurityConnectAttempt(const RsFeedItem &fi) SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, fi.mType, false); /* add to layout */ - addFeedItemIfUnique(pi, fi.mType, RsPeerId(fi.mId2), "", "", false); + addFeedItemIfUnique(pi, fi.mType, fi.mId2, "", "", "", false); #ifdef NEWS_DEBUG std::cerr << "NewsFeed::addFeedItemSecurityConnectAttempt()"; @@ -1066,7 +1248,7 @@ void NewsFeed::addFeedItemSecurityAuthDenied(const RsFeedItem &fi) SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, fi.mType, false); /* add to layout */ - addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_AUTH_DENIED, RsPeerId(fi.mId2), "", "", false); + addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_AUTH_DENIED, fi.mId2, "", "", "", false); #ifdef NEWS_DEBUG std::cerr << "NewsFeed::addFeedItemSecurityAuthDenied()"; @@ -1080,7 +1262,7 @@ void NewsFeed::addFeedItemSecurityUnknownIn(const RsFeedItem &fi) SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, RS_FEED_ITEM_SEC_UNKNOWN_IN, false); /* add to layout */ - addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_IN, RsPeerId(fi.mId2), "", "", false); + addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_IN, fi.mId2, "", "", "", false); #ifdef NEWS_DEBUG std::cerr << "NewsFeed::addFeedItemSecurityUnknownIn()"; @@ -1094,7 +1276,7 @@ void NewsFeed::addFeedItemSecurityUnknownOut(const RsFeedItem &fi) SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, RS_FEED_ITEM_SEC_UNKNOWN_OUT, false); /* add to layout */ - addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_OUT, RsPeerId(fi.mId2), "", "", false); + addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_OUT, fi.mId2, "", "", "", false); #ifdef NEWS_DEBUG std::cerr << "NewsFeed::addFeedItemSecurityUnknownOut()"; @@ -1108,7 +1290,7 @@ void NewsFeed::addFeedItemSecurityIpBlacklisted(const RsFeedItem &fi, bool isTes SecurityIpItem *pi = new SecurityIpItem(this, RsPeerId(fi.mId1), fi.mId2, fi.mResult1, RS_FEED_ITEM_SEC_IP_BLACKLISTED, isTest); /* add to layout */ - addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_BLACKLISTED, RsPeerId(fi.mId1), fi.mId2, "", false); + addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_BLACKLISTED, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false); #ifdef NEWS_DEBUG std::cerr << "NewsFeed::addFeedItemSecurityIpBlacklisted()"; @@ -1122,7 +1304,7 @@ void NewsFeed::addFeedItemSecurityWrongExternalIpReported(const RsFeedItem &fi, SecurityIpItem *pi = new SecurityIpItem(this, RsPeerId(fi.mId1), fi.mId2, fi.mId3, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, isTest); /* add to layout */ - addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, RsPeerId(fi.mId1), fi.mId2, fi.mId3, false); + addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false); #ifdef NEWS_DEBUG std::cerr << "NewsFeed::addFeedItemSecurityWrongExternalIpReported()"; @@ -1375,6 +1557,66 @@ void NewsFeed::addFeedItemFilesNew(const RsFeedItem &/*fi*/) #endif } +void NewsFeed::addFeedItemCircleMembReq(const RsFeedItem &fi) +{ + RsGxsCircleId circleId(fi.mId1); + RsGxsId gxsId(fi.mId2); + + if (circleId.isNull() || gxsId.isNull()) { + return; + } + + /* make new widget */ + GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_MEMB_REQ); + + /* add to layout */ + addFeedItemIfUnique(item, RS_FEED_ITEM_CIRCLE_MEMB_REQ, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemCircleMembReq()" << std::endl; +#endif +} + +void NewsFeed::remFeedItemCircleMembReq(const RsFeedItem &fi) +{ + RsGxsCircleId circleId(fi.mId1); + RsGxsId gxsId(fi.mId2); + + if (circleId.isNull() || gxsId.isNull()) { + return; + } + + /* make new widget */ + GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_MEMB_REQ); + + /* add to layout */ + remUniqueFeedItem(item, RS_FEED_ITEM_CIRCLE_MEMB_REQ, fi.mId1, fi.mId2, fi.mId3, fi.mId4); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::remFeedItemCircleMembReq()" << std::endl; +#endif +} + +void NewsFeed::addFeedItemCircleInvitRec(const RsFeedItem &fi) +{ + RsGxsCircleId circleId(fi.mId1); + RsGxsId gxsId(fi.mId2); + + if (circleId.isNull()) { + return; + } + + /* make new widget */ + GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_INVIT_REC); + + /* add to layout */ + addFeedItem(item); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemCircleInvitRec()" << std::endl; +#endif +} + /* FeedHolder Functions (for FeedItem functionality) */ QScrollArea *NewsFeed::getScrollArea() { @@ -1403,7 +1645,7 @@ void NewsFeed::openChat(const RsPeerId &peerId) ChatDialog::chatFriend(ChatId(peerId)); } -void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector& versions,const RsGxsMessageId &/*msgId*/, const QString &/*title*/) +void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector &/*versions*/,const RsGxsMessageId &/*msgId*/, const QString &/*title*/) { std::cerr << "NewsFeed::openComments() Not Handled Yet"; std::cerr << std::endl; diff --git a/retroshare-gui/src/gui/NewsFeed.h b/retroshare-gui/src/gui/NewsFeed.h index b97476435..9fceaf486 100644 --- a/retroshare-gui/src/gui/NewsFeed.h +++ b/retroshare-gui/src/gui/NewsFeed.h @@ -83,7 +83,8 @@ private slots: private: void addFeedItem(FeedItem *item); - void addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, bool replace); + void addFeedItemIfUnique(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, bool replace); + void remUniqueFeedItem(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4); void addFeedItemPeerConnect(const RsFeedItem &fi); void addFeedItemPeerDisconnect(const RsFeedItem &fi); @@ -119,6 +120,10 @@ private: void addFeedItemMessage(const RsFeedItem &fi); void addFeedItemFilesNew(const RsFeedItem &fi); + void addFeedItemCircleMembReq(const RsFeedItem &fi); + void remFeedItemCircleMembReq(const RsFeedItem &fi); + void addFeedItemCircleInvitRec(const RsFeedItem &fi); + virtual void loadChannelGroup(const uint32_t &token); virtual void loadChannelPost(const uint32_t &token); virtual void loadChannelPublishKey(const uint32_t &token); @@ -130,8 +135,12 @@ private: virtual void loadPostedGroup(const uint32_t &token); virtual void loadPostedMessage(const uint32_t &token); + virtual void loadCircleGroup(const uint32_t &token); + virtual void loadCircleMessage(const uint32_t &token); + private: TokenQueue *mTokenQueueChannel; + TokenQueue *mTokenQueueCircle; TokenQueue *mTokenQueueForum; TokenQueue *mTokenQueuePosted; diff --git a/retroshare-gui/src/gui/feeds/GxsCircleItem.cpp b/retroshare-gui/src/gui/feeds/GxsCircleItem.cpp new file mode 100644 index 000000000..b37b72ef1 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/GxsCircleItem.cpp @@ -0,0 +1,284 @@ +/* + * Retroshare Gxs Feed Item + * + * Copyright 2014 RetroShare Team + * + * 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.1 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 "retroshare@lunamutt.com". + * + */ + +#include "GxsCircleItem.h" +#include "ui_GxsCircleItem.h" + +#include "FeedHolder.h" +#include "gui/notifyqt.h" +#include "gui/Circles/CreateCircleDialog.h" +#include "gui/gxs/GxsIdDetails.h" + +#include +#include +#include + +#include + +/**** + * #define DEBUG_ITEM 1 + ****/ + +#define COLOR_NORMAL QColor(248, 248, 248) +#define COLOR_NEW QColor(220, 236, 253) + +#define CIRCLESDIALOG_GROUPUPDATE 3 + + +GxsCircleItem::GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type) + :FeedItem(NULL), mFeedHolder(feedHolder), mFeedId(feedId), mType(type), mCircleId(circleId), mGxsId(gxsId) +{ + setup(); +} + + +GxsCircleItem::~GxsCircleItem() +{ + delete(ui); +} + +void GxsCircleItem::setup() +{ + /* Invoke the Qt Designer generated object setup routine */ + ui = new Ui::GxsCircleItem; + ui->setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose, true); + + /* general ones */ + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(showCircleDetails())); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); + + /* update gxs information */ + + RsIdentityDetails idDetails ; + QString idName ; + if(rsIdentity->getIdDetails(mGxsId, idDetails)) + idName = tr("for identity ")+QString::fromUtf8(idDetails.mNickname.c_str()) + " (ID=" + QString::fromStdString(mGxsId.toStdString()) + ")" ; + else + idName = tr("for identity ")+QString::fromStdString(mGxsId.toStdString()) ; + + + /* update circle information */ + + RsGxsCircleDetails circleDetails; + if (rsGxsCircles->getCircleDetails(mCircleId, circleDetails)) + { + + if (mType == RS_FEED_ITEM_CIRCLE_MEMB_REQ) + { + ui->titleLabel->setText(tr("You received a membership request for circle:")); + ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str())); + ui->gxsIdLabel->setText(idName); + + ui->acceptButton->setToolTip(tr("Grant membership request")); + ui->revokeButton->setToolTip(tr("Revoke membership request")); + connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(grantCircleMembership())); + connect(ui->revokeButton, SIGNAL(clicked()), this, SLOT(revokeCircleMembership())); + } + else if (mType == RS_FEED_ITEM_CIRCLE_INVIT_REC) + { + ui->titleLabel->setText(tr("You received an invitation for circle:")); + ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str())); + ui->gxsIdLabel->setText(idName); + + ui->acceptButton->setToolTip(tr("Accept invitation")); + connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(acceptCircleSubscription())); + ui->revokeButton->setHidden(true); + } + + } + else + { + ui->titleLabel->setText(tr("Received event from unknown Circle:")); + ui->nameLabel->setText(QString::fromStdString(mCircleId.toStdString())); + ui->gxsIdLabel->setText(idName); + } + + /* Setup TokenQueue */ + mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); + +} + +bool GxsCircleItem::isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type) +{ + if ((mCircleId == circleId) && (mGxsId == gxsId) && (mType == type)) + { + return true; + } + return false; + +} + +void GxsCircleItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "GxsCircleItem::removeItem()" << std::endl; +#endif + + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, true); + hide(); + mFeedHolder->lockLayout(this, false); + + mFeedHolder->deleteFeedItem(this, mFeedId); + } +} + +void GxsCircleItem::loadRequest(const TokenQueue * queue, const TokenRequest &req) +{ +#ifdef ID_DEBUG + std::cerr << "GxsCircleItem::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; +#endif + if(queue == mCircleQueue) + { +#ifdef ID_DEBUG + std::cerr << "CirclesDialog::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; +#endif + + /* now switch on req */ + switch(req.mUserType) + { + case CIRCLESDIALOG_GROUPUPDATE: + updateCircleGroup(req.mToken); + break; + + default: + std::cerr << "GxsCircleItem::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } +} + + +/*********** SPECIFIC FUNCTIONS ***********************/ + +void GxsCircleItem::showCircleDetails() +{ + CreateCircleDialog dlg; + + dlg.editExistingId(RsGxsGroupId(mCircleId), true, mType != RS_FEED_ITEM_CIRCLE_MEMB_REQ) ; + dlg.exec(); +} + +void GxsCircleItem::acceptCircleSubscription() +{ + if (rsGxsCircles->requestCircleMembership(mGxsId, mCircleId)) + removeItem(); +} + +void GxsCircleItem::grantCircleMembership() +{ + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::list grps ; + grps.push_back(RsGxsGroupId(mCircleId)); + + uint32_t token; + mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grps, CIRCLESDIALOG_GROUPUPDATE); + + CircleUpdateOrder c ; + c.token = token ; + c.gxs_id = mGxsId ; + c.action = CircleUpdateOrder::GRANT_MEMBERSHIP ; + + mCircleUpdates[token] = c ; +} + +void GxsCircleItem::revokeCircleMembership() +{ + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::list grps; + grps.push_back(RsGxsGroupId(mCircleId)); + + uint32_t token; + mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grps, CIRCLESDIALOG_GROUPUPDATE); + + CircleUpdateOrder c; + c.token = token; + c.gxs_id = mGxsId; + c.action = CircleUpdateOrder::REVOKE_MEMBERSHIP; + + mCircleUpdates[token] = c; +} + +void GxsCircleItem::updateCircleGroup(const uint32_t& token) +{ +#ifdef ID_DEBUG + std::cerr << "Loading circle info" << std::endl; +#endif + + std::vector circle_grp_v ; + rsGxsCircles->getGroupData(token, circle_grp_v); + + if (circle_grp_v.empty()) + { + std::cerr << "(EE) unexpected empty result from getGroupData. Cannot process circle now!" << std::endl; + return ; + } + + if (circle_grp_v.size() != 1) + { + std::cerr << "(EE) very weird result from getGroupData. Should get exactly one circle" << std::endl; + return ; + } + + RsGxsCircleGroup cg = circle_grp_v.front(); + + /* now mark all the members */ + + //std::set members = cg.mInvitedMembers; + + std::map::iterator it = mCircleUpdates.find(token) ; + + if(it == mCircleUpdates.end()) + { + std::cerr << "(EE) Cannot find token " << token << " to perform group update!" << std::endl; + return ; + } + + if(it->second.action == CircleUpdateOrder::GRANT_MEMBERSHIP) + cg.mInvitedMembers.insert(it->second.gxs_id) ; + else if(it->second.action == CircleUpdateOrder::REVOKE_MEMBERSHIP) + cg.mInvitedMembers.erase(it->second.gxs_id) ; + else + { + std::cerr << "(EE) unrecognised membership action to perform: " << it->second.action << "!" << std::endl; + return ; + } + + uint32_t token2 ; + rsGxsCircles->updateGroup(token2,cg) ; + + mCircleUpdates.erase(it) ; +} + diff --git a/retroshare-gui/src/gui/feeds/GxsCircleItem.h b/retroshare-gui/src/gui/feeds/GxsCircleItem.h new file mode 100644 index 000000000..760df3db2 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/GxsCircleItem.h @@ -0,0 +1,98 @@ +/* + * Retroshare Gxs Feed Item + * + * Copyright 2014 RetroShare Team + * + * 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.1 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 "retroshare@lunamutt.com". + * + */ + +#ifndef _GXSCIRCLEITEM_H +#define _GXSCIRCLEITEM_H + +#include +#include "FeedItem.h" + +#include "util/TokenQueue.h" + +namespace Ui { +class GxsCircleItem; +} + +class FeedHolder; + +struct CircleUpdateOrder +{ + enum { UNKNOWN_ACTION=0x00, GRANT_MEMBERSHIP=0x01, REVOKE_MEMBERSHIP=0x02 }; + + uint32_t token ; + RsGxsId gxs_id ; + uint32_t action ; +}; + + +class GxsCircleItem : public FeedItem, public TokenResponse +{ + Q_OBJECT + +public: + + /** Default Constructor */ + GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type); + virtual ~GxsCircleItem(); + + bool isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type); + + void loadRequest(const TokenQueue *queue, const TokenRequest &req); + + +protected: + /* FeedItem */ + virtual void doExpand(bool /*open*/) {} + + void updateCircleGroup(const uint32_t& token); + + + +private slots: + /* default stuff */ + void removeItem(); + + void showCircleDetails(); + void acceptCircleSubscription(); + void grantCircleMembership() ; + void revokeCircleMembership(); + +private: + void setup(); + + FeedHolder *mFeedHolder; + uint32_t mFeedId; + uint32_t mType; + + RsGxsCircleId mCircleId; + RsGxsId mGxsId; + + TokenQueue *mCircleQueue; + std::map mCircleUpdates ; + + + /** Qt Designer generated object */ + Ui::GxsCircleItem *ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/feeds/GxsCircleItem.ui b/retroshare-gui/src/gui/feeds/GxsCircleItem.ui new file mode 100644 index 000000000..141d49e4c --- /dev/null +++ b/retroshare-gui/src/gui/feeds/GxsCircleItem.ui @@ -0,0 +1,298 @@ + + + GxsCircleItem + + + + 0 + 0 + 618 + 96 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + 0 + 0 + + + + + + + + + 215 + 215 + 215 + + + + + + + 215 + 215 + 215 + + + + + + + + + 215 + 215 + 215 + + + + + + + 215 + 215 + 215 + + + + + + + + + 215 + 215 + 215 + + + + + + + 215 + 215 + 215 + + + + + + + + true + + + QFrame::Box + + + QFrame::Sunken + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + :/icons/svg/circles.svg + + + true + + + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + Circle + + + + + + + name + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + name + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 254 + 28 + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + + :/images/accepted16.png:/images/accepted16.png + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + + :/images/cancel.png:/images/cancel.png + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Details + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Remove Item + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/NotifyPage.cpp b/retroshare-gui/src/gui/settings/NotifyPage.cpp index 09f9efbfc..7c0bdd123 100755 --- a/retroshare-gui/src/gui/settings/NotifyPage.cpp +++ b/retroshare-gui/src/gui/settings/NotifyPage.cpp @@ -162,6 +162,7 @@ NotifyPage::NotifyPage(QWidget * parent, Qt::WindowFlags flags) connect(ui.message_ConnectAttempt, SIGNAL(toggled(bool)), this, SLOT(updateMessageFlags())) ; connect(ui.notify_Peers, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags())); + connect(ui.notify_Circles, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags())); connect(ui.notify_Channels, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags())); connect(ui.notify_Forums, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags())); connect(ui.notify_Posted, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags())); @@ -195,6 +196,8 @@ uint NotifyPage::getNewsFlags() if (ui.notify_Peers->isChecked()) newsFlags |= RS_FEED_TYPE_PEER; + if (ui.notify_Circles->isChecked()) + newsFlags |= RS_FEED_TYPE_CIRCLE; if (ui.notify_Channels->isChecked()) newsFlags |= RS_FEED_TYPE_CHANNEL; if (ui.notify_Forums->isChecked()) @@ -324,6 +327,7 @@ void NotifyPage::load() whileBlocking(ui.popup_ConnectAttempt)->setChecked(notifyflags & RS_POPUP_CONNECT_ATTEMPT); whileBlocking(ui.notify_Peers)->setChecked(newsflags & RS_FEED_TYPE_PEER); + whileBlocking(ui.notify_Circles)->setChecked(newsflags & RS_FEED_TYPE_CIRCLE); whileBlocking(ui.notify_Channels)->setChecked(newsflags & RS_FEED_TYPE_CHANNEL); whileBlocking(ui.notify_Forums)->setChecked(newsflags & RS_FEED_TYPE_FORUM); whileBlocking(ui.notify_Posted)->setChecked(newsflags & RS_FEED_TYPE_POSTED); diff --git a/retroshare-gui/src/gui/settings/NotifyPage.ui b/retroshare-gui/src/gui/settings/NotifyPage.ui index c0bd95317..0f25f470e 100755 --- a/retroshare-gui/src/gui/settings/NotifyPage.ui +++ b/retroshare-gui/src/gui/settings/NotifyPage.ui @@ -51,6 +51,13 @@ + + + + Circles + + + diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index c469dcbba..b0280c686 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -551,6 +551,7 @@ HEADERS += rshare.h \ gui/NewsFeed.h \ gui/feeds/FeedItem.h \ gui/feeds/FeedHolder.h \ + gui/feeds/GxsCircleItem.h \ gui/feeds/PeerItem.h \ gui/feeds/MsgItem.h \ gui/feeds/ChatMsgItem.h \ @@ -656,6 +657,7 @@ FORMS += gui/StartDialog.ui \ gui/advsearch/AdvancedSearchDialog.ui \ gui/advsearch/expressionwidget.ui \ gui/NewsFeed.ui \ + gui/feeds/GxsCircleItem.ui \ gui/feeds/PeerItem.ui \ gui/feeds/MsgItem.ui \ gui/feeds/ChatMsgItem.ui \ @@ -685,7 +687,7 @@ FORMS += gui/StartDialog.ui \ gui/statistics/StatisticsWindow.ui \ gui/statistics/BwCtrlWindow.ui \ gui/statistics/RttStatistics.ui \ - gui/GetStartedDialog.ui \ + gui/GetStartedDialog.ui # gui/ForumsDialog.ui \ @@ -900,6 +902,7 @@ SOURCES += main.cpp \ gui/NewsFeed.cpp \ gui/feeds/FeedItem.cpp \ gui/feeds/FeedHolder.cpp \ + gui/feeds/GxsCircleItem.cpp \ gui/feeds/PeerItem.cpp \ gui/feeds/MsgItem.cpp \ gui/feeds/ChatMsgItem.cpp \ From 80ec9b73218e04dde129c64ddd9da8008840d5bc Mon Sep 17 00:00:00 2001 From: Jeetu Golani Date: Mon, 12 Jun 2017 15:51:26 +0530 Subject: [PATCH 13/24] Included QStringList header in ApiServerLocal.cpp [Issue 879] --- libresapi/src/api/ApiServerLocal.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libresapi/src/api/ApiServerLocal.cpp b/libresapi/src/api/ApiServerLocal.cpp index 5d89ed2d0..ec1812af7 100644 --- a/libresapi/src/api/ApiServerLocal.cpp +++ b/libresapi/src/api/ApiServerLocal.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include #include "ApiServerLocal.h" #include "JsonStream.h" From 79825eb2e2a5fb73fdd3193bf73fe3d0b6a5b39b Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 12 Jun 2017 20:36:02 +0200 Subject: [PATCH 14/24] fixed thread issue in RsGxsCleanupThread that caused random crashes --- libretroshare/src/gxs/rsgenexchange.cc | 84 +++++++++++++------------- libretroshare/src/gxs/rsgxsutil.cc | 84 ++++++++++++++------------ libretroshare/src/util/rsthreads.cc | 1 + 3 files changed, 88 insertions(+), 81 deletions(-) diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 32ddaa7e6..e6a1b3d30 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -190,52 +190,54 @@ void RsGenExchange::tick() now = time(NULL); if(mChecking || (mLastCheck + INTEGRITY_CHECK_PERIOD < now)) { - if(mIntegrityCheck) + mLastCheck = time(NULL); + { - if(mIntegrityCheck->isDone()) + RS_STACK_MUTEX(mGenMtx) ; + + if(!mIntegrityCheck) { - std::list grpIds; - std::map > msgIds; - mIntegrityCheck->getDeletedIds(grpIds, msgIds); - - if (!grpIds.empty()) - { - RS_STACK_MUTEX(mGenMtx) ; - - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, false); - gc->mGrpIdList = grpIds; -#ifdef GEN_EXCH_DEBUG - std::cerr << " adding the following grp ids to notification: " << std::endl; - for(std::list::const_iterator it(grpIds.begin());it!=grpIds.end();++it) - std::cerr << " " << *it << std::endl; -#endif - mNotifications.push_back(gc); - - // also notify the network exchange service that these groups no longer exist. - - if(mNetService) - mNetService->removeGroups(grpIds) ; - } - - if (!msgIds.empty()) { - RS_STACK_MUTEX(mGenMtx) ; - - RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, false); - c->msgChangeMap = msgIds; - mNotifications.push_back(c); - } - - delete mIntegrityCheck; - mIntegrityCheck = NULL; - mLastCheck = time(NULL); - mChecking = false; + mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore,this,mGixs); + mIntegrityCheck->start("gxs integrity"); + mChecking = true; } } - else + + if(mIntegrityCheck->isDone()) { - mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore,this,mGixs); - mIntegrityCheck->start("gxs integrity"); - mChecking = true; + RS_STACK_MUTEX(mGenMtx) ; + + std::list grpIds; + std::map > msgIds; + mIntegrityCheck->getDeletedIds(grpIds, msgIds); + + if (!grpIds.empty()) + { + RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, false); + gc->mGrpIdList = grpIds; +#ifdef GEN_EXCH_DEBUG + std::cerr << " adding the following grp ids to notification: " << std::endl; + for(std::list::const_iterator it(grpIds.begin());it!=grpIds.end();++it) + std::cerr << " " << *it << std::endl; +#endif + mNotifications.push_back(gc); + + // also notify the network exchange service that these groups no longer exist. + + if(mNetService) + mNetService->removeGroups(grpIds) ; + } + + if (!msgIds.empty()) + { + RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, false); + c->msgChangeMap = msgIds; + mNotifications.push_back(c); + } + + delete mIntegrityCheck; + mIntegrityCheck = NULL; + mChecking = false; } } } diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc index 21d7d3d3e..8a853e789 100644 --- a/libretroshare/src/gxs/rsgxsutil.cc +++ b/libretroshare/src/gxs/rsgxsutil.cc @@ -136,6 +136,9 @@ RsGxsIntegrityCheck::RsGxsIntegrityCheck(RsGeneralDataService* const dataService void RsGxsIntegrityCheck::run() { check(); + + RsStackMutex stack(mIntegrityMutex); + mDone = true; } bool RsGxsIntegrityCheck::check() @@ -286,71 +289,72 @@ bool RsGxsIntegrityCheck::check() mDs->removeMsgs(msgsToDel); - RsStackMutex stack(mIntegrityMutex); - mDone = true; + { + RsStackMutex stack(mIntegrityMutex); - std::vector::iterator grpIt; - for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt) - { - mDeletedGrps.push_back(*grpIt); - } - mDeletedMsgs = msgsToDel; + std::vector::iterator grpIt; + for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt) + { + mDeletedGrps.push_back(*grpIt); + } + mDeletedMsgs = msgsToDel; #ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl; - GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl; + GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl; + GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl; #endif - std::list connected_friends ; - rsPeers->getOnlineList(connected_friends) ; + std::list connected_friends ; + rsPeers->getOnlineList(connected_friends) ; - std::vector > gxs_ids ; + std::vector > gxs_ids ; - for(std::map::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it) - { - gxs_ids.push_back(*it) ; + for(std::map::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it) + { + gxs_ids.push_back(*it) ; #ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " " << *it << std::endl; + GXSUTIL_DEBUG() << " " << *it << std::endl; #endif - } - uint32_t nb_requested_not_in_cache = 0; + } + uint32_t nb_requested_not_in_cache = 0; #ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl; + GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl; #endif - // now request a cache update for them, which triggers downloading from friends, if missing. + // now request a cache update for them, which triggers downloading from friends, if missing. - for(;nb_requested_not_in_cachehaveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it) - { - mGixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second); + if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it) + { + mGixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second); - ++nb_requested_not_in_cache ; + ++nb_requested_not_in_cache ; #ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " ... from cache/net" << std::endl; + GXSUTIL_DEBUG() << " ... from cache/net" << std::endl; #endif - } - else - { + } + else + { #ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " ... already in cache" << std::endl; + GXSUTIL_DEBUG() << " ... already in cache" << std::endl; #endif - } - mGixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second); + } + mGixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second); - gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ; - gxs_ids.pop_back() ; - } + gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ; + gxs_ids.pop_back() ; + } #ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl; + GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl; #endif + } return true; } diff --git a/libretroshare/src/util/rsthreads.cc b/libretroshare/src/util/rsthreads.cc index 1db86f17e..8899ee01c 100644 --- a/libretroshare/src/util/rsthreads.cc +++ b/libretroshare/src/util/rsthreads.cc @@ -179,6 +179,7 @@ void RsThread::start(const std::string &threadName) THREAD_DEBUG << "pqithreadstreamer::start() initing should_stop=0" << std::endl; #endif mShouldStopSemaphore.set(0) ; + mHasStoppedSemaphore.set(0) ; int err ; From 09ff94c9ec39db7c8ebb444e2a1b46ab4eccf029 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 14 Jun 2017 23:19:52 +0200 Subject: [PATCH 15/24] added new virtual method to refuse incoming msgs (similar to groups) in RsGenExchange, and used it in p3GxsTrans to refuse msgs from peers who send too much --- libretroshare/src/gxs/rsgenexchange.cc | 10 ++- libretroshare/src/gxs/rsgenexchange.h | 11 ++++ libretroshare/src/gxstrans/p3gxstrans.cc | 78 ++++++++++++++++++++++++ libretroshare/src/gxstrans/p3gxstrans.h | 20 +++++- 4 files changed, 115 insertions(+), 4 deletions(-) diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 5845a2887..22b6dd069 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -2900,8 +2900,12 @@ void RsGenExchange::processRecvdMessages() std::cerr << " deserialised info: grp id=" << meta->mGroupId << ", msg id=" << meta->mMsgId ; #endif uint8_t validateReturn = VALIDATE_FAIL; + bool accept_new_msg = acceptNewMessage(meta); - if(ok) + if(!accept_new_msg && mNetService != NULL) + mNetService->rejectMessage(meta->mMsgId) ; // This prevents reloading the message again at next sync. + + if(ok && accept_new_msg) { std::map::iterator mit = grpMetas.find(msg->grpId); @@ -3042,8 +3046,8 @@ void RsGenExchange::processRecvdMessages() mNetService->rejectMessage(*it) ; } -bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ ) -{ return true; } +bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ ) { return true; } +bool RsGenExchange::acceptNewMessage(const RsGxsMsgMetaData* /*grpMeta*/ ) { return true; } void RsGenExchange::processRecvdGroups() { diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index 932177427..2bc80fd65 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -260,6 +260,17 @@ public: */ virtual bool acceptNewGroup(const RsGxsGrpMetaData *grpMeta) ; + /*! + * \brief acceptNewMessage + * Early checks if the message can be accepted. This is mainly used to check wether the group is for instance overloaded and the service wants + * to put limitations to it. + * Returns true unless derived in GXS services. + * + * \param grpMeta Group metadata to check + * \return + */ + virtual bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta) ; + bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe); /*! diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index 41a100e4c..bd335c9a6 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -24,6 +24,8 @@ typedef unsigned int uint; RsGxsTrans *rsGxsTrans = NULL ; +const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 60; // every 20 mins. Could be less. + p3GxsTrans::~p3GxsTrans() { p3Config::saveConfiguration(); @@ -261,6 +263,12 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) if(changed) IndicateConfigChanged(); } +void p3GxsTrans::GxsTransIntegrityCleanupThread::getPerUserStatistics(std::map& m) +{ + RS_STACK_MUTEX(mMtx) ; + + m = total_message_size_and_count ; +} void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq& m) { @@ -270,9 +278,27 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq& mMsgToDel.clear(); } +// This method does two things: +// 1 - cleaning up old messages and messages for which an ACK has been received. +// 2 - building per user statistics across groups. This is important because it allows to mitigate the excess of +// messages, which might be due to spam. +// +// Note: the anti-spam system is disabled the level of GXS, because we want to allow to send anonymous messages +// between identities that might not have a reputation yet. Still, messages from identities with a bad reputation +// are still deleted by GXS. +// +// The group limits are enforced according to the following rules: +// * a temporal sliding window is computed for each identity and the number of messages signed by this identity is counted +// * +// +// +// Deleted messages are notified to the RsGxsNetService part which keeps a list of delete messages so as not to request them again +// during the same session. This allows to safely delete messages while avoiding re-synchronisation from friend nodes. + void p3GxsTrans::GxsTransIntegrityCleanupThread::run() { // first take out all the groups + std::map grp; mDs->retrieveNxsGrps(grp, true, true); @@ -294,6 +320,8 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() // now messages + std::map totalMessageSizeAndCount; + std::map > stored_msgs ; std::list received_msgs ; @@ -332,14 +360,22 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() else std::cerr << " Unknown item type!" << std::endl; + totalMessageSizeAndCount[msg->metaData->mAuthorId].size += msg->msg.bin_len ; + totalMessageSizeAndCount[msg->metaData->mAuthorId].count++; delete msg; } } + // From the collected information, build a list of group messages to delete. + GxsMsgReq msgsToDel ; std::cerr << "Msg removal report:" << std::endl; + std::cerr << " Per user size and count: " << std::endl; + for(std::map::const_iterator it(totalMessageSizeAndCount.begin());it!=totalMessageSizeAndCount.end();++it) + std::cerr << " " << it->first << ": " << it->second.count << " messages, for a total size of " << it->second.size << " bytes." << std::endl; + for(std::list::const_iterator it(received_msgs.begin());it!=received_msgs.end();++it) { std::map >::const_iterator it2 = stored_msgs.find(*it) ; @@ -385,6 +421,7 @@ void p3GxsTrans::service_tick() { GxsMsgReq msgToDel ; + mCleanupThread->getPerUserStatistics(per_user_statistics) ; mCleanupThread->getMessagesToDelete(msgToDel) ; if(!msgToDel.empty()) @@ -1023,3 +1060,44 @@ bool p3GxsTrans::loadList(std::list&loadList) return true; } + +// We should also include the message size! + +bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta) +{ +#ifdef TODO + // 1 - check the total size of the msgs for the author of this particular msg. + + // 2 - Reject depending on embedded limits. + + // Depending on reputation, the messages will be rejected: + // + // Reputation | Maximum msg count | Maximum msg size + // ------------+----------------------+------------------ + // Negative | 0 | 0 // This is already handled by the anti-spam + // R-Negative | 10 | 10k + // Neutral | 100 | 500k + // R-Positive | 500 | 2M + + static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ; + static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 100 ; + static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 100 ; + + uint32_t max_count = 0 ; + uint32_t max_size = 0 ; + + switch(rsReputations->overallReputationLevel(msgMeta.mAuthorId)) + { + case RsReputations::REPUTATION_REMOTELY_NEGATIVE: max_count = 10 ; + max_size = 10*1024 ; + default: + case RsReputations::REPUTATION_LOCALLY_NEGATIVE: max_count = + break ; + } + +#endif + return true ; +} + + + diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h index fb205409d..8d5792343 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ b/libretroshare/src/gxstrans/p3gxstrans.h @@ -57,6 +57,14 @@ struct GxsTransClient GxsTransSendStatus status ) = 0; }; +struct MsgSizeCount +{ + MsgSizeCount() : size(0),count(0) {} + + uint32_t size ; + uint32_t count ; +}; + /** * @brief p3GxsTrans is a mail delivery service based on GXS. * p3GxsTrans is capable of asynchronous mail delivery and acknowledgement. @@ -159,7 +167,7 @@ private: * Two weeks seems fair ATM. */ static const uint32_t GXS_STORAGE_PERIOD = 0x127500; - static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS = 1203; // every 20 mins. Could be less. + static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS ; // every 20 mins. Could be less. time_t mLastMsgCleanup ; @@ -290,14 +298,24 @@ private: void getDeletedIds(std::list& grpIds, std::map >& msgIds); void getMessagesToDelete(GxsMsgReq& req) ; + void getPerUserStatistics(std::map& m) ; private: RsGeneralDataService* const mDs; RsMutex mMtx ; GxsMsgReq mMsgToDel ; + std::map total_message_size_and_count; }; + // Overloaded from RsGenExchange. + + bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta) ; + GxsTransIntegrityCleanupThread *mCleanupThread ; + + // statistics of the load across all groups, per user. + + std::map per_user_statistics ; }; From fe5ec8bda8e39c8281d70698af244ad00aca7ada Mon Sep 17 00:00:00 2001 From: sehraf Date: Thu, 15 Jun 2017 07:06:52 +0200 Subject: [PATCH 16/24] reduce BOB log level --- libretroshare/src/services/autoproxy/p3i2pbob.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretroshare/src/services/autoproxy/p3i2pbob.cc b/libretroshare/src/services/autoproxy/p3i2pbob.cc index 5b7f9f8ed..32be374f4 100644 --- a/libretroshare/src/services/autoproxy/p3i2pbob.cc +++ b/libretroshare/src/services/autoproxy/p3i2pbob.cc @@ -34,7 +34,7 @@ static const int sleepFactorDefault = 10; // 0.5s static const int sleepFactorFast = 1; // 0.05s static const int sleepFactorSlow = 20; // 1s -static struct RsLog::logInfo i2pBobLogInfo = {RsLog::Debug_All, "p3I2pBob"}; +static struct RsLog::logInfo i2pBobLogInfo = {RsLog::Default, "p3I2pBob"}; static const time_t selfCheckPeroid = 30; From 65ab68b4f70d463955cb73044a2b268088ba878e Mon Sep 17 00:00:00 2001 From: sehraf Date: Thu, 15 Jun 2017 07:20:24 +0200 Subject: [PATCH 17/24] fix stop button being wrongly disabled --- retroshare-gui/src/gui/settings/ServerPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/settings/ServerPage.cpp b/retroshare-gui/src/gui/settings/ServerPage.cpp index 5051f62b3..b33506c6b 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.cpp +++ b/retroshare-gui/src/gui/settings/ServerPage.cpp @@ -1635,7 +1635,7 @@ void ServerPage::updateStatusBob() ui.pbBobStart->setToolTip("BOB is not accessible"); ui.pbBobRestart->setEnabled(false); ui.pbBobRestart->setToolTip("BOB is not accessible"); - ui.pbBobStop->setEnabled(false); + // don't disable the stop button! (in case bob is running you are otherwise unable to stop and disable it) ui.pbBobStop->setToolTip("BOB is not accessible"); } else { ui.pbBobStart->setToolTip(""); From 26bb865d2969367f42ed99168ab805b84b40f3e3 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 15 Jun 2017 19:32:31 +0200 Subject: [PATCH 18/24] added code to reject messages based on existing per-user statistics --- libretroshare/src/gxs/rsgenexchange.cc | 4 +- libretroshare/src/gxs/rsgenexchange.h | 2 +- libretroshare/src/gxstrans/p3gxstrans.cc | 68 ++++++++++++++++++------ libretroshare/src/gxstrans/p3gxstrans.h | 6 ++- 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 22b6dd069..55eea22a6 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -2900,7 +2900,7 @@ void RsGenExchange::processRecvdMessages() std::cerr << " deserialised info: grp id=" << meta->mGroupId << ", msg id=" << meta->mMsgId ; #endif uint8_t validateReturn = VALIDATE_FAIL; - bool accept_new_msg = acceptNewMessage(meta); + bool accept_new_msg = acceptNewMessage(meta,msg->msg.bin_len); if(!accept_new_msg && mNetService != NULL) mNetService->rejectMessage(meta->mMsgId) ; // This prevents reloading the message again at next sync. @@ -3047,7 +3047,7 @@ void RsGenExchange::processRecvdMessages() } bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ ) { return true; } -bool RsGenExchange::acceptNewMessage(const RsGxsMsgMetaData* /*grpMeta*/ ) { return true; } +bool RsGenExchange::acceptNewMessage(const RsGxsMsgMetaData* /*grpMeta*/,uint32_t size ) { return true; } void RsGenExchange::processRecvdGroups() { diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index 2bc80fd65..ee7449f2f 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -269,7 +269,7 @@ public: * \param grpMeta Group metadata to check * \return */ - virtual bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta) ; + virtual bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ; bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe); diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index bd335c9a6..a1d354fd2 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -421,7 +421,6 @@ void p3GxsTrans::service_tick() { GxsMsgReq msgToDel ; - mCleanupThread->getPerUserStatistics(per_user_statistics) ; mCleanupThread->getMessagesToDelete(msgToDel) ; if(!msgToDel.empty()) @@ -429,6 +428,9 @@ void p3GxsTrans::service_tick() std::cerr << "p3GxsTrans::service_tick(): deleting messages." << std::endl; getDataStore()->removeMsgs(msgToDel); } + + RS_STACK_MUTEX(mPerUserStatsMutex); + mCleanupThread->getPerUserStatistics(per_user_statistics) ; } { @@ -1063,9 +1065,8 @@ bool p3GxsTrans::loadList(std::list&loadList) // We should also include the message size! -bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta) +bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_size) { -#ifdef TODO // 1 - check the total size of the msgs for the author of this particular msg. // 2 - Reject depending on embedded limits. @@ -1077,26 +1078,63 @@ bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta) // Negative | 0 | 0 // This is already handled by the anti-spam // R-Negative | 10 | 10k // Neutral | 100 | 500k - // R-Positive | 500 | 2M + // R-Positive | 400 | 1M + // Positive | 1000 | 2M - static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ; - static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 100 ; - static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 100 ; + // Ideally these values should be left as user-defined parameters, with the + // default values below used as backup. + + static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ; + static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 100 ; + static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT = 400 ; + static const uint32_t GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT = 1000 ; + + static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT = 10 * 1024 ; + static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 512 * 1024 ; + static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT = 1024 * 1024 ; + static const uint32_t GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT = 2 * 1024 * 1024 ; uint32_t max_count = 0 ; uint32_t max_size = 0 ; + RsReputations::ReputationLevel rep_lev = rsReputations->overallReputationLevel(msgMeta->mAuthorId); - switch(rsReputations->overallReputationLevel(msgMeta.mAuthorId)) + switch(rep_lev) { - case RsReputations::REPUTATION_REMOTELY_NEGATIVE: max_count = 10 ; - max_size = 10*1024 ; - default: - case RsReputations::REPUTATION_LOCALLY_NEGATIVE: max_count = - break ; + case RsReputations::REPUTATION_REMOTELY_NEGATIVE: max_count = GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT; + max_size = GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT; + break ; + case RsReputations::REPUTATION_NEUTRAL: max_count = GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT; + max_size = GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT; + break ; + case RsReputations::REPUTATION_REMOTELY_POSITIVE: max_count = GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT; + max_size = GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT; + break ; + case RsReputations::REPUTATION_LOCALLY_POSITIVE: max_count = GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT; + max_size = GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT; + break ; + default: + case RsReputations::REPUTATION_LOCALLY_NEGATIVE: max_count = 0 ; + max_size = 0 ; + break ; } -#endif - return true ; + RS_STACK_MUTEX(mPerUserStatsMutex); + + MsgSizeCount& s(per_user_statistics[msgMeta->mAuthorId]) ; + + std::cerr << "GxsTrans::acceptMessage(): size=" << msg_size << ", grp=" << msgMeta->mGroupId << ", gxs_id=" << msgMeta->mAuthorId << ", current (size,cnt)=(" + << s.size << "," << s.count << ") reputation=" << rep_lev << ", limits=(" << max_size << "," << max_count << ") " ; + + if(s.size + msg_size > max_size || 1+s.count > max_count) + { + std::cerr << "=> rejected." << std::endl; + return false ; + } + else + { + std::cerr << "=> accepted." << std::endl; + return true ; + } } diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h index 8d5792343..28060ad0f 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ b/libretroshare/src/gxstrans/p3gxstrans.h @@ -98,7 +98,8 @@ public: mIdService(identities), mServClientsMutex("p3GxsTrans client services map mutex"), mOutgoingMutex("p3GxsTrans outgoing queue map mutex"), - mIngoingMutex("p3GxsTrans ingoing queue map mutex") + mIngoingMutex("p3GxsTrans ingoing queue map mutex"), + mPerUserStatsMutex("p3GxsTrans user stats mutex") { mLastMsgCleanup = time(NULL) - 60; // to be changed into 0 mCleanupThread = NULL ; @@ -310,12 +311,13 @@ private: // Overloaded from RsGenExchange. - bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta) ; + bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ; GxsTransIntegrityCleanupThread *mCleanupThread ; // statistics of the load across all groups, per user. + RsMutex mPerUserStatsMutex; std::map per_user_statistics ; }; From 6633b04a44c17d878a2038f1653f837b06c1d15c Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 15 Jun 2017 23:57:02 +0200 Subject: [PATCH 19/24] changed constants for GxsTransport anti-spam --- libretroshare/src/gxstrans/p3gxstrans.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index a1d354fd2..cdd011450 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -1063,8 +1063,6 @@ bool p3GxsTrans::loadList(std::list&loadList) return true; } -// We should also include the message size! - bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_size) { // 1 - check the total size of the msgs for the author of this particular msg. @@ -1077,7 +1075,7 @@ bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_s // ------------+----------------------+------------------ // Negative | 0 | 0 // This is already handled by the anti-spam // R-Negative | 10 | 10k - // Neutral | 100 | 500k + // Neutral | 20 | 20k // R-Positive | 400 | 1M // Positive | 1000 | 2M @@ -1085,12 +1083,12 @@ bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_s // default values below used as backup. static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ; - static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 100 ; + static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 20 ; static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT = 400 ; static const uint32_t GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT = 1000 ; static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT = 10 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 512 * 1024 ; + static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 20 * 1024 ; static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT = 1024 * 1024 ; static const uint32_t GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT = 2 * 1024 * 1024 ; From eb4bb5be656a76ca167cbb0839fd137f836fa2a0 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 17 Jun 2017 21:42:00 +0200 Subject: [PATCH 20/24] fixed bug in gxs trans stats counting --- libretroshare/src/gxstrans/p3gxstrans.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index 5804c91cc..ec1fbaaba 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -390,6 +390,7 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() RS_STACK_MUTEX(mMtx) ; mMsgToDel = msgsToDel ; + total_message_size_and_count = totalMessageSizeAndCount; mDone = true; } @@ -407,6 +408,7 @@ void p3GxsTrans::service_tick() if(mLastMsgCleanup + MAX_DELAY_BETWEEN_CLEANUPS < now) { + RS_STACK_MUTEX(mPerUserStatsMutex); if(!mCleanupThread) mCleanupThread = new GxsTransIntegrityCleanupThread(getDataStore()); @@ -425,6 +427,7 @@ void p3GxsTrans::service_tick() if(mCleanupThread != NULL && mCleanupThread->isDone()) { + RS_STACK_MUTEX(mPerUserStatsMutex); GxsMsgReq msgToDel ; mCleanupThread->getMessagesToDelete(msgToDel) ; @@ -436,8 +439,14 @@ void p3GxsTrans::service_tick() deleteMsgs(token,msgToDel); } - RS_STACK_MUTEX(mPerUserStatsMutex); mCleanupThread->getPerUserStatistics(per_user_statistics) ; + + std::cerr << "p3GxsTrans: Got new set of per user statistics:"<< std::endl; + for(std::map::const_iterator it(per_user_statistics.begin());it!=per_user_statistics.end();++it) + std::cerr << " " << it->first << ": " << it->second.count << " " << it->second.size << std::endl; + + delete mCleanupThread; + mCleanupThread=NULL ; } { From 12a45294a3a5b17e1fd01772ad2e8288f10f50c3 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 17 Jun 2017 23:02:28 +0200 Subject: [PATCH 21/24] added ifdef for comments on GxsTrans --- libretroshare/src/gxstrans/p3gxstrans.cc | 98 ++++++++++++++++++++++-- libretroshare/src/gxstrans/p3gxstrans.h | 2 +- 2 files changed, 93 insertions(+), 7 deletions(-) diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index ec1fbaaba..48d60a1b8 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -20,11 +20,12 @@ #include "gxstrans/p3gxstrans.h" #include "util/stacktrace.h" +#define DEBUG_GXSTRANS 1 typedef unsigned int uint; RsGxsTrans *rsGxsTrans = NULL ; -const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 60; // every 20 mins. Could be less. +const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 900; // every 15 mins. Could be less. p3GxsTrans::~p3GxsTrans() { @@ -71,7 +72,9 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId, const uint8_t* data, uint32_t size, RsGxsTransEncryptionMode cm ) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::sendEmail(...)" << std::endl; +#endif if(!mIdService.isOwnId(own_gxsid)) { @@ -127,7 +130,9 @@ void p3GxsTrans::registerGxsTransClient( void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type << ")" << std::endl; +#endif bool changed = false ; switch (req_type) @@ -190,8 +195,10 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) * avoid to create yet another never used mail distribution group. */ +#ifdef DEBUG_GXSTRANS std::cerr << "p3GxsTrans::handleResponse(...) preferredGroupId.isNu" << "ll() let's create a new group." << std::endl; +#endif uint32_t token; publishGroup(token, new RsGxsTransGroupItem()); queueRequest(token, GROUP_CREATE); @@ -201,7 +208,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) } case GROUP_CREATE: { +#ifdef DEBUG_GXSTRANS std::cerr << "p3GxsTrans::handleResponse(...) GROUP_CREATE" << std::endl; +#endif RsGxsGroupId grpId; acknowledgeTokenGrp(token, grpId); supersedePreferredGroup(grpId); @@ -209,7 +218,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type) } case MAILS_UPDATE: { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::handleResponse(...) MAILS_UPDATE" << std::endl; +#endif typedef std::map > GxsMsgDataMap; GxsMsgDataMap gpMsgMap; getMsgData(token, gpMsgMap); @@ -302,7 +313,9 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() std::map grp; mDs->retrieveNxsGrps(grp, true, true); +#ifdef DEBUG_GXSTRANS std::cerr << "GxsTransIntegrityCleanupThread::run()" << std::endl; +#endif // compute hash and compare to stored value, if it fails then simply add it // to list @@ -347,13 +360,17 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() std::cerr << " Unrecocognised item type!" << std::endl; else if(NULL != (mitem = dynamic_cast(item))) { +#ifdef DEBUG_GXSTRANS std::cerr << " " << msg->metaData->mMsgId << ": Mail data with ID " << std::hex << std::setfill('0') << std::setw(16) << mitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl; +#endif stored_msgs[mitem->mailId] = std::make_pair(msg->metaData->mGroupId,msg->metaData->mMsgId) ; } else if(NULL != (pitem = dynamic_cast(item))) { +#ifdef DEBUG_GXSTRANS std::cerr << " " << msg->metaData->mMsgId << ": Signed rcpt of ID " << std::hex << pitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl; +#endif received_msgs.push_back(pitem->mailId) ; } @@ -370,11 +387,13 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() GxsMsgReq msgsToDel ; +#ifdef DEBUG_GXSTRANS std::cerr << "Msg removal report:" << std::endl; std::cerr << " Per user size and count: " << std::endl; for(std::map::const_iterator it(totalMessageSizeAndCount.begin());it!=totalMessageSizeAndCount.end();++it) std::cerr << " " << it->first << ": " << it->second.count << " messages, for a total size of " << it->second.size << " bytes." << std::endl; +#endif for(std::list::const_iterator it(received_msgs.begin());it!=received_msgs.end();++it) { @@ -384,7 +403,9 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run() { msgsToDel[it2->second.first].push_back(it2->second.second); +#ifdef DEBUG_GXSTRANS std::cerr << " scheduling msg " << std::hex << it2->second.first << "," << it2->second.second << " for deletion." << std::endl; +#endif } } @@ -416,7 +437,9 @@ void p3GxsTrans::service_tick() std::cerr << "Cleanup thread is already running. Not running it again!" << std::endl; else { +#ifdef DEBUG_GXSTRANS std::cerr << "Starting GxsIntegrity cleanup thread." << std::endl; +#endif mCleanupThread->start() ; mLastMsgCleanup = now ; @@ -434,16 +457,20 @@ void p3GxsTrans::service_tick() if(!msgToDel.empty()) { +#ifdef DEBUG_GXSTRANS std::cerr << "p3GxsTrans::service_tick(): deleting messages." << std::endl; +#endif uint32_t token ; deleteMsgs(token,msgToDel); } mCleanupThread->getPerUserStatistics(per_user_statistics) ; +#ifdef DEBUG_GXSTRANS std::cerr << "p3GxsTrans: Got new set of per user statistics:"<< std::endl; for(std::map::const_iterator it(per_user_statistics.begin());it!=per_user_statistics.end();++it) std::cerr << " " << it->first << ": " << it->second.count << " " << it->second.size << std::endl; +#endif delete mCleanupThread; mCleanupThread=NULL ; @@ -488,6 +515,7 @@ void p3GxsTrans::service_tick() } else { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::service_tick() " << "GXS_MAIL_SUBTYPE_MAIL handling: " << msg->meta.mMsgId @@ -497,6 +525,7 @@ void p3GxsTrans::service_tick() << " mailId: "<< msg->mailId << " payload.size(): " << msg->payload.size() << std::endl; +#endif handleEncryptedMail(msg); } break; @@ -547,14 +576,18 @@ void p3GxsTrans::service_tick() RsGenExchange::ServiceCreate_Return p3GxsTrans::service_CreateGroup( RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /*keySet*/ ) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::service_CreateGroup(...) " << grpItem->meta.mGroupId << std::endl; +#endif return SERVICE_CREATE_SUCCESS; } void p3GxsTrans::notifyChanges(std::vector& changes) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::notifyChanges(...)" << std::endl; +#endif for( std::vector::const_iterator it = changes.begin(); it != changes.end(); ++it ) { @@ -563,12 +596,16 @@ void p3GxsTrans::notifyChanges(std::vector& changes) if (grpChange) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::notifyChanges(...) grpChange" << std::endl; +#endif requestGroupsData(&(grpChange->mGrpIdList)); } else if(msgChange) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl; +#endif uint32_t token; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca, @@ -584,9 +621,11 @@ void p3GxsTrans::notifyChanges(std::vector& changes) for(itT vit = msgsIds.begin(); vit != msgsIds.end(); ++vit) { const RsGxsMessageId& msgId = *vit; +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::notifyChanges(...) got " << "notification for message " << msgId << " in group " << grpId << std::endl; +#endif } } } @@ -636,7 +675,9 @@ bool p3GxsTrans::requestGroupsData(const std::list* groupIds) bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::handleEcryptedMail(...)" << std::endl; +#endif std::set decryptIds; std::list ownIds; @@ -659,8 +700,11 @@ bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail) uint16_t csri = 0; uint32_t off = 0; getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri); + +#ifdef DEBUG_GXSTRANS std::cerr << "service: " << csri << " got CLEAR_TEXT mail!" << std::endl; +#endif /* As we cannot verify recipient without encryption, just pass the hint * as recipient */ return dispatchDecryptedMail( mail->meta.mAuthorId, mail->recipientHint, @@ -699,8 +743,10 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId, const uint8_t* decrypted_data, uint32_t decrypted_data_size ) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::dispatchDecryptedMail(, , " << decrypted_data_size << ")" << std::endl; +#endif uint16_t csri = 0; uint32_t offset = 0; @@ -726,8 +772,10 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId, << " wrong is happening!" << std::endl; return false; } +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt " << "with: msgId: " << receipt->msgId << std::endl; +#endif std::vector rcct; rcct.push_back(receipt); RsGenExchange::notifyNewMessages(rcct); @@ -872,6 +920,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) } case GxsTransSendStatus::PENDING_PUBLISH: { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::sendEmail(...) sending mail to: " << pr.recipient << " with cryptoType: " @@ -880,6 +929,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) << " receiptId: " << pr.mailItem.mailId << " payload size: " << pr.mailItem.payload.size() << std::endl; +#endif RsGxsTransMailItem *mail_item = new RsGxsTransMailItem(pr.mailItem); @@ -973,23 +1023,31 @@ RsSerialiser* p3GxsTrans::setupSerialiser() bool p3GxsTrans::saveList(bool &cleanup, std::list& saveList) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; +#endif mOutgoingMutex.lock(); mIngoingMutex.lock(); for ( auto& kv : mOutgoingQueue ) { +#ifdef DEBUG_GXSTRANS std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.group_id << ", TS=" << kv.second.sent_ts << std::endl; +#endif saveList.push_back(&kv.second); } for ( auto& kv : mIncomingQueue ) { +#ifdef DEBUG_GXSTRANS std::cerr << "Saving incoming item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::endl; +#endif saveList.push_back(kv.second); } +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; +#endif cleanup = false; return true; @@ -1003,9 +1061,11 @@ void p3GxsTrans::saveDone() bool p3GxsTrans::loadList(std::list&loadList) { +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; +#endif for(auto& v : loadList) switch(static_cast(v->PacketSubType())) @@ -1043,7 +1103,9 @@ bool p3GxsTrans::loadList(std::list&loadList) RS_STACK_MUTEX(mOutgoingMutex); mOutgoingQueue.insert(prMap::value_type(ot.mailItem.mailId, ot)); +#ifdef DEBUG_GXSTRANS std::cerr << "Loaded outgoing item (converted), ID " << std::hex << std::setfill('0') << std::setw(16) << ot.mailItem.mailId<< std::dec << ", Group id: " << ot.group_id << ", TS=" << ot.sent_ts << std::endl; +#endif } delete v; break; @@ -1058,7 +1120,9 @@ bool p3GxsTrans::loadList(std::list&loadList) mOutgoingQueue.insert( prMap::value_type(ot->mailItem.mailId, *ot)); +#ifdef DEBUG_GXSTRANS std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->group_id << ", TS=" << ot->sent_ts << std::endl; +#endif } delete v; break; @@ -1073,9 +1137,11 @@ bool p3GxsTrans::loadList(std::list&loadList) break; } +#ifdef DEBUG_GXSTRANS std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; +#endif return true; } @@ -1092,7 +1158,7 @@ bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_s // ------------+----------------------+------------------ // Negative | 0 | 0 // This is already handled by the anti-spam // R-Negative | 10 | 10k - // Neutral | 20 | 20k + // Neutral | 100 | 20k // R-Positive | 400 | 1M // Positive | 1000 | 2M @@ -1100,18 +1166,20 @@ bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_s // default values below used as backup. static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ; - static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 20 ; + static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 40 ; static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT = 400 ; static const uint32_t GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT = 1000 ; static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT = 10 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 20 * 1024 ; + static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 200 * 1024 ; static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT = 1024 * 1024 ; static const uint32_t GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT = 2 * 1024 * 1024 ; uint32_t max_count = 0 ; uint32_t max_size = 0 ; - RsReputations::ReputationLevel rep_lev = rsReputations->overallReputationLevel(msgMeta->mAuthorId); + uint32_t identity_flags = 0 ; + + RsReputations::ReputationLevel rep_lev = rsReputations->overallReputationLevel(msgMeta->mAuthorId,&identity_flags); switch(rep_lev) { @@ -1133,21 +1201,39 @@ bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_s break ; } + bool pgp_linked = identity_flags & RS_IDENTITY_FLAGS_PGP_LINKED ; + + if(rep_lev <= RsReputations::REPUTATION_NEUTRAL && !pgp_linked) + { + max_count /= 10 ; + max_size /= 10 ; + } + RS_STACK_MUTEX(mPerUserStatsMutex); MsgSizeCount& s(per_user_statistics[msgMeta->mAuthorId]) ; - std::cerr << "GxsTrans::acceptMessage(): size=" << msg_size << ", grp=" << msgMeta->mGroupId << ", gxs_id=" << msgMeta->mAuthorId << ", current (size,cnt)=(" +#ifdef DEBUG_GXSTRANS + std::cerr << "GxsTrans::acceptMessage(): size=" << msg_size << ", grp=" << msgMeta->mGroupId << ", gxs_id=" << msgMeta->mAuthorId << ", pgp_linked=" << pgp_linked << ", current (size,cnt)=(" << s.size << "," << s.count << ") reputation=" << rep_lev << ", limits=(" << max_size << "," << max_count << ") " ; +#endif if(s.size + msg_size > max_size || 1+s.count > max_count) { +#ifdef DEBUG_GXSTRANS std::cerr << "=> rejected." << std::endl; +#endif return false ; } else { +#ifdef DEBUG_GXSTRANS std::cerr << "=> accepted." << std::endl; +#endif + + s.count++ ; + s.size += msg_size ; // update the statistics, so that it's not possible to pass a bunch of msgs at once below the limits. + return true ; } } diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h index 3dd0a7567..1b029444a 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ b/libretroshare/src/gxstrans/p3gxstrans.h @@ -101,7 +101,7 @@ public: mIngoingMutex("p3GxsTrans ingoing queue map mutex"), mPerUserStatsMutex("p3GxsTrans user stats mutex") { - mLastMsgCleanup = time(NULL) - 60; // to be changed into 0 + mLastMsgCleanup = time(NULL) - MAX_DELAY_BETWEEN_CLEANUPS + 30; // always check 30 secs after start mCleanupThread = NULL ; } From b206015e7005a8368cde25724b50da520697c818 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Tue, 20 Jun 2017 15:33:28 +0200 Subject: [PATCH 22/24] libresapi: expose identity avatar in JSON API The avatar is sent as a base64 string The solution is not optimal but is the best we can do inside a JSON and it's acceptable for the moment --- libresapi/src/api/IdentityHandler.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 13332487a..6b7e1d05d 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include "Operators.h" @@ -500,6 +501,11 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp) RsIdentityDetails details; mRsIdentity->getIdDetails(RsGxsId(data.mMeta.mGroupId), details); + + std::string base64Avatar; + Radix64::encode(details.mAvatar.mData, details.mAvatar.mSize, base64Avatar); + resp.mDataStream << makeKeyValue("avatar", base64Avatar); + StreamBase& usagesStream = resp.mDataStream.getStreamToMember("usages"); usagesStream.getStreamToMember(); From 8c62c2a32632e693993d976be770180b45b28037 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Tue, 20 Jun 2017 15:35:05 +0200 Subject: [PATCH 23/24] Qml app: show contact avatar in details if available --- retroshare-qml-app/src/ContactDetails.qml | 70 ++++++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/retroshare-qml-app/src/ContactDetails.qml b/retroshare-qml-app/src/ContactDetails.qml index 7b7cfedf8..ff14ff338 100644 --- a/retroshare-qml-app/src/ContactDetails.qml +++ b/retroshare-qml-app/src/ContactDetails.qml @@ -26,22 +26,64 @@ Item id: cntDt property var md property bool is_contact: cntDt.md.is_contact + property bool has_avatar: false - ColorHash + property int avatarAttemptCnt: 0 + function getDetails() { - id: colorHash + ++cntDt.avatarAttemptCnt + rsApi.request( + "/identity/get_identity_details", + JSON.stringify({ gxs_id: cntDt.md.gxs_id }), + function(par) + { + var jData = JSON.parse(par.response).data + setDetails(jData) + if(!cntDt.has_avatar && avatarAttemptCnt < 3) + getDetails() + }) + } + function setDetails(data) + { + cntDt.has_avatar = data.avatar.length > 0 + if(cntDt.has_avatar) + { + contactAvatar.source = + "data:image/png;base64," + data.avatar + } + } + + Component.onCompleted: getDetails() + + Item + { + id: topFace + + height: 130 + width: 130 anchors.top: parent.top anchors.topMargin: 6 anchors.horizontalCenter: parent.horizontalCenter - height: 150 - hash: cntDt.md.gxs_id + Image + { + id: contactAvatar + anchors.fill: parent + visible: cntDt.has_avatar + } + + ColorHash + { + anchors.fill: parent + visible: !cntDt.has_avatar + hash: cntDt.md.gxs_id + } } Column { - anchors.top: colorHash.bottom + anchors.top: topFace.bottom anchors.topMargin: 6 anchors.horizontalCenter: parent.horizontalCenter @@ -61,7 +103,6 @@ Item Image { - source: cntDt.is_contact ? "qrc:/icons/rating.png" : "qrc:/icons/rating-unrated.png" @@ -86,10 +127,23 @@ Item } } - Text + Row { - text: "
"+cntDt.md.gxs_id+"
" + ColorHash + { + hash: cntDt.md.gxs_id + height: 30 + visible: cntDt.has_avatar + } + + Text + { + text: "
"+cntDt.md.gxs_id+"
" + y: 5 + } + anchors.horizontalCenter: parent.horizontalCenter + spacing: 5 } Text From 1d031910cb46ce73abd076748dd283d2bdf91907 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Tue, 20 Jun 2017 17:16:27 +0200 Subject: [PATCH 24/24] Created a dedicated component for avatar image --- retroshare-qml-app/src/AvatarOrColorHash.qml | 76 ++++++++++++++++++++ retroshare-qml-app/src/ContactDetails.qml | 71 +++--------------- retroshare-qml-app/src/qml.qrc | 1 + 3 files changed, 88 insertions(+), 60 deletions(-) create mode 100644 retroshare-qml-app/src/AvatarOrColorHash.qml diff --git a/retroshare-qml-app/src/AvatarOrColorHash.qml b/retroshare-qml-app/src/AvatarOrColorHash.qml new file mode 100644 index 000000000..0cf09a9c4 --- /dev/null +++ b/retroshare-qml-app/src/AvatarOrColorHash.qml @@ -0,0 +1,76 @@ +/* + * RetroShare Android QML App + * Copyright (C) 2017 Gioacchino Mazzurco + * + * 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 . + */ + +import QtQuick 2.7 + + +Item +{ + id: compRoot + + property string gxs_id + + height: 130 + width: height + + +////////////// The following should be considered privates ///////////////////// + + property bool has_avatar: false + property int avatarAttemptCnt: 0 + function getDetails() + { + ++compRoot.avatarAttemptCnt + rsApi.request( + "/identity/get_identity_details", + JSON.stringify({ gxs_id: compRoot.gxs_id }), + function(par) + { + var jData = JSON.parse(par.response).data + setDetails(jData) + if(!compRoot.has_avatar && + compRoot.avatarAttemptCnt < 3) getDetails() + }) + } + function setDetails(data) + { + compRoot.has_avatar = data.avatar.length > 0 + if(compRoot.has_avatar) + { + contactAvatar.source = + "data:image/png;base64," + data.avatar + } + } + + Component.onCompleted: if(visible && !has_avatar) getDetails() + onVisibleChanged: if(visible && !has_avatar) getDetails() + + Image + { + id: contactAvatar + anchors.fill: parent + visible: compRoot.has_avatar + } + + ColorHash + { + anchors.fill: parent + visible: !compRoot.has_avatar + hash: compRoot.gxs_id + } +} diff --git a/retroshare-qml-app/src/ContactDetails.qml b/retroshare-qml-app/src/ContactDetails.qml index ff14ff338..e66b267a9 100644 --- a/retroshare-qml-app/src/ContactDetails.qml +++ b/retroshare-qml-app/src/ContactDetails.qml @@ -26,59 +26,16 @@ Item id: cntDt property var md property bool is_contact: cntDt.md.is_contact - property bool has_avatar: false - property int avatarAttemptCnt: 0 - function getDetails() - { - ++cntDt.avatarAttemptCnt - rsApi.request( - "/identity/get_identity_details", - JSON.stringify({ gxs_id: cntDt.md.gxs_id }), - function(par) - { - var jData = JSON.parse(par.response).data - setDetails(jData) - if(!cntDt.has_avatar && avatarAttemptCnt < 3) - getDetails() - }) - } - function setDetails(data) - { - cntDt.has_avatar = data.avatar.length > 0 - if(cntDt.has_avatar) - { - contactAvatar.source = - "data:image/png;base64," + data.avatar - } - } - - Component.onCompleted: getDetails() - - Item + AvatarOrColorHash { id: topFace - height: 130 - width: 130 + gxs_id: cntDt.md.gxs_id anchors.top: parent.top anchors.topMargin: 6 anchors.horizontalCenter: parent.horizontalCenter - - Image - { - id: contactAvatar - anchors.fill: parent - visible: cntDt.has_avatar - } - - ColorHash - { - anchors.fill: parent - visible: !cntDt.has_avatar - hash: cntDt.md.gxs_id - } } Column @@ -95,6 +52,13 @@ Item anchors.horizontalCenter: parent.horizontalCenter spacing: 6 + ColorHash + { + hash: cntDt.md.gxs_id + height: parent.height - 10 + anchors.verticalCenter: parent.verticalCenter + } + Text { text: cntDt.md.name @@ -127,23 +91,10 @@ Item } } - Row + Text { - ColorHash - { - hash: cntDt.md.gxs_id - height: 30 - visible: cntDt.has_avatar - } - - Text - { - text: "
"+cntDt.md.gxs_id+"
" - y: 5 - } - + text: "
"+cntDt.md.gxs_id+"
" anchors.horizontalCenter: parent.horizontalCenter - spacing: 5 } Text diff --git a/retroshare-qml-app/src/qml.qrc b/retroshare-qml-app/src/qml.qrc index 3859fde54..61bcfd8d1 100644 --- a/retroshare-qml-app/src/qml.qrc +++ b/retroshare-qml-app/src/qml.qrc @@ -29,5 +29,6 @@ icons/rating-unrated.png icons/rating.png TimedPopup.qml + AvatarOrColorHash.qml