Merge upstream

This commit is contained in:
hunbernd 2020-01-22 00:16:41 +01:00
commit b3ac3d58a9
67 changed files with 891 additions and 878 deletions

View File

@ -111,6 +111,7 @@ p3discovery2::p3discovery2(
if(rsEvents) if(rsEvents)
rsEvents->registerEventsHandler( rsEvents->registerEventsHandler(
RsEventType::GOSSIP_DISCOVERY,
[this](std::shared_ptr<const RsEvent> event) [this](std::shared_ptr<const RsEvent> event)
{ {
rsEventsHandler(*event); rsEventsHandler(*event);
@ -1345,8 +1346,3 @@ void p3discovery2::rsEventsHandler(const RsEvent& event)
// //
// /* ignore other operations */ // /* ignore other operations */
// } // }
// (cyril) do we still need this??
RsGossipDiscoveryFriendInviteReceivedEvent::RsGossipDiscoveryFriendInviteReceivedEvent(const std::string& invite) :
RsEvent(RsEventType::GOSSIP_DISCOVERY_INVITE_RECEIVED),
mInvite(invite) {}

View File

@ -108,7 +108,7 @@ void RsGRouterGenericDataItem::serial_process(RsGenericSerializer::SerializeJob
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,signature,"signature") ; RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,signature,"signature") ;
RsTypeSerializer::serial_process<uint32_t>(j,ctx,duplication_factor,"duplication_factor") ; RsTypeSerializer::serial_process<uint32_t>(j,ctx,duplication_factor,"duplication_factor") ;
RsTypeSerializer::serial_process<uint32_t>(j,ctx,flags,"flags") ; RS_SERIAL_PROCESS(flags);
if(j == RsGenericSerializer::DESERIALIZE) // make sure the duplication factor is not altered by friends. In the worst case, the item will duplicate a bit more. if(j == RsGenericSerializer::DESERIALIZE) // make sure the duplication factor is not altered by friends. In the worst case, the item will duplicate a bit more.
{ {
@ -128,7 +128,7 @@ void RsGRouterGenericDataItem::serial_process(RsGenericSerializer::SerializeJob
void RsGRouterSignedReceiptItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) void RsGRouterSignedReceiptItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
{ {
RsTypeSerializer::serial_process<uint64_t> (j,ctx,routing_id,"routing_id") ; RsTypeSerializer::serial_process<uint64_t> (j,ctx,routing_id,"routing_id") ;
RsTypeSerializer::serial_process<uint32_t> (j,ctx,flags,"flags") ; RS_SERIAL_PROCESS(flags);
RsTypeSerializer::serial_process (j,ctx,destination_key,"destination_key") ; RsTypeSerializer::serial_process (j,ctx,destination_key,"destination_key") ;
RsTypeSerializer::serial_process<uint32_t> (j,ctx,service_id,"service_id") ; RsTypeSerializer::serial_process<uint32_t> (j,ctx,service_id,"service_id") ;
RsTypeSerializer::serial_process (j,ctx,data_hash,"data_hash") ; RsTypeSerializer::serial_process (j,ctx,data_hash,"data_hash") ;
@ -269,3 +269,4 @@ RsGRouterSignedReceiptItem *RsGRouterSignedReceiptItem::duplicate() const
return item ; return item ;
} }
RsGRouterAbstractMsgItem::~RsGRouterAbstractMsgItem() = default;

View File

@ -27,7 +27,7 @@
#include "serialiser/rstlvkeys.h" #include "serialiser/rstlvkeys.h"
#include "rsitems/rsserviceids.h" #include "rsitems/rsserviceids.h"
#include "retroshare/rstypes.h" #include "retroshare/rstypes.h"
#include "retroshare/rsflags.h"
#include "retroshare/rsgrouter.h" #include "retroshare/rsgrouter.h"
#include "groutermatrix.h" #include "groutermatrix.h"
@ -83,40 +83,59 @@ class RsGRouterNonCopyableObject
// and routing ID. Sub-items are responsible for providing the serialised data to be signed for // and routing ID. Sub-items are responsible for providing the serialised data to be signed for
// both signing and checking. // both signing and checking.
class RsGRouterAbstractMsgItem: public RsGRouterItem enum class RsGRouterItemFlags : uint32_t
{ {
public: NONE = 0x0,
explicit RsGRouterAbstractMsgItem(uint8_t pkt_subtype) : RsGRouterItem(pkt_subtype), flags(0) {} ENCRYPTED = 0x1,
virtual ~RsGRouterAbstractMsgItem() {} SERVICE_UNKNOWN = 0x2
};
RS_REGISTER_ENUM_FLAGS_TYPE(RsGRouterItemFlags)
struct RsGRouterAbstractMsgItem: RsGRouterItem
{
explicit RsGRouterAbstractMsgItem(uint8_t pkt_subtype):
RsGRouterItem(pkt_subtype), flags(RsGRouterItemFlags::NONE) {}
GRouterMsgPropagationId routing_id ; GRouterMsgPropagationId routing_id ;
GRouterKeyId destination_key ; GRouterKeyId destination_key ;
GRouterServiceId service_id ; GRouterServiceId service_id ;
RsTlvKeySignature signature ; // signs mid+destination_key+state RsTlvKeySignature signature ; // signs mid+destination_key+state
uint32_t flags ; // packet was delivered, not delivered, bounced, etc
/// packet was delivered, not delivered, bounced, etc
RsGRouterItemFlags flags;
~RsGRouterAbstractMsgItem();
}; };
class RsGRouterGenericDataItem: public RsGRouterAbstractMsgItem, public RsGRouterNonCopyableObject class RsGRouterGenericDataItem:
public RsGRouterAbstractMsgItem, public RsGRouterNonCopyableObject
{ {
public: public:
RsGRouterGenericDataItem() : RsGRouterAbstractMsgItem(RS_PKT_SUBTYPE_GROUTER_DATA), data_size(0), data_bytes(NULL), duplication_factor(0) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } RsGRouterGenericDataItem():
virtual ~RsGRouterGenericDataItem() { clear() ; } RsGRouterAbstractMsgItem(RS_PKT_SUBTYPE_GROUTER_DATA),
data_size(0), data_bytes(nullptr), duplication_factor(0)
{ setPriorityLevel(QOS_PRIORITY_RS_GROUTER); }
virtual void clear() virtual ~RsGRouterGenericDataItem() { clear(); }
{ virtual void clear()
free(data_bytes); {
data_bytes=NULL; free(data_bytes);
} data_bytes = nullptr;
}
virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); virtual void serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx );
RsGRouterGenericDataItem *duplicate() const ; RsGRouterGenericDataItem *duplicate() const;
// packet data /// packet data
// uint32_t data_size;
uint32_t data_size ; uint8_t* data_bytes;
uint8_t *data_bytes;
uint32_t duplication_factor ; // number of duplicates allowed. Should be capped at each de-serialise operation! /** number of duplicates allowed. Should be capped at each de-serialise
* operation! */
uint32_t duplication_factor;
}; };
class RsGRouterSignedReceiptItem: public RsGRouterAbstractMsgItem class RsGRouterSignedReceiptItem: public RsGRouterAbstractMsgItem

View File

@ -178,7 +178,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <unistd.h> #include <unistd.h>
#include <math.h> #include <cmath>
#include "util/rsrandom.h" #include "util/rsrandom.h"
#include "util/rsprint.h" #include "util/rsprint.h"
@ -188,7 +188,7 @@
#include "turtle/p3turtle.h" #include "turtle/p3turtle.h"
#include "gxs/rsgixs.h" #include "gxs/rsgixs.h"
#include "retroshare/rspeers.h" #include "retroshare/rspeers.h"
#include "util/cxx17retrocompat.h"
#include "p3grouter.h" #include "p3grouter.h"
#include "grouteritems.h" #include "grouteritems.h"
#include "groutertypes.h" #include "groutertypes.h"
@ -200,25 +200,18 @@
const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ; const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ;
p3GRouter::p3GRouter(p3ServiceControl *sc, RsGixs *is) p3GRouter::p3GRouter(p3ServiceControl *sc, RsGixs *is) :
: p3Service(), p3Config(), mServiceControl(sc), mTurtle(NULL), mGixs(is), grMtx("GRouter") p3Service(), p3Config(), mServiceControl(sc), mTurtle(nullptr), mGixs(is),
{ grMtx("GRouter"), _changed(false), _debug_enabled(true),
addSerialType(new RsGRouterSerialiser()) ; _last_autowash_time(0), _last_matrix_update_time(0),
_last_debug_output_time(0), _last_config_changed(0),
_last_autowash_time = 0 ; _random_salt(RsRandom::random_u64()),
_last_debug_output_time = 0 ; mMissingKeyQueueMtx("GRouterMissingKeyQueue")
_last_config_changed = 0 ; { addSerialType(new RsGRouterSerialiser()); }
_last_matrix_update_time = 0 ;
_debug_enabled = true ;
_random_salt = RSRandom::random_u64() ;
_changed = false ;
}
int p3GRouter::tick() int p3GRouter::tick()
{ {
rstime_t now = time(NULL) ; rstime_t now = time(nullptr);
// Sort incoming service data // Sort incoming service data
// //
@ -242,6 +235,41 @@ int p3GRouter::tick()
// //
handleTunnels() ; handleTunnels() ;
/* Handle items in mMissingKeyQueue */
if(now > mMissingKeyQueueCheckLastCheck + mMissingKeyQueueCheckEvery)
{
mMissingKeyQueueCheckLastCheck = now;
RS_STACK_MUTEX(mMissingKeyQueueMtx);
for(auto it = mMissingKeyQueue.begin(); it != mMissingKeyQueue.end();)
{
const RsGxsId& senderId = it->first->signature.keyId;
if(rsIdentity->isKnownId(senderId))
{
Dbg2() << __PRETTY_FUNCTION__ << " got key: " << senderId
<< " for item pending validation, calling item handler"
<< std::endl;
handleIncomingItem(it->first.get());
it = mMissingKeyQueue.erase(it);
}
else
{
Dbg3() << __PRETTY_FUNCTION__ << " requesting missing key: "
<< senderId << " to validate pending item" << std::endl;
/* At this point the network status may have varied a lot since
* we received the item, so we don't even know if the peer who
* forwarded the item is still online, moreover the fact that
* after specific request we haven't got the key yet suggests it
* is not a good route toward the key, so request it to all
* available peers */
rsIdentity->requestIdentity(senderId);
++it;
}
}
}
// Update routing matrix // Update routing matrix
// //
if(now > _last_matrix_update_time + RS_GROUTER_MATRIX_UPDATE_PERIOD) if(now > _last_matrix_update_time + RS_GROUTER_MATRIX_UPDATE_PERIOD)
@ -325,14 +353,12 @@ bool p3GRouter::unregisterKey(const RsGxsId& key_id,const GRouterServiceId& sid)
Sha1CheckSum hash = makeTunnelHash(key_id,sid) ; Sha1CheckSum hash = makeTunnelHash(key_id,sid) ;
std::map<Sha1CheckSum,GRouterPublishedKeyInfo>::iterator it = _owned_key_ids.find(hash) ; const auto it = _owned_key_ids.find(hash);
if(it == _owned_key_ids.end()) if(it == _owned_key_ids.end())
{ {
#ifdef GROUTER_DEBUG RsErr() << __PRETTY_FUNCTION__ << " key " << key_id << " not found."
std::cerr << "p3GRouter::unregisterKey(): key " << key_id << " not found." << std::endl; << std::endl;
#endif return false;
return false ;
} }
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
@ -479,7 +505,7 @@ void p3GRouter::handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem *t
#endif #endif
} }
void p3GRouter::receiveTurtleData(const RsTurtleGenericTunnelItem *gitem, const RsFileHash &/*hash*/, const RsPeerId &virtual_peer_id, RsTurtleGenericTunnelItem::Direction /*direction*/) void p3GRouter::receiveTurtleData(const RsTurtleGenericTunnelItem *gitem, const RsFileHash & hash, const RsPeerId &virtual_peer_id, RsTurtleGenericTunnelItem::Direction direction)
{ {
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << "p3GRouter::receiveTurtleData() " << std::endl; std::cerr << "p3GRouter::receiveTurtleData() " << std::endl;
@ -1304,7 +1330,7 @@ bool p3GRouter::locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTr
void p3GRouter::autoWash() void p3GRouter::autoWash()
{ {
bool items_deleted = false ; bool items_deleted = false ;
rstime_t now = time(NULL) ; rstime_t now = time(nullptr);
std::map<GRouterMsgPropagationId,std::pair<GRouterClientService *,RsGxsId> > failed_msgs ; std::map<GRouterMsgPropagationId,std::pair<GRouterClientService *,RsGxsId> > failed_msgs ;
@ -1395,9 +1421,22 @@ void p3GRouter::autoWash()
it->second.clear() ; it->second.clear() ;
_incoming_data_pipes.erase(it) ; _incoming_data_pipes.erase(it) ;
it = ittmp ; it = ittmp ;
} }
else else
++it ; ++it ;
/* Cleanup timed out items in mMissingKeyQueue */
mMissingKeyQueueMtx.lock();
while( mMissingKeyQueue.begin() != mMissingKeyQueue.end() &&
mMissingKeyQueue.front().second <= now )
{
RsWarn() << __PRETTY_FUNCTION__ << " Deleting timed out item from "
<< "unknown RsGxsId: "
<< mMissingKeyQueue.front().first->signature.keyId
<< std::endl;
mMissingKeyQueue.pop_front();
}
mMissingKeyQueueMtx.unlock();
} }
// Look into pending items. // Look into pending items.
@ -1492,27 +1531,31 @@ void p3GRouter::handleIncoming()
RsGRouterAbstractMsgItem *item = _incoming_items.front() ; RsGRouterAbstractMsgItem *item = _incoming_items.front() ;
_incoming_items.pop_front() ; _incoming_items.pop_front() ;
RsGRouterGenericDataItem *generic_data_item ; handleIncomingItem(item);
RsGRouterSignedReceiptItem *receipt_item ;
if(NULL != (generic_data_item = dynamic_cast<RsGRouterGenericDataItem*>(item)))
handleIncomingDataItem(generic_data_item) ;
else if(NULL != (receipt_item = dynamic_cast<RsGRouterSignedReceiptItem*>(item)))
handleIncomingReceiptItem(receipt_item) ;
else
std::cerr << "Item has unknown type (not data nor signed receipt). Dropping!" << std::endl;
delete item ; delete item ;
} }
} }
void p3GRouter::handleIncomingReceiptItem(RsGRouterSignedReceiptItem *receipt_item) void p3GRouter::handleIncomingItem(const RsGRouterAbstractMsgItem *item)
{
const RsGRouterGenericDataItem *generic_data_item ;
const RsGRouterSignedReceiptItem *receipt_item ;
if(NULL != (generic_data_item = dynamic_cast<const RsGRouterGenericDataItem*>(item)))
handleIncomingDataItem(generic_data_item) ;
else if(NULL != (receipt_item = dynamic_cast<const RsGRouterSignedReceiptItem*>(item)))
handleIncomingReceiptItem(receipt_item) ;
else
std::cerr << "Item has unknown type (not data nor signed receipt). Dropping!" << std::endl;
}
void p3GRouter::handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *receipt_item)
{ {
bool changed = false ; bool changed = false ;
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << "Handling incoming signed receipt item." << std::endl; std::cerr << "Handling incoming signed receipt item." << std::endl;
std::cerr << "Item content:" << std::endl; std::cerr << "Item content:" << std::endl;
receipt_item->print(std::cerr,2) ; const_cast<RsGRouterSignedReceiptItem*>(receipt_item)->print(std::cerr,2) ;
#endif #endif
RsGxsId signer_id ; RsGxsId signer_id ;
@ -1613,17 +1656,17 @@ void p3GRouter::handleIncomingReceiptItem(RsGRouterSignedReceiptItem *receipt_it
IndicateConfigChanged() ; IndicateConfigChanged() ;
} }
Sha1CheckSum p3GRouter::computeDataItemHash(RsGRouterGenericDataItem *data_item) Sha1CheckSum p3GRouter::computeDataItemHash(const RsGRouterGenericDataItem *data_item)
{ {
RsGRouterSerialiser signature_serializer(RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE | RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER); RsGRouterSerialiser signature_serializer(RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE | RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER);
uint32_t signed_data_size = signature_serializer.size(data_item); uint32_t signed_data_size = signature_serializer.size(const_cast<RsGRouterGenericDataItem*>(data_item));
uint32_t total_size = signed_data_size + data_item->signature.TlvSize() ; uint32_t total_size = signed_data_size + data_item->signature.TlvSize() ;
RsTemporaryMemory mem(total_size) ; RsTemporaryMemory mem(total_size) ;
uint32_t offset = 0 ; uint32_t offset = 0 ;
uint32_t tmp_size = total_size ; uint32_t tmp_size = total_size ;
signature_serializer.serialise(data_item,mem,&tmp_size) ; signature_serializer.serialise(const_cast<RsGRouterGenericDataItem*>(data_item),mem,&tmp_size) ;
if(tmp_size != signed_data_size) if(tmp_size != signed_data_size)
std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl; std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl;
@ -1637,12 +1680,12 @@ Sha1CheckSum p3GRouter::computeDataItemHash(RsGRouterGenericDataItem *data_item)
return RsDirUtil::sha1sum(mem,total_size) ; return RsDirUtil::sha1sum(mem,total_size) ;
} }
void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item) void p3GRouter::handleIncomingDataItem(const RsGRouterGenericDataItem *data_item)
{ {
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << "Handling incoming data item. " << std::endl; std::cerr << "Handling incoming data item. " << std::endl;
std::cerr << "Item content:" << std::endl; std::cerr << "Item content:" << std::endl;
data_item->print(std::cerr,2) ; const_cast<RsGRouterGenericDataItem*>(data_item)->print(std::cerr,2) ;
#endif #endif
// we find 3 things: // we find 3 things:
@ -1654,15 +1697,15 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
// Send a receipt? if A && B // Send a receipt? if A && B
// Notify client? if A && !C // Notify client? if A && !C
// //
GRouterClientService *client = NULL ; GRouterClientService *clientService = NULL ;
GRouterServiceId service_id = data_item->service_id ; GRouterServiceId service_id = data_item->service_id ;
RsGRouterSignedReceiptItem *receipt_item = NULL ; RsGRouterSignedReceiptItem *receipt_item = NULL ;
Sha1CheckSum item_hash = computeDataItemHash(data_item) ; Sha1CheckSum item_hash = computeDataItemHash(data_item) ;
bool item_is_already_known = false ; bool item_is_already_known = false ;
bool item_is_for_us = false ;
bool cache_has_changed = false ; bool cache_has_changed = false ;
bool item_is_for_us = _owned_key_ids.find( makeTunnelHash(data_item->destination_key,service_id) ) != _owned_key_ids.end() ;
// A - Find client and service ID from destination key. // A - Find client and service ID from destination key.
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
@ -1671,23 +1714,12 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
{ {
RS_STACK_MUTEX(grMtx) ; RS_STACK_MUTEX(grMtx) ;
std::map<GRouterServiceId,GRouterClientService*>::const_iterator its = _registered_services.find(service_id) ;
if(its == _registered_services.end())
{
std::cerr << " ERROR: client id " << service_id << " not registered. Consistency error." << std::endl;
return ;
}
client = its->second ;
// also check wether this item is for us or not // also check wether this item is for us or not
item_is_for_us = _owned_key_ids.find( makeTunnelHash(data_item->destination_key,service_id) ) != _owned_key_ids.end() ;
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << " item is " << (item_is_for_us?"":"not") << " for us." << std::endl; std::cerr << " item is " << (item_is_for_us?"":"not") << " for us." << std::endl;
#endif #endif
std::map<GRouterMsgPropagationId,GRouterRoutingInfo>::iterator it = _pending_messages.find(data_item->routing_id) ; auto it = _pending_messages.find(data_item->routing_id) ;
if(it != _pending_messages.end()) if(it != _pending_messages.end())
{ {
@ -1709,26 +1741,56 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
std::cerr << " item is new." << std::endl; std::cerr << " item is new." << std::endl;
#endif #endif
} }
if(!item_is_already_known)
{
uint32_t error_status ;
if(!verifySignedDataItem(data_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK,error_status)) // we should get proper flags out of this
{
switch(error_status)
{
case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE:
{
RS_STACK_MUTEX(mMissingKeyQueueMtx);
rstime_t timeout = time(nullptr) + mMissingKeyQueueEntryTimeout;
RsGxsId authorId = data_item->signature.keyId;
mMissingKeyQueue.push_back( std::make_pair(std::unique_ptr<RsGRouterGenericDataItem>(data_item->duplicate()), timeout) );
/* Do not request the missing key here to the peer which forwarded the item as verifySignedDataItem(...) does it already */
RsInfo() << __PRETTY_FUNCTION__ << " Received a message from unknown RsGxsId: " << authorId <<". Cannot verify signature yet, storing in mMissingKeyQueue for later processing. Timeout: " << timeout << std::endl;
return;
}
default:
RsWarn() << __PRETTY_FUNCTION__ << " item signature verification FAILED with: " << error_status << ", Dropping!" << std::endl;
return;
}
}
#ifdef GROUTER_DEBUG
else
std::cerr << " verifying item signature: CHECKED!" ;
#endif
}
// At this point, if item is already known, it is guarrantied to be identical to the stored item. // At this point, if item is already known, it is guarrantied to be identical to the stored item.
// If the item is for us, and not already known, check the signature and hash, and generate a signed receipt // If the item is for us, and not already known, check the signature and hash, and generate a signed receipt
if(item_is_for_us && !item_is_already_known) if(item_is_for_us && !item_is_already_known)
{ {
// Check that we actually have a registered service ready to accept this item. If not, drop it.
{
RS_STACK_MUTEX(grMtx) ;
auto its = _registered_services.find(service_id) ;
if(its != _registered_services.end())
clientService = its->second ;
}
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << " step B: item is for us and is new, so make sure it's authentic and create a receipt" << std::endl; std::cerr << " step B: item is for us and is new, so make sure it's authentic and create a receipt" << std::endl;
#endif
uint32_t error_status ;
if(!verifySignedDataItem(data_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK,error_status)) // we should get proper flags out of this
{
std::cerr << " verifying item signature: FAILED! Droping that item" ;
std::cerr << " You probably received a message from a person you don't have key." << std::endl;
std::cerr << " Signature key ID: " << data_item->signature.keyId << std::endl;
return ;
}
#ifdef GROUTER_DEBUG
else
std::cerr << " verifying item signature: CHECKED!" ;
#endif #endif
// No we need to send a signed receipt to the sender. // No we need to send a signed receipt to the sender.
@ -1737,7 +1799,13 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
receipt_item->service_id = data_item->service_id ; receipt_item->service_id = data_item->service_id ;
receipt_item->routing_id = data_item->routing_id ; receipt_item->routing_id = data_item->routing_id ;
receipt_item->destination_key = data_item->signature.keyId ; receipt_item->destination_key = data_item->signature.keyId ;
receipt_item->flags = 0 ; receipt_item->flags = RsGRouterItemFlags::NONE ;
if(!clientService)
{
receipt_item->flags = RsGRouterItemFlags::SERVICE_UNKNOWN;
RsWarn() << __PRETTY_FUNCTION__ << " got a message from: " << data_item->signature.keyId << " for an unkown service: " << data_item->service_id << " is your RetroShare version updated?" << std::endl;
}
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << " preparing signed receipt." << std::endl; std::cerr << " preparing signed receipt." << std::endl;
@ -1813,7 +1881,7 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
// if the item is for us and is not already known, notify the client. // if the item is for us and is not already known, notify the client.
if(item_is_for_us && !item_is_already_known) if(clientService && !item_is_already_known)
{ {
// compute the hash before decryption. // compute the hash before decryption.
@ -1835,9 +1903,9 @@ void p3GRouter::handleIncomingDataItem(RsGRouterGenericDataItem *data_item)
std::cerr << " notyfying client." << std::endl; std::cerr << " notyfying client." << std::endl;
#endif #endif
if(client->acceptDataFromPeer(decrypted_item->signature.keyId)) if(clientService->acceptDataFromPeer(decrypted_item->signature.keyId))
{ {
client->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size); clientService->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size);
decrypted_item->data_bytes = NULL ; decrypted_item->data_bytes = NULL ;
decrypted_item->data_size = 0 ; decrypted_item->data_size = 0 ;
@ -1871,7 +1939,7 @@ bool p3GRouter::locked_getLocallyRegisteredClientFromServiceId(const GRouterServ
return true ; return true ;
} }
void p3GRouter::addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) void p3GRouter::addRoutingClue(const RsGxsId& id, const RsPeerId& peer_id)
{ {
RS_STACK_MUTEX(grMtx) ; RS_STACK_MUTEX(grMtx) ;
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
@ -1890,7 +1958,7 @@ bool p3GRouter::registerClientService(const GRouterServiceId& id,GRouterClientSe
bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key)
{ {
assert(!(item->flags & RS_GROUTER_DATA_FLAGS_ENCRYPTED)) ; assert(!(item->flags & RsGRouterItemFlags::ENCRYPTED));
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << " Encrypting data for key " << destination_key << std::endl; std::cerr << " Encrypting data for key " << destination_key << std::endl;
@ -1915,7 +1983,7 @@ bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& de
free(item->data_bytes) ; free(item->data_bytes) ;
item->data_bytes = encrypted_data ; item->data_bytes = encrypted_data ;
item->data_size = encrypted_size ; item->data_size = encrypted_size ;
item->flags |= RS_GROUTER_DATA_FLAGS_ENCRYPTED ; item->flags |= RsGRouterItemFlags::ENCRYPTED;
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << " Encrypted size = " << encrypted_size << std::endl; std::cerr << " Encrypted size = " << encrypted_size << std::endl;
@ -1926,7 +1994,7 @@ return true ;
} }
bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item) bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item)
{ {
assert(item->flags & RS_GROUTER_DATA_FLAGS_ENCRYPTED) ; assert(!!(item->flags & RsGRouterItemFlags::ENCRYPTED));
#ifdef GROUTER_DEBUG #ifdef GROUTER_DEBUG
std::cerr << " decrypting data for key " << item->destination_key << std::endl; std::cerr << " decrypting data for key " << item->destination_key << std::endl;
@ -1952,7 +2020,7 @@ bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item)
free(item->data_bytes) ; free(item->data_bytes) ;
item->data_bytes = decrypted_data ; item->data_bytes = decrypted_data ;
item->data_size = decrypted_size ; item->data_size = decrypted_size ;
item->flags &= ~RS_GROUTER_DATA_FLAGS_ENCRYPTED ; item->flags &= ~RsGRouterItemFlags::ENCRYPTED;
return true ; return true ;
} }
@ -2010,56 +2078,62 @@ bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signi
return false ; return false ;
} }
} }
bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item,const RsIdentityUsage::UsageCode& info,uint32_t& error_status) bool p3GRouter::verifySignedDataItem(const RsGRouterAbstractMsgItem *item,const RsIdentityUsage::UsageCode& info,uint32_t& error_status)
{ {
try try
{ {
if( rsReputations->overallReputationLevel(item->signature.keyId) == if( rsReputations->overallReputationLevel(item->signature.keyId) ==
RsReputationLevel::LOCALLY_NEGATIVE ) RsReputationLevel::LOCALLY_NEGATIVE )
{ {
std::cerr << "(WW) received global router message from banned identity " << item->signature.keyId << ". Rejecting the message." << std::endl; RsWarn() << __PRETTY_FUNCTION__ << " received global router "
return false ; << "message from banned identity " << item->signature.keyId
} << ". Rejecting the message." << std::endl;
RsGRouterSerialiser signature_serializer(RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE | RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER); return false;
}
uint32_t data_size = signature_serializer.size(item) ; RsGRouterSerialiser signature_serializer(
RsTemporaryMemory data(data_size) ; RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE |
RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER );
uint32_t data_size = signature_serializer.size(const_cast<RsGRouterAbstractMsgItem*>(item)); // the const cast shouldn't be necessary if size() took a const.
RsTemporaryMemory data(data_size);
if(data == NULL) if(data == NULL)
throw std::runtime_error("Cannot allocate data.") ; throw std::runtime_error("Cannot allocate data.") ;
if(!signature_serializer.serialise(item,data,&data_size)) if(!signature_serializer.serialise(const_cast<RsGRouterAbstractMsgItem*>(item),data,&data_size))
throw std::runtime_error("Cannot serialise signed data.") ; throw std::runtime_error("Cannot serialise signed data.");
RsIdentityUsage use(RS_SERVICE_TYPE_GROUTER,info) ; RsIdentityUsage use(RS_SERVICE_TYPE_GROUTER,info);
if(!mGixs->validateData(data,data_size,item->signature,true,use, error_status)) if(!mGixs->validateData( data, data_size, item->signature, true, use, error_status ))
{ {
switch(error_status) switch(error_status)
{ {
case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE:
{ {
std::list<RsPeerId> peer_ids ; std::list<RsPeerId> peer_ids;
peer_ids.push_back(item->PeerId()) ; peer_ids.push_back(item->PeerId());
std::cerr << "(EE) Key for GXS Id " << item->signature.keyId << " is not available. Cannot verify. Asking key to peer " << item->PeerId() << std::endl;
mGixs->requestKey(item->signature.keyId,peer_ids,use) ; // request the key around
}
break ;
case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: std::cerr << "(EE) Signature mismatch. Spoofing/Corrupted/MITM?." << std::endl;
break ;
default: std::cerr << "(EE) Signature verification failed on GRouter message. Unknown error status: " << error_status << std::endl;
break ;
}
return false;
}
return true ; RsWarn() << __PRETTY_FUNCTION__ << " Key for GXS Id " << item->signature.keyId << " is not available. Cannot verify. Asking key to peer " << item->PeerId() << std::endl;
} mGixs->requestKey(item->signature.keyId,peer_ids,use);
catch(std::exception& e) }
{ break;
std::cerr << " signature verification failed. Error: " << e.what() << std::endl; case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH:
RsWarn() << __PRETTY_FUNCTION__ << " Signature mismatch. " << "Spoofing/Corrupted/MITM?." << std::endl;
break;
default:
RsErr() << __PRETTY_FUNCTION__ << " Signature verification failed on GRouter message. Unknown error status: " << error_status << std::endl;
break;
}
return false;
}
return true;
}
catch(std::exception& e)
{
RsErr() << __PRETTY_FUNCTION__ << " Failed. Error: " << e.what() << std::endl;
return false ; return false ;
} }
} }
@ -2093,7 +2167,7 @@ bool p3GRouter::cancel(GRouterMsgPropagationId mid)
return true ; return true ;
} }
bool p3GRouter::sendData(const RsGxsId& destination,const GRouterServiceId& client_id,const uint8_t *data, uint32_t data_size,const RsGxsId& signing_id, GRouterMsgPropagationId &propagation_id) bool p3GRouter::sendData( const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t* data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId&propagation_id )
{ {
// std::cerr << "GRouter currently disabled." << std::endl; // std::cerr << "GRouter currently disabled." << std::endl;
// return false; // return false;
@ -2127,7 +2201,7 @@ bool p3GRouter::sendData(const RsGxsId& destination,const GRouterServiceId& clie
data_item->duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ; data_item->duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ;
data_item->service_id = client_id ; data_item->service_id = client_id ;
data_item->destination_key = destination ; data_item->destination_key = destination ;
data_item->flags = 0 ; // this is unused for now. data_item->flags = RsGRouterItemFlags::NONE ; // this is unused for now.
// First, encrypt. // First, encrypt.
@ -2204,8 +2278,12 @@ return true ;
Sha1CheckSum p3GRouter::makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client) Sha1CheckSum p3GRouter::makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client)
{ {
assert( destination.SIZE_IN_BYTES == 16) ; static_assert( RsGxsId::SIZE_IN_BYTES == 16,
assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ; "This function breaks if RsGxsId size changes" );
static_assert( Sha1CheckSum::SIZE_IN_BYTES == 20,
"This function breaks if Sha1CheckSum size changes" );
static_assert( sizeof(client) == 4,
"This function breaks if client service id size changes" );
uint8_t bytes[20] ; uint8_t bytes[20] ;
memcpy(bytes,destination.toByteArray(),16) ; memcpy(bytes,destination.toByteArray(),16) ;

View File

@ -22,8 +22,8 @@
#pragma once #pragma once
#include <map> #include <map>
#include <queue>
#include <fstream> #include <fstream>
#include <list>
#include "retroshare/rsgrouter.h" #include "retroshare/rsgrouter.h"
#include "retroshare/rstypes.h" #include "retroshare/rstypes.h"
@ -33,15 +33,13 @@
#include "turtle/turtleclientservice.h" #include "turtle/turtleclientservice.h"
#include "services/p3service.h" #include "services/p3service.h"
#include "pqi/p3cfgmgr.h" #include "pqi/p3cfgmgr.h"
#include "util/rsdebug.h"
#include "groutertypes.h" #include "groutertypes.h"
#include "groutermatrix.h" #include "groutermatrix.h"
#include "grouteritems.h" #include "grouteritems.h"
// To be put in pqi/p3cfgmgr.h // To be put in pqi/p3cfgmgr.h
//
static const uint32_t CONFIG_TYPE_GROUTER = 0x0016 ; static const uint32_t CONFIG_TYPE_GROUTER = 0x0016 ;
static const uint32_t RS_GROUTER_DATA_FLAGS_ENCRYPTED = 0x0001 ;
class p3LinkMgr ; class p3LinkMgr ;
class p3turtle ; class p3turtle ;
@ -126,7 +124,8 @@ public:
// Routing clue collection methods // // Routing clue collection methods //
//===================================================// //===================================================//
virtual void addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) ; virtual void addRoutingClue(
const RsGxsId& id, const RsPeerId& peer_id) override;
//===================================================// //===================================================//
// Client/server request services // // Client/server request services //
@ -220,7 +219,7 @@ private:
void handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item); void handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item);
void handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem*) ; void handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem*) ;
static Sha1CheckSum computeDataItemHash(RsGRouterGenericDataItem *data_item); static Sha1CheckSum computeDataItemHash(const RsGRouterGenericDataItem *data_item);
std::ostream& grouter_debug() const std::ostream& grouter_debug() const
{ {
@ -238,8 +237,9 @@ private:
void handleIncoming() ; void handleIncoming() ;
void handleIncomingReceiptItem(RsGRouterSignedReceiptItem *receipt_item) ; void handleIncomingItem(const RsGRouterAbstractMsgItem *item);
void handleIncomingDataItem(RsGRouterGenericDataItem *data_item) ; void handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *receipt_item) ;
void handleIncomingDataItem(const RsGRouterGenericDataItem *data_item) ;
bool locked_getLocallyRegisteredClientFromServiceId(const GRouterServiceId& service_id,GRouterClientService *& client); bool locked_getLocallyRegisteredClientFromServiceId(const GRouterServiceId& service_id,GRouterClientService *& client);
@ -252,7 +252,7 @@ private:
// signs an item with the given key. // signs an item with the given key.
bool signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& id) ; bool signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& id) ;
bool verifySignedDataItem(RsGRouterAbstractMsgItem *item, const RsIdentityUsage::UsageCode &info, uint32_t &error_status) ; bool verifySignedDataItem(const RsGRouterAbstractMsgItem *item, const RsIdentityUsage::UsageCode &info, uint32_t &error_status) ;
bool encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) ; bool encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) ;
bool decryptDataItem(RsGRouterGenericDataItem *item) ; bool decryptDataItem(RsGRouterGenericDataItem *item) ;
@ -352,4 +352,23 @@ private:
rstime_t _last_config_changed ; rstime_t _last_config_changed ;
uint64_t _random_salt ; uint64_t _random_salt ;
/** Temporarly store items that could not have been verified yet due to
* missing author key, attempt to handle them once in a while.
* The items are discarded if after mMissingKeyQueueEntryTimeout the key
* hasn't been received yet, and are not saved on RetroShare stopping. */
std::list< std::pair<
std::unique_ptr<RsGRouterAbstractMsgItem>, rstime_t > > mMissingKeyQueue;
RsMutex mMissingKeyQueueMtx; /// protect mMissingKeyQueue
/// @see mMissingKeyQueue
static constexpr rstime_t mMissingKeyQueueEntryTimeout = 600;
/// @see mMissingKeyQueue
static constexpr rstime_t mMissingKeyQueueCheckEvery = 30;
/// @see mMissingKeyQueue
rstime_t mMissingKeyQueueCheckLastCheck = 0;
RS_SET_CONTEXT_DEBUG_LEVEL(2)
}; };

View File

@ -331,6 +331,15 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
rsEvents, "rsEvents", cAns, session ) ) rsEvents, "rsEvents", cAns, session ) )
return; return;
RsEventType eventType = RsEventType::NONE;
// deserialize input parameters from JSON
{
RsGenericSerializer::SerializeContext& ctx(cReq);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);
RS_SERIAL_PROCESS(eventType);
}
const std::weak_ptr<rb::Session> weakSession(session); const std::weak_ptr<rb::Session> weakSession(session);
RsEventsHandlerId_t hId = rsEvents->generateUniqueHandlerId(); RsEventsHandlerId_t hId = rsEvents->generateUniqueHandlerId();
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback = std::function<void(std::shared_ptr<const RsEvent>)> multiCallback =
@ -365,7 +374,7 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
} ); } );
}; };
bool retval = rsEvents->registerEventsHandler(multiCallback, hId); bool retval = rsEvents->registerEventsHandler(eventType,multiCallback, hId);
{ {
RsGenericSerializer::SerializeContext& ctx(cAns); RsGenericSerializer::SerializeContext& ctx(cAns);

View File

@ -71,23 +71,32 @@ struct RsBroadcastDiscoveryResult : RsSerializable
* @brief Event emitted when a non friend new peer is found in the local network * @brief Event emitted when a non friend new peer is found in the local network
* @see RsEvents * @see RsEvents
*/ */
struct RsBroadcastDiscoveryPeerFoundEvent : RsEvent enum class RsBroadcastDiscoveryEventType: uint32_t {
{ UNKNOWN = 0x00,
RsBroadcastDiscoveryPeerFoundEvent( PEER_FOUND = 0x01
const RsBroadcastDiscoveryResult& eventData ) : };
RsEvent(RsEventType::BROADCAST_DISCOVERY_PEER_FOUND), mData(eventData) {}
RsBroadcastDiscoveryResult mData; struct RsBroadcastDiscoveryEvent : RsEvent
{
RsBroadcastDiscoveryEvent()
: RsEvent(RsEventType::BROADCAST_DISCOVERY),
mDiscoveryEventType(RsBroadcastDiscoveryEventType::UNKNOWN)
{}
virtual ~RsBroadcastDiscoveryEvent() override = default;
RsBroadcastDiscoveryEventType mDiscoveryEventType;
RsBroadcastDiscoveryResult mData;
/// @see RsSerializable /// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j, void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx) override RsGenericSerializer::SerializeContext& ctx) override
{ {
RsEvent::serial_process(j, ctx); RsEvent::serial_process(j, ctx);
RS_SERIAL_PROCESS(mDiscoveryEventType);
RS_SERIAL_PROCESS(mData); RS_SERIAL_PROCESS(mData);
} }
~RsBroadcastDiscoveryPeerFoundEvent() override;
}; };

View File

@ -53,10 +53,10 @@ enum class RsEventType : uint32_t
NONE = 0, /// Used to detect uninitialized event NONE = 0, /// Used to detect uninitialized event
/// @see RsBroadcastDiscovery /// @see RsBroadcastDiscovery
BROADCAST_DISCOVERY_PEER_FOUND = 1, BROADCAST_DISCOVERY = 1,
/// @see RsDiscPendingPgpReceivedEvent /// @see RsDiscPendingPgpReceivedEvent
GOSSIP_DISCOVERY_INVITE_RECEIVED = 2, GOSSIP_DISCOVERY = 2,
/// @see AuthSSL /// @see AuthSSL
AUTHSSL_CONNECTION_AUTENTICATION = 3, AUTHSSL_CONNECTION_AUTENTICATION = 3,
@ -64,14 +64,14 @@ enum class RsEventType : uint32_t
/// @see pqissl /// @see pqissl
PEER_CONNECTION = 4, PEER_CONNECTION = 4,
/// @see RsGxsChanges /// @see RsGxsChanges // this one is used in RsGxsBroadcast
GXS_CHANGES = 5, GXS_CHANGES = 5,
/// Emitted when a peer state changes, @see RsPeers /// Emitted when a peer state changes, @see RsPeers
PEER_STATE_CHANGED = 6, PEER_STATE_CHANGED = 6,
/// @see RsMailStatusEvent /// @see RsMailStatusEvent
MAIL_STATUS_CHANGE = 7, MAIL_STATUS = 7,
/// @see RsGxsCircleEvent /// @see RsGxsCircleEvent
GXS_CIRCLES = 8, GXS_CIRCLES = 8,
@ -163,6 +163,7 @@ public:
* Every time an event is dispatced the registered events handlers will get * Every time an event is dispatced the registered events handlers will get
* their method handleEvent called with the event passed as paramether. * their method handleEvent called with the event passed as paramether.
* @jsonapi{development,manualwrapper} * @jsonapi{development,manualwrapper}
* @param eventType Type of event for which the callback is called
* @param multiCallback Function that will be called each time an event * @param multiCallback Function that will be called each time an event
* is dispatched. * is dispatched.
* @param[inout] hId Optional storage for handler id, useful to * @param[inout] hId Optional storage for handler id, useful to
@ -173,6 +174,7 @@ public:
* @return False on error, true otherwise. * @return False on error, true otherwise.
*/ */
virtual bool registerEventsHandler( virtual bool registerEventsHandler(
RsEventType eventType,
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback, std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0) RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
) = 0; ) = 0;

View File

@ -45,11 +45,18 @@ extern std::shared_ptr<RsGossipDiscovery> rsGossipDiscovery;
/** /**
* @brief Emitted when a pending PGP certificate is received * @brief Emitted when a pending PGP certificate is received
*/ */
struct RsGossipDiscoveryFriendInviteReceivedEvent : RsEvent
{
RsGossipDiscoveryFriendInviteReceivedEvent(
const std::string& invite );
enum class RsGossipDiscoveryEventType: uint32_t {
UNKNOWN = 0x00,
PEER_INVITE_RECEIVED = 0x01
};
struct RsGossipDiscoveryEvent : RsEvent
{
RsGossipDiscoveryEvent(): RsEvent(RsEventType::GOSSIP_DISCOVERY) {}
virtual ~RsGossipDiscoveryEvent() override {}
RsGossipDiscoveryEventType mGossipDiscoveryEventType;
std::string mInvite; std::string mInvite;
/// @see RsSerializable /// @see RsSerializable
@ -57,6 +64,7 @@ struct RsGossipDiscoveryFriendInviteReceivedEvent : RsEvent
RsGenericSerializer::SerializeContext& ctx ) RsGenericSerializer::SerializeContext& ctx )
{ {
RsEvent::serial_process(j,ctx); RsEvent::serial_process(j,ctx);
RS_SERIAL_PROCESS(mGossipDiscoveryEventType);
RS_SERIAL_PROCESS(mInvite); RS_SERIAL_PROCESS(mInvite);
} }
}; };

View File

@ -19,12 +19,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * * along with this program. If not, see <https://www.gnu.org/licenses/>. *
* * * *
*******************************************************************************/ *******************************************************************************/
#pragma once #pragma once
#include "util/rsdir.h" #include "util/rsdir.h"
#include "util/rsdeprecate.h"
#include "retroshare/rsids.h" #include "retroshare/rsids.h"
#include "retroshare/rsgxsifacetypes.h" #include "retroshare/rsgxsifacetypes.h"
#include "rsitems/rsserviceids.h"
typedef RsGxsId GRouterKeyId ; // we use SSLIds, so that it's easier in the GUI to mix up peer ids with grouter ids. typedef RsGxsId GRouterKeyId ; // we use SSLIds, so that it's easier in the GUI to mix up peer ids with grouter ids.
typedef uint32_t GRouterServiceId ; typedef uint32_t GRouterServiceId ;

View File

@ -511,9 +511,13 @@ struct RsIdentity : RsGxsIfaceHelper
* @brief request details of a not yet known identity to the network * @brief request details of a not yet known identity to the network
* @jsonapi{development} * @jsonapi{development}
* @param[in] id id of the identity to request * @param[in] id id of the identity to request
* @param[in] peers optional list of the peers to ask for the key, if empty
* all online peers are asked.
* @return false on error, true otherwise * @return false on error, true otherwise
*/ */
virtual bool requestIdentity(const RsGxsId& id) = 0; virtual bool requestIdentity(
const RsGxsId& id,
const std::vector<RsPeerId>& peers = std::vector<RsPeerId>() ) = 0;
/// default base URL used for indentity links @see exportIdentityLink /// default base URL used for indentity links @see exportIdentityLink
static const std::string DEFAULT_IDENTITY_BASE_URL; static const std::string DEFAULT_IDENTITY_BASE_URL;

View File

@ -296,7 +296,6 @@ struct MsgTagType : RsSerializable
} //namespace Rs } //namespace Rs
} //namespace Msgs } //namespace Msgs
enum class RsMailStatusEventCode: uint8_t enum class RsMailStatusEventCode: uint8_t
{ {
NEW_MESSAGE = 0x00, NEW_MESSAGE = 0x00,
@ -312,9 +311,9 @@ enum class RsMailStatusEventCode: uint8_t
struct RsMailStatusEvent : RsEvent struct RsMailStatusEvent : RsEvent
{ {
RsMailStatusEvent() : RsEvent(RsEventType::MAIL_STATUS_CHANGE) {} RsMailStatusEvent() : RsEvent(RsEventType::MAIL_STATUS) {}
RsMailStatusEventCode mMailStatusEventCode; RsMailStatusEventCode mMailStatusEventCode;
std::set<RsMailMessageId> mChangedMsgIds; std::set<RsMailMessageId> mChangedMsgIds;
/// @see RsEvent /// @see RsEvent
@ -326,7 +325,7 @@ struct RsMailStatusEvent : RsEvent
RS_SERIAL_PROCESS(mMailStatusEventCode); RS_SERIAL_PROCESS(mMailStatusEventCode);
} }
~RsMailStatusEvent() override; ~RsMailStatusEvent() override = default;
}; };
#define RS_CHAT_PUBLIC 0x0001 #define RS_CHAT_PUBLIC 0x0001
@ -335,7 +334,7 @@ struct RsMailStatusEvent : RsEvent
#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000 #define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000
#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001 #define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001
#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0002 #define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0002
#define RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED 0x0003 #define RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED 0x0003
#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000 #define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000

View File

@ -33,8 +33,8 @@ void RsGxsPostedPostItem::serial_process(RsGenericSerializer::SerializeJob j,RsG
// and do not expect to deserialize mImage member if the data block has been consummed entirely (keeps compatibility // and do not expect to deserialize mImage member if the data block has been consummed entirely (keeps compatibility
// of new RS with older posts. // of new RS with older posts.
if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize)
return ; return ;
if((j == RsGenericSerializer::SIZE_ESTIMATE || j == RsGenericSerializer::SERIALIZE) && mImage.empty()) if((j == RsGenericSerializer::SIZE_ESTIMATE || j == RsGenericSerializer::SERIALIZE) && mImage.empty())
return ; return ;

View File

@ -538,8 +538,7 @@ bool p3Msgs::initiateDistantChatConnexion(
const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id,
DistantChatPeerId& pid, uint32_t& error_code, bool notify ) DistantChatPeerId& pid, uint32_t& error_code, bool notify )
{ {
return mChatSrv->initiateDistantChatConnexion( to_gxs_id, from_gxs_id, return mChatSrv->initiateDistantChatConnexion( to_gxs_id, from_gxs_id, pid, error_code, notify );
pid, error_code, notify );
} }
bool p3Msgs::getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info) bool p3Msgs::getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)
{ {
@ -559,7 +558,6 @@ uint32_t p3Msgs::getDistantChatPermissionFlags()
} }
RsMsgs::~RsMsgs() = default; RsMsgs::~RsMsgs() = default;
RsMailStatusEvent::~RsMailStatusEvent() = default;
Rs::Msgs::MessageInfo::~MessageInfo() = default; Rs::Msgs::MessageInfo::~MessageInfo() = default;
MsgInfoSummary::~MsgInfoSummary() = default; MsgInfoSummary::~MsgInfoSummary() = default;
VisibleChatLobbyRecord::~VisibleChatLobbyRecord() = default; VisibleChatLobbyRecord::~VisibleChatLobbyRecord() = default;

View File

@ -297,6 +297,7 @@ int RsInit::InitRetroShare(const RsConfigOptions& conf)
rsInitConfig->inet = conf.forcedInetAddress ; rsInitConfig->inet = conf.forcedInetAddress ;
rsInitConfig->port = conf.forcedPort ; rsInitConfig->port = conf.forcedPort ;
rsInitConfig->debugLevel = conf.debugLevel; rsInitConfig->debugLevel = conf.debugLevel;
rsInitConfig->udpListenerOnly = conf.udpListenerOnly;
rsInitConfig->optBaseDir = conf.optBaseDir; rsInitConfig->optBaseDir = conf.optBaseDir;
rsInitConfig->jsonApiPort = conf.jsonApiPort; rsInitConfig->jsonApiPort = conf.jsonApiPort;
rsInitConfig->jsonApiBindAddress = conf.jsonApiBindAddress; rsInitConfig->jsonApiBindAddress = conf.jsonApiBindAddress;

View File

@ -182,10 +182,15 @@ void BroadcastDiscoveryService::threadTick()
} }
else if(!isFriend) else if(!isFriend)
{ {
typedef RsBroadcastDiscoveryPeerFoundEvent Evt_t;
if(rsEvents) if(rsEvents)
rsEvents->postEvent( {
std::shared_ptr<Evt_t>(new Evt_t(rbdr)) ); auto ev = std::make_shared<RsBroadcastDiscoveryEvent>();
ev->mDiscoveryEventType = RsBroadcastDiscoveryEventType::PEER_FOUND;
ev->mData = rbdr;
rsEvents->postEvent(ev);
}
} }
} }
} }
@ -307,5 +312,4 @@ bool BroadcastDiscoveryService::assertMulticastLockIsvalid()
RsBroadcastDiscovery::~RsBroadcastDiscovery() = default; RsBroadcastDiscovery::~RsBroadcastDiscovery() = default;
RsBroadcastDiscoveryResult::~RsBroadcastDiscoveryResult() = default; RsBroadcastDiscoveryResult::~RsBroadcastDiscoveryResult() = default;
RsBroadcastDiscoveryPeerFoundEvent::~RsBroadcastDiscoveryPeerFoundEvent() = default;
BroadcastDiscoveryPack::~BroadcastDiscoveryPack() = default; BroadcastDiscoveryPack::~BroadcastDiscoveryPack() = default;

View File

@ -1163,92 +1163,89 @@ bool p3IdService::havePrivateKey(const RsGxsId &id)
if(! isOwnId(id)) if(! isOwnId(id))
return false ; return false ;
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mIdMtx);
return mKeyCache.is_cached(id) ; return mKeyCache.is_cached(id);
} }
static void mergeIds(std::map<RsGxsId,std::list<RsPeerId> >& idmap,const RsGxsId& id,const std::list<RsPeerId>& peers) static void mergeIds(std::map<RsGxsId,std::list<RsPeerId> >& idmap,const RsGxsId& id,const std::list<RsPeerId>& peers)
{ {
// merge the two lists (I use a std::set to make it more efficient) /* merge the two lists, use std::set to avoid duplicates efficiently */
#ifdef DEBUG_IDS
std::cerr << "p3IdService::requestKey(): merging list with existing pending request." << std::endl;
#endif
std::list<RsPeerId>& old_peers(idmap[id]) ; // create if necessary std::set<RsPeerId> new_peers(std::begin(peers), std::end(peers));
std::set<RsPeerId> new_peers ;
for(std::list<RsPeerId>::const_iterator it(peers.begin());it!=peers.end();++it) std::list<RsPeerId>& stored_peers(idmap[id]);
new_peers.insert(*it) ; std::copy( std::begin(stored_peers), std::end(stored_peers),
std::inserter(new_peers, std::begin(new_peers)) );
for(std::list<RsPeerId>::iterator it(old_peers.begin());it!=old_peers.end();++it) stored_peers.clear();
new_peers.insert(*it) ; std::copy( std::begin(new_peers), std::end(new_peers),
std::inserter(stored_peers, std::begin(stored_peers)) );
old_peers.clear();
for(std::set<RsPeerId>::iterator it(new_peers.begin());it!=new_peers.end();++it)
old_peers.push_back(*it) ;
} }
bool p3IdService::requestIdentity(const RsGxsId& id) bool p3IdService::requestIdentity(
const RsGxsId& id, const std::vector<RsPeerId>& peers )
{ {
std::list<RsPeerId> askPeersList(peers.begin(), peers.end());
// Empty list passed? Ask to all online peers.
if(askPeersList.empty()) rsPeers->getOnlineList(askPeersList);
if(askPeersList.empty()) // Still empty? Fail!
{
RsErr() << __PRETTY_FUNCTION__ << " failure retrieving peers list"
<< std::endl;
return false;
}
RsIdentityUsage usageInfo( RsServiceType::GXSID, RsIdentityUsage usageInfo( RsServiceType::GXSID,
RsIdentityUsage::IDENTITY_DATA_UPDATE ); RsIdentityUsage::IDENTITY_DATA_UPDATE );
std::list<RsPeerId> onlinePeers;
return rsPeers && rsPeers->getOnlineList(onlinePeers) return requestKey(id, askPeersList, usageInfo);
&& requestKey(id, onlinePeers, usageInfo);
} }
bool p3IdService::requestKey(const RsGxsId &id, const std::list<RsPeerId>& peers,const RsIdentityUsage& use_info) bool p3IdService::requestKey(const RsGxsId &id, const std::list<RsPeerId>& peers,const RsIdentityUsage& use_info)
{ {
if(id.isNull()) Dbg3() << __PRETTY_FUNCTION__ << " id: " << id << std::endl;
{
std::cerr << "(EE) nul ID requested to p3IdService. This should not happen. Callstack:" << std::endl;
print_stacktrace();
return false ;
}
if (haveKey(id)) if(id.isNull())
return true; {
else RsErr() << __PRETTY_FUNCTION__ << " cannot request null id"
{ << std::endl;
// Normally we should call getIdDetails(), but since the key is not known, we need to digg a possibly old information return false;
// from the reputation system, which keeps its own list of banned keys. Of course, the owner ID is not known at this point. }
#ifdef DEBUG_IDS if(peers.empty())
std::cerr << "p3IdService::requesting key " << id <<std::endl; {
#endif RsErr() << __PRETTY_FUNCTION__ << " cannot request id: " << id
<< " to empty lists of peers" << std::endl;
return false;
}
RsReputationInfo info; if(isKnownId(id)) return true;
rsReputations->getReputationInfo(id,RsPgpId(),info) ;
if( info.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE ) /* Normally we should call getIdDetails(), but since the key is not known,
{ * we need to dig a possibly old information from the reputation system,
std::cerr << "(II) not requesting Key " << id << " because it has been banned." << std::endl; * which keeps its own list of banned keys.
* Of course, the owner ID is not known at this point.c*/
{ RsReputationInfo info;
RS_STACK_MUTEX(mIdMtx); /********** STACK LOCKED MTX ******/ rsReputations->getReputationInfo(id, RsPgpId(), info);
mIdsNotPresent.erase(id) ;
}
return true;
}
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ if( info.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE )
{
RsInfo() << __PRETTY_FUNCTION__ << " not requesting Key " << id
<< " because it has been banned." << std::endl;
std::map<RsGxsId,std::list<RsPeerId> >::iterator rit = mIdsNotPresent.find(id) ; RS_STACK_MUTEX(mIdMtx);
mIdsNotPresent.erase(id);
if(rit != mIdsNotPresent.end()) return false;
{ }
if(!peers.empty())
mergeIds(mIdsNotPresent,id,peers) ;
return true ; {
} RS_STACK_MUTEX(mIdMtx);
} mergeIds(mIdsNotPresent, id, peers);
{ mKeysTS[id].usage_map[use_info] = time(nullptr);
RS_STACK_MUTEX(mIdMtx); /********** STACK LOCKED MTX ******/ }
mKeysTS[id].usage_map[use_info] = time(NULL) ;
}
return cache_request_load(id, peers); return cache_request_load(id, peers);
} }
@ -2772,34 +2769,30 @@ bool p3IdService::cache_store(const RsGxsIdGroupItem *item)
bool p3IdService::cache_request_load(const RsGxsId &id, const std::list<RsPeerId> &peers) bool p3IdService::cache_request_load(const RsGxsId &id, const std::list<RsPeerId> &peers)
{ {
#ifdef DEBUG_IDS Dbg4() << __PRETTY_FUNCTION__ << " id: " << id << std::endl;
std::cerr << "p3IdService::cache_request_load(" << id << ")" << std::endl;
#endif // DEBUG_IDS
{ {
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mIdMtx);
// merge, even if peers is empty
mergeIds(mCacheLoad_ToCache, id, peers);
}
mergeIds(mCacheLoad_ToCache,id,peers) ; // merge, even if peers is empty if(RsTickEvent::event_count(GXSID_EVENT_CACHELOAD) > 0)
} {
Dbg3() << __PRETTY_FUNCTION__ << " cache reload already scheduled "
<< "skipping" << std::endl;
return true;
}
if (RsTickEvent::event_count(GXSID_EVENT_CACHELOAD) > 0) int32_t age = 0;
{ if( RsTickEvent::prev_event_ago(GXSID_EVENT_CACHELOAD, age) && age < MIN_CYCLE_GAP )
/* its already scheduled */ {
return true; RsTickEvent::schedule_in(GXSID_EVENT_CACHELOAD, MIN_CYCLE_GAP - age);
} return true;
}
int32_t age = 0; RsTickEvent::schedule_now(GXSID_EVENT_CACHELOAD);
if (RsTickEvent::prev_event_ago(GXSID_EVENT_CACHELOAD, age)) return true;
{
if (age < MIN_CYCLE_GAP)
{
RsTickEvent::schedule_in(GXSID_EVENT_CACHELOAD, MIN_CYCLE_GAP - age);
return true;
}
}
RsTickEvent::schedule_now(GXSID_EVENT_CACHELOAD);
return true;
} }
@ -2923,71 +2916,88 @@ bool p3IdService::cache_load_for_token(uint32_t token)
void p3IdService::requestIdsFromNet() void p3IdService::requestIdsFromNet()
{ {
RsStackMutex stack(mIdMtx); RS_STACK_MUTEX(mIdMtx);
if(!mNes) if(!mNes)
{ {
std::cerr << "(WW) cannot request missing GXS IDs because network service is not present." << std::endl; RsErr() << __PRETTY_FUNCTION__ << " Cannot request missing GXS IDs "
return ; << "because network service is not present." << std::endl;
} return;
}
std::map<RsGxsId, std::list<RsPeerId> >::iterator cit; std::map<RsGxsId, std::list<RsPeerId> >::iterator cit;
std::map<RsPeerId, std::list<RsGxsId> > requests; std::map<RsPeerId, std::list<RsGxsId> > requests;
// Transform to appropriate structure (<peer, std::list<RsGxsId> > map) to make request to nes per peer ID /* Transform to appropriate structure (<RsPeerId, std::list<RsGxsId> > map)
// Only delete entries in mIdsNotPresent that can actually be performed. * to make request to nes per peer ID
* Only delete entries in mIdsNotPresent that can actually be performed, or
* that have empty peer list */
for(cit = mIdsNotPresent.begin(); cit != mIdsNotPresent.end();) for(cit = mIdsNotPresent.begin(); cit != mIdsNotPresent.end();)
{ {
#ifdef DEBUG_IDS Dbg2() << __PRETTY_FUNCTION__ << " Processing missing key RsGxsId: "
std::cerr << "p3IdService::requestIdsFromNet() Id not found, deferring for net request: " << cit->first << std::endl; << cit->first << std::endl;
#endif
const std::list<RsPeerId>& peers = cit->second; const RsGxsId& gxsId = cit->first;
std::list<RsPeerId>::const_iterator cit2; const std::list<RsPeerId>& peers = cit->second;
std::list<RsPeerId>::const_iterator cit2;
bool request_can_proceed = false ; bool request_can_proceed = false ;
for(cit2 = peers.begin(); cit2 != peers.end(); ++cit2) for(cit2 = peers.begin(); cit2 != peers.end(); ++cit2)
if(rsPeers->isOnline(*cit2) || mNes->isDistantPeer(*cit2)) // make sure that the peer in online, so that we know that the request has some chance to succeed. {
{ const RsPeerId& peer = *cit2;
requests[*cit2].push_back(cit->first);
request_can_proceed = true ;
#ifdef DEBUG_IDS
std::cerr << " will ask ID " << cit->first << " to peer ID " << *cit2 << std::endl;
#endif
}
if(request_can_proceed || peers.empty()) if(rsPeers->isOnline(peer) || mNes->isDistantPeer(peer))
{ {
std::map<RsGxsId, std::list<RsPeerId> >::iterator tmp(cit); /* make sure that the peer in online, so that we know that the
++tmp ; * request has some chance to succeed.*/
mIdsNotPresent.erase(cit) ; requests[peer].push_back(cit->first);
cit = tmp ; request_can_proceed = true ;
}
else
{
#ifdef DEBUG_IDS
std::cerr << "(EE) no online peers among supply list in ID request for groupId " << cit->first << ". Keeping it until peers show up."<< std::endl;
#endif
++cit ;
}
}
for(std::map<RsPeerId, std::list<RsGxsId> >::const_iterator cit2(requests.begin()); cit2 != requests.end(); ++cit2) Dbg2() << __PRETTY_FUNCTION__ << " Moving missing key RsGxsId:"
{ << gxsId << " to peer: " << peer << " requests queue"
std::list<RsGxsId>::const_iterator gxs_id_it = cit2->second.begin(); << std::endl;
std::list<RsGxsGroupId> grpIds; }
for(; gxs_id_it != cit2->second.end(); ++gxs_id_it) }
{
#ifdef DEBUG_IDS
std::cerr << " asking ID " << *gxs_id_it << " to peer ID " << cit2->first << std::endl;
#endif
grpIds.push_back(RsGxsGroupId(*gxs_id_it));
}
mNes->requestGrp(grpIds, cit2->first); const bool noPeersFound = peers.empty();
} if(noPeersFound)
RsWarn() << __PRETTY_FUNCTION__ << " No peers supplied to request "
<< "RsGxsId: " << gxsId << " dropping." << std::endl;
if(request_can_proceed || noPeersFound)
{
std::map<RsGxsId, std::list<RsPeerId> >::iterator tmp(cit);
++tmp;
mIdsNotPresent.erase(cit);
cit = tmp;
}
else
{
RsInfo() << __PRETTY_FUNCTION__ << " no online peers among supplied"
<< " list in request for RsGxsId: " << gxsId
<< ". Keeping it until peers show up."<< std::endl;
++cit;
}
}
for( std::map<RsPeerId, std::list<RsGxsId> >::const_iterator cit2(
requests.begin() ); cit2 != requests.end(); ++cit2 )
{
const RsPeerId& peer = cit2->first;
std::list<RsGxsGroupId> grpIds;
for( std::list<RsGxsId>::const_iterator gxs_id_it = cit2->second.begin();
gxs_id_it != cit2->second.end(); ++gxs_id_it )
{
Dbg2() << __PRETTY_FUNCTION__ << " passing RsGxsId: " << *gxs_id_it
<< " request for peer: " << peer
<< " to RsNetworkExchangeService " << std::endl;
grpIds.push_back(RsGxsGroupId(*gxs_id_it));
}
mNes->requestGrp(grpIds, peer);
}
} }
bool p3IdService::cache_update_if_cached(const RsGxsId &id, std::string serviceString) bool p3IdService::cache_update_if_cached(const RsGxsId &id, std::string serviceString)
@ -4698,14 +4708,12 @@ void p3IdService::handle_event(uint32_t event_type, const std::string &/*elabel*
break; break;
case GXSID_EVENT_REQUEST_IDS: case GXSID_EVENT_REQUEST_IDS:
requestIdsFromNet(); requestIdsFromNet();
break; break;
default:
RsErr() << __PRETTY_FUNCTION__ << " Unknown Event Type: "
default: << event_type << std::endl;
/* error */ print_stacktrace();
std::cerr << "p3IdService::handle_event() Unknown Event Type: " << event_type; break;
std::cerr << std::endl;
break;
} }
} }

View File

@ -381,7 +381,10 @@ public:
RsGxsId* id = nullptr); RsGxsId* id = nullptr);
/// @see RsIdentity /// @see RsIdentity
bool requestIdentity(const RsGxsId& id) override; bool requestIdentity(
const RsGxsId& id,
const std::vector<RsPeerId>& peers = std::vector<RsPeerId>()
) override;
/**************** RsGixsReputation Implementation ****************/ /**************** RsGixsReputation Implementation ****************/
@ -494,7 +497,7 @@ private:
/* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */
std::map<RsPgpId, PGPFingerprintType> mPgpFingerprintMap; std::map<RsPgpId, RsPgpFingerprint> mPgpFingerprintMap;
std::list<RsGxsIdGroup> mGroupsToProcess; std::list<RsGxsIdGroup> mGroupsToProcess;
/************************************************************************ /************************************************************************
@ -633,5 +636,5 @@ private:
bool mAutoAddFriendsIdentitiesAsContacts; bool mAutoAddFriendsIdentitiesAsContacts;
uint32_t mMaxKeepKeysBanned; uint32_t mMaxKeepKeysBanned;
RS_SET_CONTEXT_DEBUG_LEVEL(1) RS_SET_CONTEXT_DEBUG_LEVEL(2)
}; };

View File

@ -2134,8 +2134,7 @@ bool p3MsgService::receiveGxsTransMail( const RsGxsId& authorId,
{ {
RS_STACK_MUTEX(recentlyReceivedMutex); RS_STACK_MUTEX(recentlyReceivedMutex);
if( mRecentlyReceivedMessageHashes.find(hash) != if( mRecentlyReceivedMessageHashes.find(hash) != mRecentlyReceivedMessageHashes.end() )
mRecentlyReceivedMessageHashes.end() )
{ {
RsInfo() << __PRETTY_FUNCTION__ << " (II) receiving " RsInfo() << __PRETTY_FUNCTION__ << " (II) receiving "
<< "message of hash " << hash << " more than once. " << "message of hash " << hash << " more than once. "
@ -2143,14 +2142,12 @@ bool p3MsgService::receiveGxsTransMail( const RsGxsId& authorId,
<< std::endl; << std::endl;
return true; return true;
} }
mRecentlyReceivedMessageHashes[hash] = mRecentlyReceivedMessageHashes[hash] = static_cast<uint32_t>(time(nullptr));
static_cast<uint32_t>(time(nullptr));
} }
IndicateConfigChanged(); IndicateConfigChanged();
RsItem *item = _serialiser->deserialise( RsItem *item = _serialiser->deserialise( const_cast<uint8_t*>(data), &dataSize );
const_cast<uint8_t*>(data), &dataSize );
RsMsgItem *msg_item = dynamic_cast<RsMsgItem*>(item); RsMsgItem *msg_item = dynamic_cast<RsMsgItem*>(item);
if(msg_item) if(msg_item)

View File

@ -100,22 +100,42 @@ RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked()
} }
bool RsEventsService::registerEventsHandler( bool RsEventsService::registerEventsHandler(
RsEventType eventType,
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback, std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId ) RsEventsHandlerId_t& hId )
{ {
RS_STACK_MUTEX(mHandlerMapMtx); RS_STACK_MUTEX(mHandlerMapMtx);
if(!hId) hId = generateUniqueHandlerId_unlocked();
mHandlerMap[hId] = multiCallback; if( (int)eventType > mHandlerMaps.size() + 10)
{
RsErr() << "Cannot register an event handler for an event type larger than 10 plus the max pre-defined event (value passed was " << (int)eventType << " whereas max is " << (int)RsEventType::MAX << ")" << std::endl;
return false;
}
if( (int)eventType >= mHandlerMaps.size())
mHandlerMaps.resize( (int)eventType +1 );
if(!hId)
hId = generateUniqueHandlerId_unlocked();
mHandlerMaps[(int)eventType][hId] = multiCallback;
return true; return true;
} }
bool RsEventsService::unregisterEventsHandler(RsEventsHandlerId_t hId) bool RsEventsService::unregisterEventsHandler(RsEventsHandlerId_t hId)
{ {
RS_STACK_MUTEX(mHandlerMapMtx); RS_STACK_MUTEX(mHandlerMapMtx);
auto it = mHandlerMap.find(hId);
if(it == mHandlerMap.end()) return false; for(uint32_t i=0;i<mHandlerMaps.size();++i)
mHandlerMap.erase(it); {
return true; auto it = mHandlerMaps[i].find(hId);
if(it != mHandlerMaps[i].end())
{
mHandlerMaps[i].erase(it);
return true;
}
}
return false;
} }
void RsEventsService::threadTick() void RsEventsService::threadTick()
@ -156,23 +176,25 @@ void RsEventsService::handleEvent(std::shared_ptr<const RsEvent> event)
{ {
std::function<void(std::shared_ptr<const RsEvent>)> mCallback; std::function<void(std::shared_ptr<const RsEvent>)> mCallback;
mHandlerMapMtx.lock(); uint32_t event_type_index = static_cast<uint32_t>(event->mType);
auto cbpt = mHandlerMap.begin();
mHandlerMapMtx.unlock();
getHandlerFromMapLock:
mHandlerMapMtx.lock();
if(cbpt != mHandlerMap.end())
{ {
mCallback = cbpt->second; RS_STACK_MUTEX(mHandlerMapMtx); /* LOCKED AREA */
++cbpt;
}
mHandlerMapMtx.unlock();
if(mCallback) if(event_type_index >= mHandlerMaps.size() || event_type_index < 1)
{ {
mCallback(event); // It is relevant that this happens outside mutex RsErr() << "Cannot handle an event of type " << event_type_index << ": out of scope!" << std::endl;
mCallback = std::function<void(std::shared_ptr<const RsEvent>)>(nullptr); return;
goto getHandlerFromMapLock; }
// Call all clients that registered a callback for this event type
for(auto cbit: mHandlerMaps[event_type_index])
cbit.second(event);
// Also call all clients that registered with NONE, meaning that they expect all events
for(auto cbit: mHandlerMaps[static_cast<uint32_t>(RsEventType::NONE)])
cbit.second(event);
} }
} }

View File

@ -35,6 +35,7 @@ class RsEventsService :
public: public:
RsEventsService(): RsEventsService():
mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1), mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1),
mHandlerMaps(static_cast<int>(RsEventType::MAX)),
mEventQueueMtx("RsEventsService::mEventQueueMtx") {} mEventQueueMtx("RsEventsService::mEventQueueMtx") {}
/// @see RsEvents /// @see RsEvents
@ -54,6 +55,7 @@ public:
/// @see RsEvents /// @see RsEvents
bool registerEventsHandler( bool registerEventsHandler(
RsEventType eventType,
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback, std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0) RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
) override; ) override;
@ -64,9 +66,11 @@ public:
protected: protected:
RsMutex mHandlerMapMtx; RsMutex mHandlerMapMtx;
RsEventsHandlerId_t mLastHandlerId; RsEventsHandlerId_t mLastHandlerId;
std::map<
RsEventsHandlerId_t, std::vector<
std::function<void(std::shared_ptr<const RsEvent>)> > mHandlerMap; std::map<
RsEventsHandlerId_t,
std::function<void(std::shared_ptr<const RsEvent>)> > > mHandlerMaps;
RsMutex mEventQueueMtx; RsMutex mEventQueueMtx;
std::deque< std::shared_ptr<const RsEvent> > mEventQueue; std::deque< std::shared_ptr<const RsEvent> > mEventQueue;

View File

@ -137,18 +137,18 @@ static int tou_socket_read(BIO *b, char *out, int outl)
int ret=0; int ret=0;
if (!out) if (out)
{ {
clear_tou_socket_error(BIO_get_fd(b,NULL)); clear_tou_socket_error(BIO_get_fd(b,NULL));
/* call tou library */ /* call tou library */
ret=tou_read(BIO_get_fd(b,NULL),out,outl); ret=tou_read(BIO_get_fd(b,NULL),out,outl);
BIO_clear_retry_flags(b); BIO_clear_retry_flags(b);
if (ret <= 0) if (ret <= 0)
{ {
if (BIO_tou_socket_should_retry(BIO_get_fd(b,NULL), ret)) if (BIO_tou_socket_should_retry(BIO_get_fd(b,NULL), ret))
BIO_set_retry_read(b); BIO_set_retry_read(b);
}
} }
}
#ifdef DEBUG_TOU_BIO #ifdef DEBUG_TOU_BIO
fprintf(stderr, "tou_socket_read() = %d\n", ret); fprintf(stderr, "tou_socket_read() = %d\n", ret);
#endif #endif

View File

@ -1886,11 +1886,15 @@ void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item)
// because there is not too much file hashes to be active at a time, // because there is not too much file hashes to be active at a time,
// and this mostly prevents from sending the hash back in the tunnel. // and this mostly prevents from sending the hash back in the tunnel.
bool found = false ; #ifdef P3TURTLE_DEBUG
bool ext_found = false ;
#endif
for(std::map<TurtleFileHash,TurtleHashInfo>::iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) for(std::map<TurtleFileHash,TurtleHashInfo>::iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it)
if(it->second.last_request == item->request_id) if(it->second.last_request == item->request_id)
{ {
found = true ; #ifdef P3TURTLE_DEBUG
ext_found = true ;
#endif
{ {
// add the tunnel uniquely // add the tunnel uniquely
@ -1917,7 +1921,7 @@ void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item)
} }
} }
#ifdef P3TURTLE_DEBUG #ifdef P3TURTLE_DEBUG
if(!found) if(!ext_found)
std::cerr << "p3turtle: error. Could not find hash that emmitted tunnel request " << reinterpret_cast<void*>(item->tunnel_id) << std::endl ; std::cerr << "p3turtle: error. Could not find hash that emmitted tunnel request " << reinterpret_cast<void*>(item->tunnel_id) << std::endl ;
#endif #endif
} }

View File

@ -47,8 +47,7 @@ protected:
private slots: private slots:
/* default stuff */ /* default stuff */
void removeItem(); void toggle() override;
void toggle();
void readAndClearItem(); void readAndClearItem();
void copyLink(); void copyLink();
@ -61,9 +60,7 @@ private:
RsFeedReader *mFeedReader; RsFeedReader *mFeedReader;
FeedReaderNotify *mNotify; FeedReaderNotify *mNotify;
FeedHolder *mParent;
std::string mFeedId;
std::string mMsgId; std::string mMsgId;
QString mLink; QString mLink;

View File

@ -72,8 +72,21 @@ static NewsFeed *instance = NULL;
/** Constructor */ /** Constructor */
NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed) NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed)
{ {
mEventHandlerId =0; // needed to force intialization by registerEventsHandler() mEventTypes = {
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId ); RsEventType::AUTHSSL_CONNECTION_AUTENTICATION,
RsEventType::PEER_CONNECTION ,
RsEventType::GXS_CIRCLES ,
RsEventType::GXS_CHANNELS ,
RsEventType::GXS_FORUMS ,
RsEventType::GXS_POSTED ,
RsEventType::MAIL_STATUS
};
for(uint32_t i=0;i<mEventTypes.size();++i)
{
mEventHandlerIds.push_back(0); // needed to force intialization by registerEventsHandler()
rsEvents->registerEventsHandler(mEventTypes[i], [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerIds.back() );
}
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
ui->setupUi(this); ui->setupUi(this);
@ -117,7 +130,8 @@ QString hlp_str = tr(
NewsFeed::~NewsFeed() NewsFeed::~NewsFeed()
{ {
rsEvents->unregisterEventsHandler(mEventHandlerId); for(uint32_t i=0;i<mEventHandlerIds.size();++i)
rsEvents->unregisterEventsHandler(mEventHandlerIds[i]);
// save settings // save settings
processSettings(false); processSettings(false);
@ -188,10 +202,10 @@ void NewsFeed::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
handleForumEvent(event); handleForumEvent(event);
if(event->mType == RsEventType::GXS_POSTED && (flags & RS_FEED_TYPE_POSTED)) if(event->mType == RsEventType::GXS_POSTED && (flags & RS_FEED_TYPE_POSTED))
handleMailEvent(event);
if(event->mType == RsEventType::MAIL_STATUS_CHANGE && (flags & RS_FEED_TYPE_MSG))
handlePostedEvent(event); handlePostedEvent(event);
if(event->mType == RsEventType::MAIL_STATUS && (flags & RS_FEED_TYPE_MSG))
handleMailEvent(event);
} }
void NewsFeed::handleMailEvent(std::shared_ptr<const RsEvent> event) void NewsFeed::handleMailEvent(std::shared_ptr<const RsEvent> event)
@ -200,6 +214,7 @@ void NewsFeed::handleMailEvent(std::shared_ptr<const RsEvent> event)
dynamic_cast<const RsMailStatusEvent*>(event.get()); dynamic_cast<const RsMailStatusEvent*>(event.get());
if(!pe) return; if(!pe) return;
switch(pe->mMailStatusEventCode) switch(pe->mMailStatusEventCode)
{ {
case RsMailStatusEventCode::NEW_MESSAGE: case RsMailStatusEventCode::NEW_MESSAGE:
@ -480,14 +495,10 @@ void NewsFeed::addFeedItemIfUnique(FeedItem *item, bool replace)
void NewsFeed::remUniqueFeedItem(FeedItem *item) void NewsFeed::remUniqueFeedItem(FeedItem *item)
{ {
FeedItem *feedItem = ui->feedWidget->findFeedItem(item->uniqueIdentifier()); //FeedItem *feedItem = ui->feedWidget->findFeedItem(item->uniqueIdentifier());
if (feedItem) ui->feedWidget->removeFeedItem(item);
{
delete item; delete item;
ui->feedWidget->removeFeedItem(feedItem);
}
} }
/* FeedHolder Functions (for FeedItem functionality) */ /* FeedHolder Functions (for FeedItem functionality) */
@ -496,7 +507,7 @@ QScrollArea *NewsFeed::getScrollArea()
return NULL; return NULL;
} }
void NewsFeed::deleteFeedItem(QWidget *item, uint32_t /*type*/) void NewsFeed::deleteFeedItem(FeedItem *item, uint32_t /*type*/)
{ {
#ifdef NEWS_DEBUG #ifdef NEWS_DEBUG
std::cerr << "NewsFeed::deleteFeedItem()"; std::cerr << "NewsFeed::deleteFeedItem()";
@ -504,6 +515,7 @@ void NewsFeed::deleteFeedItem(QWidget *item, uint32_t /*type*/)
#endif #endif
if (item) { if (item) {
ui->feedWidget->removeFeedItem(item);
item->close (); item->close ();
} }
} }

View File

@ -74,7 +74,7 @@ public:
/* FeedHolder Functions (for FeedItem functionality) */ /* FeedHolder Functions (for FeedItem functionality) */
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(FeedItem *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title); virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title);
@ -118,7 +118,8 @@ private:
/* UI - from Designer */ /* UI - from Designer */
Ui::NewsFeed *ui; Ui::NewsFeed *ui;
RsEventsHandlerId_t mEventHandlerId; std::vector<RsEventsHandlerId_t> mEventHandlerIds;
std::vector<RsEventType> mEventTypes;
}; };
#endif #endif

View File

@ -49,7 +49,7 @@ public:
const RsPostedPost &getPost() const; const RsPostedPost &getPost() const;
RsPostedPost &post(); RsPostedPost &post();
uint64_t uniqueIdentifier() const override { return hash_64bits("PostedItem " + mMessageId.toStdString()); } uint64_t uniqueIdentifier() const override { return hash_64bits("PostedItem " + messageId().toStdString()); }
protected: protected:
/* FeedItem */ /* FeedItem */
virtual void doExpand(bool open); virtual void doExpand(bool open);
@ -60,7 +60,7 @@ private slots:
void makeDownVote(); void makeDownVote();
void readToggled(bool checked); void readToggled(bool checked);
void readAndClearItem(); void readAndClearItem();
void toggle(); void toggle() override;
void copyMessageLink(); void copyMessageLink();
void toggleNotes(); void toggleNotes();
void viewPicture(); void viewPicture();

View File

@ -168,8 +168,7 @@ QScrollArea *PostedListWidget::getScrollArea()
return ui->scrollAreaCardView; return ui->scrollAreaCardView;
}*/ }*/
void PostedListWidget::deleteFeedItem(FeedItem *, uint32_t /*type*/)
void PostedListWidget::deleteFeedItem(QWidget */*item*/, uint32_t /*type*/)
{ {
#ifdef DEBUG_POSTED_LIST_WIDGET #ifdef DEBUG_POSTED_LIST_WIDGET
std::cerr << "PostedListWidget::deleteFeedItem() Nah"; std::cerr << "PostedListWidget::deleteFeedItem() Nah";

View File

@ -49,7 +49,7 @@ public:
/* FeedHolder */ /* FeedHolder */
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(FeedItem *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title); virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title);

View File

@ -382,31 +382,42 @@ void ChatWidget::init(const ChatId &chat_id, const QString &title)
if (messageCount > 0) if (messageCount > 0)
{ {
rsHistory->getMessages(chatId, historyMsgs, messageCount); rsHistory->getMessages(chatId, historyMsgs, messageCount);
std::list<HistoryMsg>::iterator historyIt; std::list<HistoryMsg>::iterator historyIt;
for (historyIt = historyMsgs.begin(); historyIt != historyMsgs.end(); ++historyIt) for (historyIt = historyMsgs.begin(); historyIt != historyMsgs.end(); ++historyIt)
{ {
// it can happen that a message is first added to the message history // it can happen that a message is first added to the message history
// and later the gui receives the message through notify // and later the gui receives the message through notify
// avoid this by not adding history entries if their age is < 2secs // avoid this by not adding history entries if their age is < 2secs
if ((time(NULL)-2) <= historyIt->recvTime) if (time(nullptr) <= historyIt->recvTime+2)
continue; continue;
QString name; QString name;
if (chatId.isLobbyId() || chatId.isDistantChatId()) if (chatId.isLobbyId() || chatId.isDistantChatId())
{ {
RsIdentityDetails details; RsIdentityDetails details;
if (rsIdentity->getIdDetails(RsGxsId(historyIt->peerName), details)) time_t start = time(nullptr);
name = QString::fromUtf8(details.mNickname.c_str()); while (!rsIdentity->getIdDetails(RsGxsId(historyIt->peerName), details))
else {
name = QString::fromUtf8(historyIt->peerName.c_str()); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} else { if (time(nullptr)>start+2)
name = QString::fromUtf8(historyIt->peerName.c_str()); {
} std::cerr << "ChatWidget History haven't found Id Details and have wait 1 sec for it." << std::endl;
break;
}
}
addChatMsg(historyIt->incoming, name, RsGxsId(historyIt->peerName.c_str()), QDateTime::fromTime_t(historyIt->sendTime), QDateTime::fromTime_t(historyIt->recvTime), QString::fromUtf8(historyIt->message.c_str()), MSGTYPE_HISTORY); if (rsIdentity->getIdDetails(RsGxsId(historyIt->peerName), details))
} name = QString::fromUtf8(details.mNickname.c_str());
else
name = QString::fromUtf8(historyIt->peerName.c_str());
} else {
name = QString::fromUtf8(historyIt->peerName.c_str());
}
addChatMsg(historyIt->incoming, name, RsGxsId(historyIt->peerName.c_str()), QDateTime::fromTime_t(historyIt->sendTime), QDateTime::fromTime_t(historyIt->recvTime), QString::fromUtf8(historyIt->message.c_str()), MSGTYPE_HISTORY);
}
} }
} }

View File

@ -178,7 +178,7 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
ui->filterLineEdit->showFilterIcon(); ui->filterLineEdit->showFilterIcon();
mEventHandlerId=0; // forces initialization mEventHandlerId=0; // forces initialization
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId ); rsEvents->registerEventsHandler( RsEventType::PEER_CONNECTION, [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId );
mModel = new RsFriendListModel(); mModel = new RsFriendListModel();
mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this); mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this);
@ -258,13 +258,10 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
void NewFriendList::handleEvent(std::shared_ptr<const RsEvent> e) void NewFriendList::handleEvent(std::shared_ptr<const RsEvent> e)
{ {
if(e->mType == RsEventType::PEER_CONNECTION) // /!\ The function we're in is called from a different thread. It's very important
{ // to use this trick in order to avoid data races.
// /!\ The function we're in is called from a different thread. It's very important
// to use this trick in order to avoid data races.
RsQThreadUtils::postToObject( [=]() { forceUpdateDisplay() ; }, this ) ; RsQThreadUtils::postToObject( [=]() { forceUpdateDisplay() ; }, this ) ;
}
} }
NewFriendList::~NewFriendList() NewFriendList::~NewFriendList()

View File

@ -111,7 +111,6 @@ bool RSFeedWidget::eventFilter(QObject *object, QEvent *event)
FeedItem *feedItem = feedItemFromTreeItem(treeItem); FeedItem *feedItem = feedItemFromTreeItem(treeItem);
if (feedItem) { if (feedItem) {
disconnectSignals(feedItem); disconnectSignals(feedItem);
feedRemoved(feedItem);
delete(feedItem); delete(feedItem);
} }
delete(treeItem); delete(treeItem);
@ -135,23 +134,19 @@ void RSFeedWidget::feedAdded(FeedItem *feedItem, QTreeWidgetItem *treeItem)
{ {
} }
void RSFeedWidget::feedRemoved(FeedItem *feedItem)
{
}
void RSFeedWidget::feedsCleared() void RSFeedWidget::feedsCleared()
{ {
} }
void RSFeedWidget::connectSignals(FeedItem *feedItem) void RSFeedWidget::connectSignals(FeedItem *feedItem)
{ {
connect(feedItem, SIGNAL(feedItemDestroyed(FeedItem*)), this, SLOT(feedItemDestroyed(FeedItem*))); connect(feedItem, SIGNAL(feedItemNeedsClosing(qulonglong)), this, SLOT(feedItemDestroyed(qulonglong)));
connect(feedItem, SIGNAL(sizeChanged(FeedItem*)), this, SLOT(feedItemSizeChanged(FeedItem*))); connect(feedItem, SIGNAL(sizeChanged(FeedItem*)), this, SLOT(feedItemSizeChanged(FeedItem*)));
} }
void RSFeedWidget::disconnectSignals(FeedItem *feedItem) void RSFeedWidget::disconnectSignals(FeedItem *feedItem)
{ {
disconnect(feedItem, SIGNAL(feedItemDestroyed(FeedItem*)), this, SLOT(feedItemDestroyed(FeedItem*))); disconnect(feedItem, SIGNAL(feedItemNeedsClosing(qulonglong)), this, SLOT(feedItemDestroyed(qulonglong)));
disconnect(feedItem, SIGNAL(sizeChanged(FeedItem*)), this, SLOT(feedItemSizeChanged(FeedItem*))); disconnect(feedItem, SIGNAL(sizeChanged(FeedItem*)), this, SLOT(feedItemSizeChanged(FeedItem*)));
} }
@ -384,11 +379,10 @@ FeedItem *RSFeedWidget::feedItem(int index)
void RSFeedWidget::removeFeedItem(FeedItem *feedItem) void RSFeedWidget::removeFeedItem(FeedItem *feedItem)
{ {
if (!feedItem) { if (!feedItem)
return; return;
}
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem->uniqueIdentifier()); QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);// WARNING: do not use the other function based on identifier here, because some items change their identifier when loading.
if (treeItem) if (treeItem)
{ {
@ -396,11 +390,10 @@ void RSFeedWidget::removeFeedItem(FeedItem *feedItem)
if(treeItem_index < 0) if(treeItem_index < 0)
{ {
std::cerr << "(EE) Cannot remove designated item \"" << feedItem->uniqueIdentifier() << "\": not found!" << std::endl; std::cerr << "(EE) Cannot remove designated item \"" << (void*)feedItem << "\": not found!" << std::endl;
return ; return ;
} }
feedRemoved(feedItem);
disconnectSignals(feedItem); disconnectSignals(feedItem);
delete ui->treeWidget->takeTopLevelItem(treeItem_index); delete ui->treeWidget->takeTopLevelItem(treeItem_index);
@ -424,20 +417,39 @@ void RSFeedWidget::feedItemSizeChanged(FeedItem */*feedItem*/)
ui->treeWidget->doItemsLayout(); ui->treeWidget->doItemsLayout();
} }
void RSFeedWidget::feedItemDestroyed(FeedItem *feedItem) void RSFeedWidget::feedItemDestroyed(qulonglong id)
{ {
/* No need to disconnect when object will be destroyed */ /* No need to disconnect when object will be destroyed */
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem->uniqueIdentifier()); QTreeWidgetItem *treeItem = findTreeWidgetItem(id);
feedRemoved(feedItem); if(treeItem)
if (treeItem)
delete(treeItem); delete(treeItem);
if (!mCountChangedDisabled) if (!mCountChangedDisabled)
emit feedCountChanged(); emit feedCountChanged();
} }
QTreeWidgetItem *RSFeedWidget::findTreeWidgetItem(const FeedItem *w)
{
QTreeWidgetItemIterator it(ui->treeWidget);
QTreeWidgetItem *treeItem=NULL;
// this search could probably be automatised by giving the tree items the identifier as data for some specific role, then calling QTreeWidget::findItems()
#warning TODO
while (*it)
{
FeedItem *feedItem = feedItemFromTreeItem(*it);
if (feedItem == w)
return *it;
++it;
}
return NULL;
}
QTreeWidgetItem *RSFeedWidget::findTreeWidgetItem(uint64_t identifier) QTreeWidgetItem *RSFeedWidget::findTreeWidgetItem(uint64_t identifier)
{ {
QList<QTreeWidgetItem*> list = ui->treeWidget->findItems(QString("%1").arg(identifier,8,16,QChar('0')),Qt::MatchExactly,COLUMN_IDENTIFIER); QList<QTreeWidgetItem*> list = ui->treeWidget->findItems(QString("%1").arg(identifier,8,16,QChar('0')),Qt::MatchExactly,COLUMN_IDENTIFIER);
@ -490,27 +502,21 @@ void RSFeedWidget::withAll(RSFeedWidgetCallbackFunction callback, void *data)
FeedItem *RSFeedWidget::findFeedItem(uint64_t identifier) FeedItem *RSFeedWidget::findFeedItem(uint64_t identifier)
{ {
QTreeWidgetItemIterator it(ui->treeWidget); QList<QTreeWidgetItem*> list = ui->treeWidget->findItems(QString("%1").arg(identifier,8,16,QChar('0')),Qt::MatchExactly,COLUMN_IDENTIFIER);
QTreeWidgetItem *treeItem=NULL;
// this search could probably be automatised by giving the tree items the identifier as data for some specific role, then calling QTreeWidget::findItems() if(list.empty())
#warning TODO return nullptr;
while ((treeItem = *it) != NULL) { else if(list.size() == 1)
++it; return feedItemFromTreeItem(list.front());
else
FeedItem *feedItem = feedItemFromTreeItem(treeItem); {
if (!feedItem) std::cerr << "(EE) More than a single item with identifier \"" << identifier << "\" in the feed tree widget. This shouldn't happen!" << std::endl;
continue; return nullptr;
}
uint64_t id = feedItem->uniqueIdentifier();
if (id == identifier)
return feedItem;
}
return NULL;
} }
void RSFeedWidget::selectedFeedItems(QList<FeedItem*> &feedItems) void RSFeedWidget::selectedFeedItems(QList<FeedItem*> &feedItems)
{ {
foreach (QTreeWidgetItem *treeItem, ui->treeWidget->selectedItems()) { foreach (QTreeWidgetItem *treeItem, ui->treeWidget->selectedItems()) {

View File

@ -87,11 +87,10 @@ public slots:
protected: protected:
bool eventFilter(QObject *object, QEvent *event); bool eventFilter(QObject *object, QEvent *event);
virtual void feedAdded(FeedItem *feedItem, QTreeWidgetItem *treeItem); virtual void feedAdded(FeedItem *feedItem, QTreeWidgetItem *treeItem);
virtual void feedRemoved(FeedItem *feedItem);
virtual void feedsCleared(); virtual void feedsCleared();
private slots: private slots:
void feedItemDestroyed(FeedItem *feedItem); void feedItemDestroyed(qulonglong id);
void feedItemSizeChanged(FeedItem *feedItem); void feedItemSizeChanged(FeedItem *feedItem);
private: private:
@ -99,6 +98,7 @@ private:
void disconnectSignals(FeedItem *feedItem); void disconnectSignals(FeedItem *feedItem);
FeedItem *feedItemFromTreeItem(QTreeWidgetItem *treeItem); FeedItem *feedItemFromTreeItem(QTreeWidgetItem *treeItem);
QTreeWidgetItem *findTreeWidgetItem(uint64_t identifier); QTreeWidgetItem *findTreeWidgetItem(uint64_t identifier);
QTreeWidgetItem *findTreeWidgetItem(const FeedItem *w);
void filterItems(); void filterItems();
void filterItem(QTreeWidgetItem *treeItem, FeedItem *feedItem); void filterItem(QTreeWidgetItem *treeItem, FeedItem *feedItem);

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1139</width> <width>600</width>
<height>1171</height> <height>400</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">

View File

@ -43,7 +43,7 @@
/** Constructor */ /** Constructor */
ChatMsgItem::ChatMsgItem(FeedHolder *parent, uint32_t feedId, const RsPeerId &peerId, const std::string &message) : ChatMsgItem::ChatMsgItem(FeedHolder *parent, uint32_t feedId, const RsPeerId &peerId, const std::string &message) :
FeedItem(NULL), mParent(parent), mFeedId(feedId), mPeerId(peerId) FeedItem(parent,feedId,NULL), mPeerId(peerId)
{ {
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
setupUi(this); setupUi(this);
@ -153,26 +153,6 @@ void ChatMsgItem::insertChat(const std::string &message)
chatTextlabel->setText(formatMsg); chatTextlabel->setText(formatMsg);
} }
void ChatMsgItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "ChatMsgItem::removeItem()";
std::cerr << std::endl;
#endif
if (mParent) {
mParent->lockLayout(this, true);
}
hide();
if (mParent) {
mParent->lockLayout(this, false);
mParent->deleteFeedItem(this, mFeedId);
}
}
void ChatMsgItem::gotoHome() void ChatMsgItem::gotoHome()
{ {
#ifdef DEBUG_ITEM #ifdef DEBUG_ITEM
@ -191,7 +171,7 @@ void ChatMsgItem::sendMsg()
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
if (mParent) if (mFeedHolder)
{ {
MessageComposer *nMsgDialog = MessageComposer::newMsg(); MessageComposer *nMsgDialog = MessageComposer::newMsg();
@ -214,15 +194,15 @@ void ChatMsgItem::openChat()
std::cerr << "ChatMsgItem::openChat()"; std::cerr << "ChatMsgItem::openChat()";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
if (mParent) if (mFeedHolder)
{ {
mParent->openChat(mPeerId); mFeedHolder->openChat(mPeerId);
} }
} }
void ChatMsgItem::togglequickmessage() void ChatMsgItem::togglequickmessage()
{ {
mParent->lockLayout(this, true); mFeedHolder->lockLayout(this, true);
if (messageFrame->isHidden()) if (messageFrame->isHidden())
{ {
@ -239,7 +219,7 @@ void ChatMsgItem::togglequickmessage()
emit sizeChanged(this); emit sizeChanged(this);
mParent->lockLayout(this, false); mFeedHolder->lockLayout(this, false);
} }
void ChatMsgItem::sendMessage() void ChatMsgItem::sendMessage()

View File

@ -45,7 +45,6 @@ protected:
private slots: private slots:
/* default stuff */ /* default stuff */
void gotoHome(); void gotoHome();
void removeItem();
void sendMsg(); void sendMsg();
void openChat(); void openChat();
@ -60,9 +59,6 @@ private slots:
private: private:
void insertChat(const std::string &message); void insertChat(const std::string &message);
FeedHolder *mParent;
uint32_t mFeedId;
RsPeerId mPeerId; RsPeerId mPeerId;
}; };

View File

@ -27,6 +27,7 @@
#include <retroshare/rsgxschannels.h> // WRONG ONE - BUT IT'LL DO FOR NOW. #include <retroshare/rsgxschannels.h> // WRONG ONE - BUT IT'LL DO FOR NOW.
class QScrollArea; class QScrollArea;
class FeedItem;
class FeedHolder class FeedHolder
{ {
@ -34,7 +35,7 @@ public:
FeedHolder(); FeedHolder();
virtual QScrollArea *getScrollArea() = 0; virtual QScrollArea *getScrollArea() = 0;
virtual void deleteFeedItem(QWidget *item, uint32_t type) = 0; virtual void deleteFeedItem(FeedItem *item, uint32_t type) = 0;
virtual void openChat(const RsPeerId& peerId) = 0; virtual void openChat(const RsPeerId& peerId) = 0;
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title)=0; virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title)=0;

View File

@ -20,17 +20,15 @@
#include <iostream> #include <iostream>
#include "FeedItem.h" #include "FeedItem.h"
#include "FeedHolder.h"
/** Constructor */ /** Constructor */
FeedItem::FeedItem(QWidget *parent) : QWidget(parent), mHash(0) FeedItem::FeedItem(FeedHolder *fh, uint32_t feedId, QWidget *parent) : QWidget(parent), mHash(0),mFeedHolder(fh),mFeedId(feedId)
{ {
mWasExpanded = false; mWasExpanded = false;
} }
FeedItem::~FeedItem() FeedItem::~FeedItem() { }
{
emit feedItemDestroyed(this);
}
void FeedItem::expand(bool open) void FeedItem::expand(bool open)
{ {
@ -48,12 +46,28 @@ void FeedItem::expand(bool open)
uint64_t FeedItem::hash_64bits(const std::string& s) const uint64_t FeedItem::hash_64bits(const std::string& s) const
{ {
if(mHash == 0) if(mHash == 0)
{ mHash = hash64(s);
mHash = 0x01110bbfa09;
for(uint32_t i=0;i<s.size();++i)
mHash = ~(((mHash << 31) ^ (mHash >> 3)) + s[i]*0x217898fbba7 + 0x0294379);
}
return mHash; return mHash;
} }
uint64_t FeedItem::hash64(const std::string& s)
{
uint64_t hash = 0x01110bbfa09;
for(uint32_t i=0;i<s.size();++i)
hash = ~(((hash << 31) ^ (hash >> 3)) + s[i]*0x217898fbba7 + 0x0294379);
return hash;
}
void FeedItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "MsgItem::removeItem()";
std::cerr << std::endl;
#endif
mFeedHolder->deleteFeedItem(this,0);
}

View File

@ -23,13 +23,15 @@
#include <QWidget> #include <QWidget>
class FeedHolder;
class FeedItem : public QWidget class FeedItem : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
/** Default Constructor */ /** Default Constructor */
FeedItem(QWidget *parent = 0); FeedItem(FeedHolder *fh,uint32_t feedId,QWidget *parent = 0);
/** Default Destructor */ /** Default Destructor */
virtual ~FeedItem(); virtual ~FeedItem();
@ -42,14 +44,25 @@ public:
* would contain the same information. It should therefore sumarise the data represented by the item. * would contain the same information. It should therefore sumarise the data represented by the item.
*/ */
virtual uint64_t uniqueIdentifier() const =0; virtual uint64_t uniqueIdentifier() const =0;
static uint64_t hash64(const std::string& s);
protected slots:
void removeItem();
protected: protected:
virtual void doExpand(bool open) = 0; virtual void doExpand(bool open) = 0;
virtual void expandFill(bool /*first*/) {} virtual void expandFill(bool /*first*/) {}
virtual void toggle() {}
uint64_t hash_64bits(const std::string& s) const; uint64_t hash_64bits(const std::string& s) const;
FeedHolder *mFeedHolder;
uint32_t mFeedId;
signals: signals:
void sizeChanged(FeedItem *feedItem); void sizeChanged(FeedItem *feedItem);
void feedItemDestroyed(FeedItem *feedItem); void feedItemNeedsClosing(qulonglong);
private: private:
bool mWasExpanded; bool mWasExpanded;

View File

@ -53,7 +53,7 @@ protected:
private slots: private slots:
/* default stuff */ /* default stuff */
void toggle(); void toggle() override;
void subscribeChannel(); void subscribeChannel();

View File

@ -46,12 +46,14 @@
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set<RsGxsMessageId>& older_versions) : GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set<RsGxsMessageId>& older_versions) :
GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsChannels, autoUpdate) GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsChannels, autoUpdate)
{ {
mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded
init(messageId,older_versions) ; init(messageId,older_versions) ;
} }
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost& post, bool isHome, bool autoUpdate,const std::set<RsGxsMessageId>& older_versions) : GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost& post, bool isHome, bool autoUpdate,const std::set<RsGxsMessageId>& older_versions) :
GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, autoUpdate) GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, autoUpdate)
{ {
mPost.mMeta.mMsgId.clear(); // security
init(post.mMeta.mMsgId,older_versions) ; init(post.mMeta.mMsgId,older_versions) ;
mPost = post ; mPost = post ;
} }
@ -71,63 +73,9 @@ void GxsChannelPostItem::init(const RsGxsMessageId& messageId,const std::set<RsG
setup(); setup();
mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded
mLoaded = false ; mLoaded = false ;
} }
// This code has been suspended because it adds more complexity than usefulness.
// It was used to load a channel post where the post item is already known.
#ifdef SUSPENDED
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelGroup &group, const RsGxsChannelPost &post, bool isHome, bool autoUpdate) :
GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, autoUpdate)
{
#ifdef DEBUG_ITEM
std::cerr << "GxsChannelPostItem::GxsChannelPostItem() Direct Load";
std::cerr << std::endl;
#endif
QVector<RsGxsMessageId> v;
bool self = false;
for(std::set<RsGxsMessageId>::const_iterator it(post.mOlderVersions.begin());it!=post.mOlderVersions.end();++it)
{
if(*it == post.mMeta.mMsgId)
self = true ;
v.push_back(*it) ;
}
if(!self)
v.push_back(post.mMeta.mMsgId);
setMessageVersions(v) ;
setup();
setGroup(group, false);
setPost(post,false);
mLoaded = false ;
}
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, bool isHome, bool autoUpdate) :
GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, autoUpdate)
{
#ifdef DEBUG_ITEM
std::cerr << "GxsChannelPostItem::GxsChannelPostItem() Direct Load";
std::cerr << std::endl;
#endif
setup();
mLoaded = true ;
requestGroup();
setPost(post);
requestComment();
}
#endif
void GxsChannelPostItem::paintEvent(QPaintEvent *e) void GxsChannelPostItem::paintEvent(QPaintEvent *e)
{ {
/* This method employs a trick to trigger a deferred loading. The post and group is requested only /* This method employs a trick to trigger a deferred loading. The post and group is requested only
@ -168,7 +116,6 @@ void GxsChannelPostItem::setup()
/* clear ui */ /* clear ui */
ui->titleLabel->setText(tr("Loading")); ui->titleLabel->setText(tr("Loading"));
ui->subjectLabel->clear();
ui->datetimelabel->clear(); ui->datetimelabel->clear();
ui->filelabel->clear(); ui->filelabel->clear();
ui->newCommentLabel->hide(); ui->newCommentLabel->hide();
@ -207,7 +154,7 @@ void GxsChannelPostItem::setup()
ui->warning_label->hide(); ui->warning_label->hide();
ui->titleLabel->setMinimumWidth(100); ui->titleLabel->setMinimumWidth(100);
ui->subjectLabel->setMinimumWidth(100); //ui->subjectLabel->setMinimumWidth(100);
ui->warning_label->setMinimumWidth(100); ui->warning_label->setMinimumWidth(100);
ui->mainFrame->setProperty("new", false); ui->mainFrame->setProperty("new", false);
@ -326,12 +273,14 @@ void GxsChannelPostItem::loadMessage(const uint32_t &token)
if (posts.size() == 1) if (posts.size() == 1)
{ {
std::cerr << (void*)this << ": Obtained post, with msgId = " << posts[0].mMeta.mMsgId << std::endl;
setPost(posts[0]); setPost(posts[0]);
} }
else if (cmts.size() == 1) else if (cmts.size() == 1)
{ {
RsGxsComment cmt = cmts[0]; RsGxsComment cmt = cmts[0];
std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl;
ui->newCommentLabel->show(); ui->newCommentLabel->show();
ui->commLabel->show(); ui->commLabel->show();
ui->commLabel->setText(QString::fromUtf8(cmt.mComment.c_str())); ui->commLabel->setText(QString::fromUtf8(cmt.mComment.c_str()));
@ -428,7 +377,7 @@ void GxsChannelPostItem::fill()
ui->titleLabel->setText(title); ui->titleLabel->setText(title);
RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, messageName()); RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, messageName());
ui->subjectLabel->setText(msgLink.toHtml()); //ui->subjectLabel->setText(msgLink.toHtml());
if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroup.mMeta.mSubscribeFlags)) if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroup.mMeta.mSubscribeFlags))
{ {
@ -451,10 +400,10 @@ void GxsChannelPostItem::fill()
/* subject */ /* subject */
ui->titleLabel->setText(QString::fromUtf8(mPost.mMeta.mMsgName.c_str())); ui->titleLabel->setText(QString::fromUtf8(mPost.mMeta.mMsgName.c_str()));
uint32_t autorized_lines = (int)floor((ui->logoLabel->height() - ui->titleLabel->height() - ui->buttonHLayout->sizeHint().height())/QFontMetricsF(ui->subjectLabel->font()).height()); //uint32_t autorized_lines = (int)floor((ui->logoLabel->height() - ui->titleLabel->height() - ui->buttonHLayout->sizeHint().height())/QFontMetricsF(ui->subjectLabel->font()).height());
// fill first 4 lines of message. (csoler) Disabled the replacement of smileys and links, because the cost is too crazy // fill first 4 lines of message. (csoler) Disabled the replacement of smileys and links, because the cost is too crazy
ui->subjectLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); //ui->subjectLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS));
//ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 2)) ; //ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 2)) ;
@ -522,7 +471,13 @@ void GxsChannelPostItem::fill()
voteDownButton->setEnabled(false); voteDownButton->setEnabled(false);
}*/ }*/
ui->msgFrame->setVisible(!mPost.mMsg.empty()); {
QTextDocument doc;
doc.setHtml( QString::fromUtf8(mPost.mMsg.c_str()) );
ui->msgFrame->setVisible(doc.toPlainText().length() > 0);
}
if (wasExpanded() || ui->expandFrame->isVisible()) { if (wasExpanded() || ui->expandFrame->isVisible()) {
fillExpandFrame(); fillExpandFrame();
} }
@ -531,7 +486,7 @@ void GxsChannelPostItem::fill()
if ( (mPost.mCount != 0) || (mPost.mSize != 0) ) { if ( (mPost.mCount != 0) || (mPost.mSize != 0) ) {
ui->filelabel->setVisible(true); ui->filelabel->setVisible(true);
ui->filelabel->setText(QString("(%1 %2) %3").arg(mPost.mCount).arg(tr("Files")).arg(misc::friendlyUnit(mPost.mSize))); ui->filelabel->setText(QString("(%1 %2) %3").arg(mPost.mCount).arg( (mPost.mCount > 1)?tr("Files"):tr("File")).arg(misc::friendlyUnit(mPost.mSize)));
} else { } else {
ui->filelabel->setVisible(false); ui->filelabel->setVisible(false);
} }
@ -575,6 +530,7 @@ void GxsChannelPostItem::fill()
void GxsChannelPostItem::fillExpandFrame() void GxsChannelPostItem::fillExpandFrame()
{ {
ui->msgLabel->setText(RsHtml().formatText(NULL, QString::fromUtf8(mPost.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); ui->msgLabel->setText(RsHtml().formatText(NULL, QString::fromUtf8(mPost.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS));
} }
QString GxsChannelPostItem::messageName() QString GxsChannelPostItem::messageName()

View File

@ -53,7 +53,7 @@ public:
//GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, bool isHome, bool autoUpdate); //GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, bool isHome, bool autoUpdate);
virtual ~GxsChannelPostItem(); virtual ~GxsChannelPostItem();
uint64_t uniqueIdentifier() const override { hash_64bits("GxsChannelPostItem " + mPost.mMeta.mMsgId.toStdString()) ; } uint64_t uniqueIdentifier() const override { hash_64bits("GxsChannelPostItem " + messageId().toStdString()) ; }
bool setGroup(const RsGxsChannelGroup &group, bool doFill = true); bool setGroup(const RsGxsChannelGroup &group, bool doFill = true);
bool setPost(const RsGxsChannelPost &post, bool doFill = true); bool setPost(const RsGxsChannelPost &post, bool doFill = true);
@ -66,6 +66,7 @@ public:
bool isUnread() const ; bool isUnread() const ;
static uint64_t computeIdentifier(const RsGxsMessageId& msgid) { return hash64("GxsChannelPostItem " + msgid.toStdString()) ; }
protected: protected:
void init(const RsGxsMessageId& messageId,const std::set<RsGxsMessageId>& older_versions); void init(const RsGxsMessageId& messageId,const std::set<RsGxsMessageId>& older_versions);
@ -90,7 +91,7 @@ protected:
private slots: private slots:
/* default stuff */ /* default stuff */
void toggle(); void toggle() override;
void readAndClearItem(); void readAndClearItem();
void download(); void download();
void play(); void play();

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1359</width> <width>1433</width>
<height>342</height> <height>541</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gxsChannelPostItem_GLayout"> <layout class="QGridLayout" name="gxsChannelPostItem_GLayout">
@ -50,26 +50,30 @@
<item> <item>
<layout class="QHBoxLayout" name="mainTopHLayout"> <layout class="QHBoxLayout" name="mainTopHLayout">
<item> <item>
<widget class="QLabel" name="logoLabel"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <widget class="QLabel" name="logoLabel">
<horstretch>0</horstretch> <property name="sizePolicy">
<verstretch>0</verstretch> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
</sizepolicy> <horstretch>0</horstretch>
</property> <verstretch>0</verstretch>
<property name="text"> </sizepolicy>
<string/> </property>
</property> <property name="text">
<property name="pixmap"> <string/>
<pixmap resource="../images.qrc">:/images/thumb-default-video.png</pixmap> </property>
</property> <property name="pixmap">
<property name="scaledContents"> <pixmap resource="../images.qrc">:/images/thumb-default-video.png</pixmap>
<bool>false</bool> </property>
</property> <property name="scaledContents">
<property name="alignment"> <bool>false</bool>
<set>Qt::AlignCenter</set> </property>
</property> <property name="alignment">
</widget> <set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="mainRTopVLayout"> <layout class="QVBoxLayout" name="mainRTopVLayout">
@ -114,40 +118,17 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="newLabel">
<property name="text">
<string>New</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="subjectHLayout"> <layout class="QHBoxLayout" name="subjectHLayout"/>
<item>
<widget class="QLabel" name="subjectLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">Short Description</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filelabel">
<property name="text">
<string notr="true">fileLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="warningHLayout"> <layout class="QHBoxLayout" name="warningHLayout">
@ -234,13 +215,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="newLabel">
<property name="text">
<string>New</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="scoreLabel"> <widget class="QLabel" name="scoreLabel">
<property name="font"> <property name="font">
@ -335,19 +309,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QPushButton" name="copyLinkButton"> <widget class="QPushButton" name="copyLinkButton">
<property name="sizePolicy"> <property name="sizePolicy">
@ -368,6 +329,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="filelabel">
<property name="text">
<string notr="true">fileLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="unsubscribeButton"> <widget class="QPushButton" name="unsubscribeButton">
<property name="sizePolicy"> <property name="sizePolicy">
@ -387,6 +358,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QPushButton" name="expandButton"> <widget class="QPushButton" name="expandButton">
<property name="sizePolicy"> <property name="sizePolicy">

View File

@ -40,7 +40,7 @@
GxsCircleItem::GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type) 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) :FeedItem(feedHolder,feedId,NULL), mType(type), mCircleId(circleId), mGxsId(gxsId)
{ {
setup(); setup();
} }
@ -172,22 +172,6 @@ uint64_t GxsCircleItem::uniqueIdentifier() const
return hash_64bits("GxsCircle " + mCircleId.toStdString() + " " + mGxsId.toStdString() + " " + QString::number(mType).toStdString()); return hash_64bits("GxsCircle " + mCircleId.toStdString() + " " + mGxsId.toStdString() + " " + QString::number(mType).toStdString());
} }
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) void GxsCircleItem::loadRequest(const TokenQueue * queue, const TokenRequest &req)
{ {
#ifdef ID_DEBUG #ifdef ID_DEBUG

View File

@ -65,9 +65,6 @@ protected:
private slots: private slots:
/* default stuff */
void removeItem();
void showCircleDetails(); void showCircleDetails();
void acceptCircleSubscription(); void acceptCircleSubscription();
void grantCircleMembership() ; void grantCircleMembership() ;
@ -76,8 +73,6 @@ private slots:
private: private:
void setup(); void setup();
FeedHolder *mFeedHolder;
uint32_t mFeedId;
uint32_t mType; uint32_t mType;
RsGxsCircleId mCircleId; RsGxsCircleId mCircleId;

View File

@ -158,7 +158,6 @@ void GxsForumGroupItem::fill()
ui->clearButton->setEnabled(false); ui->clearButton->setEnabled(false);
} }
} }
void GxsForumGroupItem::toggle() void GxsForumGroupItem::toggle()
{ {
expand(ui->expandFrame->isHidden()); expand(ui->expandFrame->isHidden());

View File

@ -46,6 +46,7 @@ public:
protected: protected:
/* FeedItem */ /* FeedItem */
virtual void doExpand(bool open); virtual void doExpand(bool open);
void toggle() override;
/* GxsGroupFeedItem */ /* GxsGroupFeedItem */
virtual QString groupName(); virtual QString groupName();
@ -53,9 +54,6 @@ protected:
virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_FORUM; } virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_FORUM; }
private slots: private slots:
/* default stuff */
void toggle();
void subscribeForum(); void subscribeForum();
private: private:

View File

@ -43,7 +43,7 @@ public:
bool setGroup(const RsGxsForumGroup &group, bool doFill = true); bool setGroup(const RsGxsForumGroup &group, bool doFill = true);
bool setMessage(const RsGxsForumMsg &msg, bool doFill = true); bool setMessage(const RsGxsForumMsg &msg, bool doFill = true);
uint64_t uniqueIdentifier() const override { return hash_64bits("GxsForumMsgItem " + mMessage.mMeta.mMsgId.toStdString()) ; } uint64_t uniqueIdentifier() const override { return hash_64bits("GxsForumMsgItem " + messageId().toStdString()) ; }
protected: protected:
/* FeedItem */ /* FeedItem */
virtual void doExpand(bool open); virtual void doExpand(bool open);
@ -67,7 +67,7 @@ protected:
private slots: private slots:
/* default stuff */ /* default stuff */
void toggle(); void toggle() override;
void readAndClearItem(); void readAndClearItem();
void unsubscribeForum(); void unsubscribeForum();

View File

@ -43,7 +43,7 @@
/** Constructor */ /** Constructor */
MsgItem::MsgItem(FeedHolder *parent, uint32_t feedId, const std::string &msgId, bool isHome) : MsgItem::MsgItem(FeedHolder *parent, uint32_t feedId, const std::string &msgId, bool isHome) :
FeedItem(NULL), mParent(parent), mFeedId(feedId), mMsgId(msgId), mIsHome(isHome) FeedItem(parent,feedId,NULL), mMsgId(msgId), mIsHome(isHome)
{ {
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
setupUi(this); setupUi(this);
@ -222,15 +222,10 @@ void MsgItem::updateItem()
} }
} }
void MsgItem::toggle()
{
expand(expandFrame->isHidden());
}
void MsgItem::doExpand(bool open) void MsgItem::doExpand(bool open)
{ {
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, true); mFeedHolder->lockLayout(this, true);
} }
if (open) if (open)
@ -252,8 +247,8 @@ void MsgItem::doExpand(bool open)
emit sizeChanged(this); emit sizeChanged(this);
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, false); mFeedHolder->lockLayout(this, false);
} }
} }
@ -266,23 +261,6 @@ void MsgItem::expandFill(bool first)
} }
} }
void MsgItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "MsgItem::removeItem()";
std::cerr << std::endl;
#endif
mParent->lockLayout(this, true);
hide();
mParent->lockLayout(this, false);
if (mParent)
{
mParent->deleteFeedItem(this, mFeedId);
}
}
void MsgItem::gotoHome() void MsgItem::gotoHome()
{ {
@ -315,7 +293,7 @@ void MsgItem::replyMsg()
std::cerr << "MsgItem::replyMsg()"; std::cerr << "MsgItem::replyMsg()";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
if (mParent) if (mFeedHolder)
{ {
//mParent->openMsg(FEEDHOLDER_MSG_MESSAGE, mPeerId, mMsgId); //mParent->openMsg(FEEDHOLDER_MSG_MESSAGE, mPeerId, mMsgId);
@ -339,6 +317,11 @@ void MsgItem::playMedia()
#endif #endif
} }
void MsgItem::toggle()
{
expand(expandFrame->isHidden());
}
void MsgItem::checkMessageReadStatus() void MsgItem::checkMessageReadStatus()
{ {
if (!mCloseOnRead) { if (!mCloseOnRead) {

View File

@ -50,7 +50,6 @@ private:
private slots: private slots:
/* default stuff */ /* default stuff */
void gotoHome(); void gotoHome();
void removeItem();
void toggle(); void toggle();
void playMedia(); void playMedia();
@ -62,9 +61,6 @@ private slots:
void updateItem(); void updateItem();
private: private:
FeedHolder *mParent;
uint32_t mFeedId;
std::string mMsgId; std::string mMsgId;
QString mMsg; QString mMsg;

View File

@ -41,7 +41,7 @@
/** Constructor */ /** Constructor */
PeerItem::PeerItem(FeedHolder *parent, uint32_t feedId, const RsPeerId &peerId, uint32_t type, bool isHome) : PeerItem::PeerItem(FeedHolder *parent, uint32_t feedId, const RsPeerId &peerId, uint32_t type, bool isHome) :
FeedItem(NULL), mParent(parent), mFeedId(feedId), FeedItem(parent,feedId,NULL),
mPeerId(peerId), mType(type), mIsHome(isHome) mPeerId(peerId), mType(type), mIsHome(isHome)
{ {
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
@ -50,12 +50,12 @@ PeerItem::PeerItem(FeedHolder *parent, uint32_t feedId, const RsPeerId &peerId,
sendmsgButton->setEnabled(false); sendmsgButton->setEnabled(false);
/* general ones */ /* general ones */
connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); connect( expandButton, SIGNAL( clicked() ), this, SLOT( toggle() ) );
connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); connect( clearButton, SIGNAL( clicked() ), this, SLOT( removeItem() ) );
/* specific ones */ /* specific ones */
connect( chatButton, SIGNAL( clicked( void ) ), this, SLOT( openChat ( void ) ) ); connect( chatButton, SIGNAL( clicked() ), this, SLOT( openChat() ) );
connect( sendmsgButton, SIGNAL( clicked( ) ), this, SLOT( sendMsg() ) ); connect( sendmsgButton, SIGNAL( clicked() ), this, SLOT( sendMsg() ) );
connect(NotifyQt::getInstance(), SIGNAL(friendsChanged()), this, SLOT(updateItem())); connect(NotifyQt::getInstance(), SIGNAL(friendsChanged()), this, SLOT(updateItem()));
@ -225,7 +225,7 @@ void PeerItem::updateItem()
/* slow Tick */ /* slow Tick */
int msec_rate = 10129; int msec_rate = 10129;
QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); QTimer::singleShot( msec_rate, this, SLOT(updateItem() ));
return; return;
} }
@ -236,8 +236,8 @@ void PeerItem::toggle()
void PeerItem::doExpand(bool open) void PeerItem::doExpand(bool open)
{ {
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, true); mFeedHolder->lockLayout(this, true);
} }
if (open) if (open)
@ -255,25 +255,8 @@ void PeerItem::doExpand(bool open)
emit sizeChanged(this); emit sizeChanged(this);
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, false); mFeedHolder->lockLayout(this, false);
}
}
void PeerItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "PeerItem::removeItem()";
std::cerr << std::endl;
#endif
mParent->lockLayout(this, true);
hide();
mParent->lockLayout(this, false);
if (mParent)
{
mParent->deleteFeedItem(this, mFeedId);
} }
} }
@ -321,9 +304,9 @@ void PeerItem::openChat()
std::cerr << "PeerItem::openChat()"; std::cerr << "PeerItem::openChat()";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
if (mParent) if (mFeedHolder)
{ {
mParent->openChat(mPeerId); mFeedHolder->openChat(mPeerId);
} }
} }

View File

@ -51,8 +51,7 @@ protected:
private slots: private slots:
/* default stuff */ /* default stuff */
void removeItem(); void toggle() override;
void toggle();
void addFriend(); void addFriend();
void removeFriend(); void removeFriend();
@ -63,8 +62,6 @@ private slots:
private: private:
FeedHolder *mParent;
uint32_t mFeedId;
RsPeerId mPeerId; RsPeerId mPeerId;
uint32_t mType; uint32_t mType;

View File

@ -54,9 +54,7 @@ protected:
virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_UNKNOWN; } virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_UNKNOWN; }
private slots: private slots:
/* default stuff */ void toggle() override;
void toggle();
void subscribePosted(); void subscribePosted();
private: private:

View File

@ -40,14 +40,14 @@
/** Constructor */ /** Constructor */
SecurityIpItem::SecurityIpItem(FeedHolder *parent, const RsPeerId &sslId, const std::string &ipAddr, uint32_t result, uint32_t type, bool isTest) : SecurityIpItem::SecurityIpItem(FeedHolder *parent, const RsPeerId &sslId, const std::string &ipAddr, uint32_t result, uint32_t type, bool isTest) :
FeedItem(NULL), mParent(parent), mType(type), mSslId(sslId), mIpAddr(ipAddr), mResult(result), mIsTest(isTest), FeedItem(parent,0,NULL), mType(type), mSslId(sslId), mIpAddr(ipAddr), mResult(result), mIsTest(isTest),
ui(new(Ui::SecurityIpItem)) ui(new(Ui::SecurityIpItem))
{ {
setup(); setup();
} }
SecurityIpItem::SecurityIpItem(FeedHolder *parent, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, uint32_t type, bool isTest) : SecurityIpItem::SecurityIpItem(FeedHolder *parent, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, uint32_t type, bool isTest) :
FeedItem(NULL), mParent(parent), mType(type), mSslId(sslId), mIpAddr(ipAddr), mIpAddrReported(ipAddrReported), mResult(0), mIsTest(isTest), FeedItem(parent,0,NULL), mType(type), mSslId(sslId), mIpAddr(ipAddr), mIpAddrReported(ipAddrReported), mResult(0), mIsTest(isTest),
ui(new(Ui::SecurityIpItem)) ui(new(Ui::SecurityIpItem))
{ {
setup(); setup();
@ -192,8 +192,8 @@ void SecurityIpItem::toggle()
void SecurityIpItem::doExpand(bool open) void SecurityIpItem::doExpand(bool open)
{ {
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, true); mFeedHolder->lockLayout(this, true);
} }
if (open) if (open)
@ -211,25 +211,8 @@ void SecurityIpItem::doExpand(bool open)
emit sizeChanged(this); emit sizeChanged(this);
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, false); mFeedHolder->lockLayout(this, false);
}
}
void SecurityIpItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "SecurityIpItem::removeItem()";
std::cerr << std::endl;
#endif
mParent->lockLayout(this, true);
hide();
mParent->lockLayout(this, false);
if (mParent)
{
mParent->deleteFeedItem(this, mFeedId);
} }
} }

View File

@ -54,16 +54,12 @@ private:
private slots: private slots:
/* default stuff */ /* default stuff */
void removeItem(); void toggle() override;
void toggle();
void peerDetails(); void peerDetails();
void updateItem(); void updateItem();
void banIpListChanged(const QString &ipAddress); void banIpListChanged(const QString &ipAddress);
private: private:
FeedHolder *mParent;
uint32_t mFeedId;
uint32_t mType; uint32_t mType;
RsPeerId mSslId; RsPeerId mSslId;
std::string mIpAddr; std::string mIpAddr;

View File

@ -44,7 +44,7 @@
/** Constructor */ /** Constructor */
SecurityItem::SecurityItem(FeedHolder *parent, uint32_t feedId, const RsPgpId &gpgId, const RsPeerId &sslId, const std::string &sslCn, const std::string& ip_address,uint32_t type, bool isHome) : SecurityItem::SecurityItem(FeedHolder *parent, uint32_t feedId, const RsPgpId &gpgId, const RsPeerId &sslId, const std::string &sslCn, const std::string& ip_address,uint32_t type, bool isHome) :
FeedItem(NULL), mParent(parent), mFeedId(feedId), FeedItem(parent,feedId,NULL),
mGpgId(gpgId), mSslId(sslId), mSslCn(sslCn), mIP(ip_address), mType(type), mIsHome(isHome) mGpgId(gpgId), mSslId(sslId), mSslCn(sslCn), mIP(ip_address), mType(type), mIsHome(isHome)
{ {
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
@ -288,8 +288,8 @@ void SecurityItem::toggle()
void SecurityItem::doExpand(bool open) void SecurityItem::doExpand(bool open)
{ {
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, true); mFeedHolder->lockLayout(this, true);
} }
if (open) if (open)
@ -307,25 +307,8 @@ void SecurityItem::doExpand(bool open)
emit sizeChanged(this); emit sizeChanged(this);
if (mParent) { if (mFeedHolder) {
mParent->lockLayout(this, false); mFeedHolder->lockLayout(this, false);
}
}
void SecurityItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "SecurityItem::removeItem()";
std::cerr << std::endl;
#endif
mParent->lockLayout(this, true);
hide();
mParent->lockLayout(this, false);
if (mParent)
{
mParent->deleteFeedItem(this, mFeedId);
} }
} }
@ -413,8 +396,8 @@ void SecurityItem::openChat()
std::cerr << "SecurityItem::openChat()"; std::cerr << "SecurityItem::openChat()";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
if (mParent) if (mFeedHolder)
{ {
mParent->openChat(mSslId); mFeedHolder->openChat(mSslId);
} }
} }

View File

@ -50,8 +50,7 @@ protected:
private slots: private slots:
/* default stuff */ /* default stuff */
void removeItem(); void toggle() override;
void toggle();
void friendRequest(); void friendRequest();
void removeFriend(); void removeFriend();
@ -62,9 +61,6 @@ private slots:
void updateItem(); void updateItem();
private: private:
FeedHolder *mParent;
uint32_t mFeedId;
RsPgpId mGpgId; RsPgpId mGpgId;
RsPeerId mSslId; RsPeerId mSslId;
std::string mSslCn; std::string mSslCn;

View File

@ -46,8 +46,6 @@ void GxsFeedWidget::feedAdded(FeedItem *feedItem, QTreeWidgetItem *treeItem)
void GxsFeedWidget::feedRemoved(FeedItem *feedItem) void GxsFeedWidget::feedRemoved(FeedItem *feedItem)
{ {
RSFeedWidget::feedRemoved(feedItem);
GxsFeedItem *gxsFeedItem = dynamic_cast<GxsFeedItem*>(feedItem); GxsFeedItem *gxsFeedItem = dynamic_cast<GxsFeedItem*>(feedItem);
if (!gxsFeedItem) { if (!gxsFeedItem) {
return; return;

View File

@ -32,7 +32,7 @@
**/ **/
GxsGroupFeedItem::GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate) : GxsGroupFeedItem::GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate) :
FeedItem(NULL) FeedItem(feedHolder,feedId,NULL)
{ {
#ifdef DEBUG_ITEM #ifdef DEBUG_ITEM
std::cerr << "GxsGroupFeedItem::GxsGroupFeedItem()"; std::cerr << "GxsGroupFeedItem::GxsGroupFeedItem()";
@ -40,8 +40,6 @@ GxsGroupFeedItem::GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, cons
#endif #endif
/* this are just generally useful for all children */ /* this are just generally useful for all children */
mFeedHolder = feedHolder;
mFeedId = feedId;
mIsHome = isHome; mIsHome = isHome;
/* load data if we can */ /* load data if we can */
@ -93,27 +91,6 @@ bool GxsGroupFeedItem::initLoadQueue()
return (mLoadQueue != NULL); return (mLoadQueue != NULL);
} }
void GxsGroupFeedItem::removeItem()
{
#ifdef DEBUG_ITEM
std::cerr << "GxsGroupFeedItem::removeItem()";
std::cerr << std::endl;
#endif
if (mFeedHolder)
{
mFeedHolder->lockLayout(this, true);
}
hide();
if (mFeedHolder)
{
mFeedHolder->lockLayout(this, false);
mFeedHolder->deleteFeedItem(this, mFeedId);
}
}
void GxsGroupFeedItem::unsubscribe() void GxsGroupFeedItem::unsubscribe()
{ {
#ifdef DEBUG_ITEM #ifdef DEBUG_ITEM

View File

@ -64,12 +64,9 @@ protected:
protected slots: protected slots:
void subscribe(); void subscribe();
void unsubscribe(); void unsubscribe();
void removeItem();
void copyGroupLink(); void copyGroupLink();
protected: protected:
FeedHolder *mFeedHolder;
uint32_t mFeedId;
bool mIsHome; bool mIsHome;
RsGxsIfaceHelper *mGxsIface; RsGxsIfaceHelper *mGxsIface;
TokenQueue *mLoadQueue; TokenQueue *mLoadQueue;

View File

@ -52,17 +52,15 @@ GxsChannelDialog::GxsChannelDialog(QWidget *parent)
{ {
mEventHandlerId = 0; mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread! // Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); rsEvents->registerEventsHandler(RsEventType::GXS_CHANNELS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
} }
void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
{ {
if(event->mType == RsEventType::GXS_CHANNELS) const RsGxsChannelEvent *e = dynamic_cast<const RsGxsChannelEvent*>(event.get());
{
const RsGxsChannelEvent *e = dynamic_cast<const RsGxsChannelEvent*>(event.get());
if(!e) if(!e)
return; return;
switch(e->mChannelEventCode) switch(e->mChannelEventCode)
{ {
@ -71,7 +69,6 @@ void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> ev
default: default:
break; break;
} }
}
} }
GxsChannelDialog::~GxsChannelDialog() GxsChannelDialog::~GxsChannelDialog()

View File

@ -132,17 +132,15 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
mEventHandlerId = 0; mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread! // Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); rsEvents->registerEventsHandler(RsEventType::GXS_CHANNELS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
} }
void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
{ {
if(event->mType == RsEventType::GXS_CHANNELS) const RsGxsChannelEvent *e = dynamic_cast<const RsGxsChannelEvent*>(event.get());
{
const RsGxsChannelEvent *e = dynamic_cast<const RsGxsChannelEvent*>(event.get());
if(!e) if(!e)
return; return;
switch(e->mChannelEventCode) switch(e->mChannelEventCode)
{ {
@ -156,7 +154,6 @@ void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEven
default: default:
break; break;
} }
}
} }
GxsChannelPostsWidget::~GxsChannelPostsWidget() GxsChannelPostsWidget::~GxsChannelPostsWidget()
@ -233,8 +230,12 @@ QScrollArea *GxsChannelPostsWidget::getScrollArea()
return NULL; return NULL;
} }
void GxsChannelPostsWidget::deleteFeedItem(QWidget * /*item*/, uint32_t /*type*/) void GxsChannelPostsWidget::deleteFeedItem(FeedItem *feedItem, uint32_t /*type*/)
{ {
if (!feedItem)
return;
ui->feedWidget->removeFeedItem(feedItem);
} }
void GxsChannelPostsWidget::openChat(const RsPeerId & /*peerId*/) void GxsChannelPostsWidget::openChat(const RsPeerId & /*peerId*/)
@ -460,7 +461,7 @@ void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost& post, bool re
if(!post.mMeta.mOrigMsgId.isNull()) if(!post.mMeta.mOrigMsgId.isNull())
{ {
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mOrigMsgId); FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(post.mMeta.mOrigMsgId)) ;
item = dynamic_cast<GxsChannelPostItem*>(feedItem); item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if(item) if(item)
@ -476,7 +477,7 @@ void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost& post, bool re
if (related) if (related)
{ {
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mMsgId); FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(post.mMeta.mMsgId)) ;
item = dynamic_cast<GxsChannelPostItem*>(feedItem); item = dynamic_cast<GxsChannelPostItem*>(feedItem);
} }
if (item) { if (item) {
@ -669,7 +670,7 @@ void GxsChannelPostsWidget::blank()
bool GxsChannelPostsWidget::navigatePostItem(const RsGxsMessageId &msgId) bool GxsChannelPostsWidget::navigatePostItem(const RsGxsMessageId &msgId)
{ {
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(groupId(), msgId); FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(msgId));
if (!feedItem) { if (!feedItem) {
return false; return false;
} }
@ -718,17 +719,17 @@ void GxsChannelPostsWidget::toggleAutoDownload()
return; return;
} }
RsQThreadUtils::postToObject( [=]() // RsQThreadUtils::postToObject( [=]()
{ // {
/* Here it goes any code you want to be executed on the Qt Gui // /* Here it goes any code you want to be executed on the Qt Gui
* thread, for example to update the data model with new information // * thread, for example to update the data model with new information
* after a blocking call to RetroShare API complete, note that // * after a blocking call to RetroShare API complete, note that
* Qt::QueuedConnection is important! // * Qt::QueuedConnection is important!
*/ // */
//
std::cerr << __PRETTY_FUNCTION__ << " Has been executed on GUI " // std::cerr << __PRETTY_FUNCTION__ << " Has been executed on GUI "
<< "thread but was scheduled by async thread" << std::endl; // << "thread but was scheduled by async thread" << std::endl;
}, this ); // }, this );
}); });
} }

View File

@ -58,7 +58,7 @@ public:
/* FeedHolder */ /* FeedHolder */
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(FeedItem *feedItem, uint32_t type);
virtual void openChat(const RsPeerId& peerId); virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title); virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title);

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>880</width> <width>977</width>
<height>557</height> <height>628</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
@ -369,7 +369,7 @@
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="textInteractionFlags"> <property name="textInteractionFlags">
@ -525,7 +525,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
</item> </item>
<item> <item>
<widget class="GxsFeedWidget" name="feedWidget" native="true"> <widget class="RSFeedWidget" name="feedWidget" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -572,22 +572,22 @@ p, li { white-space: pre-wrap; }
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
<header location="global">gui/common/LineEditClear.h</header> <header location="global">gui/common/LineEditClear.h</header>
</customwidget> </customwidget>
<customwidget>
<class>GxsFeedWidget</class>
<extends>QWidget</extends>
<header>gui/gxs/GxsFeedWidget.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>GxsChannelFilesWidget</class> <class>GxsChannelFilesWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>gui/gxschannels/GxsChannelFilesWidget.h</header> <header>gui/gxschannels/GxsChannelFilesWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>RSFeedWidget</class>
<extends>QWidget</extends>
<header>gui/common/RSFeedWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../images.qrc"/>
<include location="../icons.qrc"/> <include location="../icons.qrc"/>
<include location="../images.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -436,7 +436,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
mEventHandlerId = 0; mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread! // Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); rsEvents->registerEventsHandler(RsEventType::GXS_FORUMS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
} }
void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -45,7 +45,7 @@ GxsForumsDialog::GxsForumsDialog(QWidget *parent)
mEventHandlerId = 0; mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread! // Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId ); rsEvents->registerEventsHandler(RsEventType::GXS_FORUMS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
} }
void GxsForumsDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event) void GxsForumsDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -39,11 +39,9 @@ RsGxsUpdateBroadcast::RsGxsUpdateBroadcast(RsGxsIfaceHelper *ifaceImpl) :
{ {
mEventHandlerId = 0; // forces initialization in registerEventsHandler() mEventHandlerId = 0; // forces initialization in registerEventsHandler()
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) rsEvents->registerEventsHandler(RsEventType::GXS_CHANGES, [this](std::shared_ptr<const RsEvent> event)
{ {
if(event->mType == RsEventType::GXS_CHANGES) onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get()));
onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get()));
}, mEventHandlerId ); }, mEventHandlerId );
} }