diff --git a/libretroshare/src/grouter/grouteritems.cc b/libretroshare/src/grouter/grouteritems.cc index 14c3164c5..b67ed71e6 100644 --- a/libretroshare/src/grouter/grouteritems.cc +++ b/libretroshare/src/grouter/grouteritems.cc @@ -45,17 +45,18 @@ RsItem *RsGRouterSerialiser::deserialise(void *data, uint32_t *pktsize) switch(getRsItemSubType(rstype)) { - case RS_PKT_SUBTYPE_GROUTER_DATA: return deserialise_RsGRouterGenericDataItem (data, *pktsize); - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK: return deserialise_RsGRouterTransactionChunkItem(data, *pktsize); - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN: return deserialise_RsGRouterTransactionAcknItem (data, *pktsize); - case RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT: return deserialise_RsGRouterSignedReceiptItem (data, *pktsize); - case RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES: return deserialise_RsGRouterMatrixCluesItem (data, *pktsize); - case RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST: return deserialise_RsGRouterMatrixFriendListItem(data, *pktsize); - case RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO: return deserialise_RsGRouterRoutingInfoItem (data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_DATA: return deserialise_RsGRouterGenericDataItem (data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK: return deserialise_RsGRouterTransactionChunkItem(data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN: return deserialise_RsGRouterTransactionAcknItem (data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT: return deserialise_RsGRouterSignedReceiptItem (data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES: return deserialise_RsGRouterMatrixCluesItem (data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK: return deserialise_RsGRouterMatrixTrackItem (data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST: return deserialise_RsGRouterMatrixFriendListItem(data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO: return deserialise_RsGRouterRoutingInfoItem (data, *pktsize); - default: - std::cerr << "RsGRouterSerialiser::deserialise(): Could not de-serialise item. SubPacket id = " << std::hex << getRsItemSubType(rstype) << " id = " << rstype << std::dec << std::endl; - return NULL; + default: + std::cerr << "RsGRouterSerialiser::deserialise(): Could not de-serialise item. SubPacket id = " << std::hex << getRsItemSubType(rstype) << " id = " << rstype << std::dec << std::endl; + return NULL; } return NULL; } @@ -269,6 +270,28 @@ RsGRouterMatrixFriendListItem *RsGRouterSerialiser::deserialise_RsGRouterMatrixF return item; } + +RsGRouterMatrixTrackItem *RsGRouterSerialiser::deserialise_RsGRouterMatrixTrackItem(void *data, uint32_t pktsize) const +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + + RsGRouterMatrixTrackItem *item = new RsGRouterMatrixTrackItem() ; + + ok &= item->provider_id.deserialise(data, pktsize, offset) ; + ok &= item->message_id.deserialise(data,pktsize,offset) ; + ok &= getRawTimeT(data, pktsize, &offset, item->time_stamp) ; + + if (offset != rssize || !ok) + { + std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl; + delete item; + return NULL ; + } + + return item; +} RsGRouterMatrixCluesItem *RsGRouterSerialiser::deserialise_RsGRouterMatrixCluesItem(void *data, uint32_t pktsize) const { uint32_t offset = 8; // skip the header @@ -559,6 +582,17 @@ uint32_t RsGRouterMatrixFriendListItem::serial_size() const return s ; } + +uint32_t RsGRouterMatrixTrackItem::serial_size() const +{ + uint32_t s = 8 ; // header + s += 8 ; // time_stamp + s += RsPeerId::SIZE_IN_BYTES; // provider_id + s += RsMessageId::SIZE_IN_BYTES; // message_id + + return s ; +} + uint32_t RsGRouterRoutingInfoItem::serial_size() const { uint32_t s = 8 ; // header @@ -637,6 +671,26 @@ bool RsGRouterMatrixCluesItem::serialise(void *data,uint32_t& size) const return ok; } +bool RsGRouterMatrixTrackItem::serialise(void *data,uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= provider_id.serialise(data, tlvsize, offset) ; + ok &= message_id.serialise(data,tlvsize,offset) ; + ok &= setRawTimeT(data, tlvsize, &offset, time_stamp) ; + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsGRouterMatrixTrackItem::serialisedata() size error! " << std::endl; + } + + return ok; +} bool FriendTrialRecord::deserialise(void *data,uint32_t& offset,uint32_t size) { bool ok = true ; @@ -701,6 +755,7 @@ bool RsGRouterRoutingInfoItem::serialise(void *data,uint32_t& size) const // ------------------------------------- IO --------------------------------------- // // -----------------------------------------------------------------------------------// // + std::ostream& RsGRouterSignedReceiptItem::print(std::ostream& o, uint16_t) { o << "RsGRouterReceiptItem:" << std::endl ; @@ -746,6 +801,15 @@ std::ostream& RsGRouterRoutingInfoItem::print(std::ostream& o, uint16_t) return o ; } +std::ostream& RsGRouterMatrixTrackItem::print(std::ostream& o, uint16_t) +{ + o << "RsGRouterMatrixTrackItem:" << std::endl ; + o << " provider_id: " << provider_id << std::endl; + o << " message_id: " << message_id << std::endl; + o << " time_stamp: " << time_stamp << std::endl; + + return o ; +} std::ostream& RsGRouterMatrixCluesItem::print(std::ostream& o, uint16_t) { o << "RsGRouterMatrixCluesItem:" << std::endl ; diff --git a/libretroshare/src/grouter/grouteritems.h b/libretroshare/src/grouter/grouteritems.h index ea42eea61..574c7b3c4 100644 --- a/libretroshare/src/grouter/grouteritems.h +++ b/libretroshare/src/grouter/grouteritems.h @@ -33,20 +33,19 @@ #include "retroshare/rsgrouter.h" #include "groutermatrix.h" -const uint8_t RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY = 0x01 ; // used to publish a key -const uint8_t RS_PKT_SUBTYPE_GROUTER_ACK_deprecated = 0x03 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT_deprecated = 0x04 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated = 0x05 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated2 = 0x06 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x07 ; // used to send data to a destination (Signed by source) -const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT = 0x08 ; // long-distance acknowledgement of data received - -const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK = 0x10 ; // chunk of data. Used internally. -const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN = 0x11 ; // acknowledge for finished transaction. Not necessary, but increases fiability. - -const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES = 0x80 ; // item to save matrix clues -const uint8_t RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST = 0x82 ; // item to save friend lists -const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO = 0x93 ; // +const uint8_t RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY = 0x01 ; // used to publish a key +const uint8_t RS_PKT_SUBTYPE_GROUTER_ACK_deprecated = 0x03 ; // don't use! +const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT_deprecated = 0x04 ; // don't use! +const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated = 0x05 ; // don't use! +const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated2 = 0x06 ; // don't use! +const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x07 ; // used to send data to a destination (Signed by source) +const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT = 0x08 ; // long-distance acknowledgement of data received +const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK = 0x10 ; // chunk of data. Used internally. +const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN = 0x11 ; // acknowledge for finished transaction. Not necessary, but increases fiability. +const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES = 0x80 ; // item to save matrix clues +const uint8_t RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST = 0x82 ; // item to save friend lists +const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO = 0x93 ; // +const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK = 0x94 ; // item to save matrix track info const uint8_t QOS_PRIORITY_RS_GROUTER = 4 ; // relevant for items that travel through friends @@ -243,6 +242,24 @@ class RsGRouterMatrixCluesItem: public RsGRouterItem std::list clues ; }; +class RsGRouterMatrixTrackItem: public RsGRouterItem +{ + public: + RsGRouterMatrixTrackItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK) + { setPriorityLevel(0) ; } // this item is never sent through the network + + virtual bool serialise(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; + + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; + + // packet data + // + RsGxsMessageId message_id ; + RsPeerId provider_id ; + time_t time_stamp ; +}; class RsGRouterMatrixFriendListItem: public RsGRouterItem { public: @@ -317,6 +334,7 @@ private: RsGRouterTransactionAcknItem *deserialise_RsGRouterTransactionAcknItem(void *data,uint32_t size) const ; RsGRouterSignedReceiptItem *deserialise_RsGRouterSignedReceiptItem(void *data,uint32_t size) const ; RsGRouterMatrixCluesItem *deserialise_RsGRouterMatrixCluesItem(void *data,uint32_t size) const ; + RsGRouterMatrixTrackItem *deserialise_RsGRouterMatrixTrackItem(void *data,uint32_t size) const ; RsGRouterMatrixFriendListItem *deserialise_RsGRouterMatrixFriendListItem(void *data,uint32_t size) const ; RsGRouterRoutingInfoItem *deserialise_RsGRouterRoutingInfoItem(void *data,uint32_t size) const ; }; diff --git a/libretroshare/src/grouter/groutermatrix.cc b/libretroshare/src/grouter/groutermatrix.cc index 1401f6a6c..4da0d02ed 100644 --- a/libretroshare/src/grouter/groutermatrix.cc +++ b/libretroshare/src/grouter/groutermatrix.cc @@ -27,13 +27,55 @@ #include "groutermatrix.h" #include "grouteritems.h" -//#define ROUTING_MATRIX_DEBUG +#define ROUTING_MATRIX_DEBUG GRouterMatrix::GRouterMatrix() { _proba_need_updating = true ; } +bool GRouterMatrix::addTrackingInfo(const RsGxsMessageId& mid,const RsPeerId& source_friend) +{ + time_t now = time(NULL) ; + + RoutingTrackEntry rte ; + + rte.friend_id = source_friend ; + rte.time_stamp = now ; + + _tracking_clues[mid] = rte ; +#ifdef ROUTING_MATRIX_DEBUG + std::cerr << "GRouterMatrix::addTrackingInfo(): Added clue mid=" << mid << ", from " << source_friend << " ID=" << source_friend << std::endl; +#endif + return true ; +} + +bool GRouterMatrix::cleanUp() +{ + // remove all tracking entries that have become too old. + +#ifdef ROUTING_MATRIX_DEBUG + std::cerr << "GRouterMatrix::cleanup()" << std::endl; +#endif + time_t now = time(NULL) ; + + for(std::map::iterator it(_tracking_clues.begin());it!=_tracking_clues.end();) + if(it->second.time_stamp + RS_GROUTER_MAX_KEEP_TRACKING_CLUES < now) + { +#ifdef ROUTING_MATRIX_DEBUG + std::cerr << " removing old entry msgId=" << it->first << ", from id " << it->second.friend_id << ", obtained " << (now - it->second.time_stamp) << " secs ago." << std::endl; +#endif + std::map::iterator tmp(it) ; + ++tmp ; + _tracking_clues.erase(it) ; + it=tmp ; + } + else + ++it ; + + return true ; +} + bool GRouterMatrix::addRoutingClue(const GRouterKeyId& key_id,const RsPeerId& source_friend,float weight) { // 1 - get the friend index. @@ -115,7 +157,19 @@ void GRouterMatrix::getListOfKnownKeys(std::vector& key_ids) const key_ids.clear() ; for(std::map >::const_iterator it(_time_combined_hits.begin());it!=_time_combined_hits.end();++it) - key_ids.push_back(it->first) ; + key_ids.push_back(it->first) ; +} + +bool GRouterMatrix::getTrackingInfo(const RsGxsMessageId& mid, RsPeerId &source_friend) +{ + std::map::const_iterator it = _tracking_clues.find(mid) ; + + if(it == _tracking_clues.end()) + return false ; + + source_friend = it->second.friend_id; + + return true ; } void GRouterMatrix::debugDump() const @@ -143,6 +197,10 @@ void GRouterMatrix::debugDump() const std::cerr << it->second[i] << " " ; std::cerr << std::endl; } + std::cerr << " Tracking clues: " << std::endl; + + for(std::map::const_iterator it(_tracking_clues.begin());it!=_tracking_clues.end();++it) + std::cerr << " " << it->first << ": from " << it->second.friend_id << " " << now - it->second.time_stamp << " secs ago." << std::endl; } bool GRouterMatrix::computeRoutingProbabilities(const GRouterKeyId& key_id, const std::vector& friends, std::vector& probas) const @@ -241,55 +299,78 @@ bool GRouterMatrix::saveList(std::list& items) std::cerr << " GRoutingMatrix::saveList()" << std::endl; #endif - RsGRouterMatrixFriendListItem *item = new RsGRouterMatrixFriendListItem ; + RsGRouterMatrixFriendListItem *item = new RsGRouterMatrixFriendListItem ; - item->reverse_friend_indices = _reverse_friend_indices ; - items.push_back(item) ; + item->reverse_friend_indices = _reverse_friend_indices ; + items.push_back(item) ; - for(std::map >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) - { - RsGRouterMatrixCluesItem *item = new RsGRouterMatrixCluesItem ; + for(std::map >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) + { + RsGRouterMatrixCluesItem *item = new RsGRouterMatrixCluesItem ; - item->destination_key = it->first ; - item->clues = it->second ; + item->destination_key = it->first ; + item->clues = it->second ; - items.push_back(item) ; - } + items.push_back(item) ; + } - return true ; + for(std::map::const_iterator it(_tracking_clues.begin());it!=_tracking_clues.end();++it) + { + RsGRouterMatrixTrackItem *item = new RsGRouterMatrixTrackItem ; + + item->provider_id = it->second.friend_id ; + item->time_stamp = it->second.time_stamp ; + item->message_id = it->first ; + + items.push_back(item) ; + } + + return true ; } bool GRouterMatrix::loadList(std::list& items) { - RsGRouterMatrixFriendListItem *itm1 = NULL ; - RsGRouterMatrixCluesItem *itm2 = NULL ; + RsGRouterMatrixFriendListItem *itm1 = NULL ; + RsGRouterMatrixCluesItem *itm2 = NULL ; + RsGRouterMatrixTrackItem *itm3 = NULL ; #ifdef ROUTING_MATRIX_DEBUG std::cerr << " GRoutingMatrix::loadList()" << std::endl; #endif - for(std::list::const_iterator it(items.begin());it!=items.end();++it) - { - if(NULL != (itm2 = dynamic_cast(*it))) - { + for(std::list::const_iterator it(items.begin());it!=items.end();++it) + { + if(NULL != (itm3 = dynamic_cast(*it))) + { #ifdef ROUTING_MATRIX_DEBUG - std::cerr << " initing routing clues." << std::endl; + std::cerr << " initing tracking clues." << std::endl; +#endif + RoutingTrackEntry rte ; + rte.friend_id = itm3->provider_id ; + rte.time_stamp = itm3->time_stamp ; + + _tracking_clues[itm3->message_id] = rte; + } + if(NULL != (itm2 = dynamic_cast(*it))) + { +#ifdef ROUTING_MATRIX_DEBUG + std::cerr << " initing routing clues." << std::endl; #endif - _routing_clues[itm2->destination_key] = itm2->clues ; - _proba_need_updating = true ; // notifies to re-compute all the info. - } - if(NULL != (itm1 = dynamic_cast(*it))) - { - _reverse_friend_indices = itm1->reverse_friend_indices ; - _friend_indices.clear() ; + _routing_clues[itm2->destination_key] = itm2->clues ; + _proba_need_updating = true ; // notifies to re-compute all the info. + } + if(NULL != (itm1 = dynamic_cast(*it))) + { + _reverse_friend_indices = itm1->reverse_friend_indices ; + _friend_indices.clear() ; - for(uint32_t i=0;i<_reverse_friend_indices.size();++i) - _friend_indices[_reverse_friend_indices[i]] = i ; + for(uint32_t i=0;i<_reverse_friend_indices.size();++i) + _friend_indices[_reverse_friend_indices[i]] = i ; - _proba_need_updating = true ; // notifies to re-compute all the info. - } - } + _proba_need_updating = true ; // notifies to re-compute all the info. + } + } - return true ; + return true ; } diff --git a/libretroshare/src/grouter/groutermatrix.h b/libretroshare/src/grouter/groutermatrix.h index 4c9ddee95..18c0cb189 100644 --- a/libretroshare/src/grouter/groutermatrix.h +++ b/libretroshare/src/grouter/groutermatrix.h @@ -42,6 +42,12 @@ struct RoutingMatrixHitEntry time_t time_stamp ; }; +struct RoutingTrackEntry +{ + RsPeerId friend_id ; // not the full key. Gets too big otherwise! + time_t time_stamp ; +}; + class GRouterMatrix { public: @@ -61,15 +67,19 @@ class GRouterMatrix // Record one routing clue. The events can possibly be merged in time buckets. // bool addRoutingClue(const GRouterKeyId& id,const RsPeerId& source_friend,float weight) ; + bool addTrackingInfo(const RsGxsMessageId& id,const RsPeerId& source_friend) ; bool saveList(std::list& items) ; bool loadList(std::list& items) ; + bool cleanUp() ; + // Dump info in terminal. // void debugDump() const ; void getListOfKnownKeys(std::vector& key_ids) const ; + bool getTrackingInfo(const RsGxsMessageId& id,RsPeerId& source_friend); private: // returns the friend id, possibly creating a new id. // @@ -81,8 +91,9 @@ class GRouterMatrix // List of events received and computed routing probabilities // - std::map > _routing_clues ; // received routing clues. Should be saved. - std::map > _time_combined_hits ; // hit matrix after time-convolution filter + std::map > _routing_clues ; // received routing clues. Should be saved. + std::map > _time_combined_hits ; // hit matrix after time-convolution filter + std::map _tracking_clues ; // who provided the most recent messages // This is used to avoid re-computing probas when new events have been received. // @@ -93,6 +104,5 @@ class GRouterMatrix // std::map _friend_indices ; // index for each friend to lookup in the routing matrix Not saved. std::vector _reverse_friend_indices ;// SSLid corresponding to each friend index. Saved. - }; diff --git a/libretroshare/src/grouter/groutertypes.h b/libretroshare/src/grouter/groutertypes.h index 0a3900421..3c4897b0a 100644 --- a/libretroshare/src/grouter/groutertypes.h +++ b/libretroshare/src/grouter/groutertypes.h @@ -37,9 +37,10 @@ class RsGRouterSignedReceiptItem ; static const uint16_t GROUTER_CLIENT_ID_MESSAGES = 0x1001 ; -static const uint32_t RS_GROUTER_MATRIX_MAX_HIT_ENTRIES = 10 ; // max number of clues to store -static const uint32_t RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS = 60 ; // can be set to up to half the publish time interval. Prevents flooding routes. -static const uint32_t RS_GROUTER_MIN_CONFIG_SAVE_PERIOD = 5 ; // at most save config every 5 seconds +static const uint32_t RS_GROUTER_MATRIX_MAX_HIT_ENTRIES = 10 ; // max number of clues to store +static const uint32_t RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS = 60 ; // can be set to up to half the publish time interval. Prevents flooding routes. +static const uint32_t RS_GROUTER_MIN_CONFIG_SAVE_PERIOD = 10 ; // at most save config every 10 seconds +static const uint32_t RS_GROUTER_MAX_KEEP_TRACKING_CLUES = 86400*10 ; // max time for which we keep record of tracking info: 10 days. static const float RS_GROUTER_BASE_WEIGHT_ROUTED_MSG = 1.0f ; // base contribution of routed message clue to routing matrix static const float RS_GROUTER_BASE_WEIGHT_GXS_PACKET = 0.1f ; // base contribution of GXS message to routing matrix @@ -56,7 +57,7 @@ static const uint32_t MAX_INACTIVE_DATA_PIPE_DELAY = 300 ; // cl static const time_t RS_GROUTER_DEBUG_OUTPUT_PERIOD = 10 ; // Output everything static const time_t RS_GROUTER_AUTOWASH_PERIOD = 10 ; // Autowash every minute. Not a costly operation. -static const time_t RS_GROUTER_MATRIX_UPDATE_PERIOD = 1 *10 ; // Check for key advertising every 10 minutes +static const time_t RS_GROUTER_MATRIX_UPDATE_PERIOD = 60*10 ; // Check for key advertising every 10 minutes static const uint32_t GROUTER_ITEM_MAX_CACHE_KEEP_TIME = 2*86400 ; // Cached items are kept for 48 hours at most. static const uint32_t RS_GROUTER_DATA_STATUS_UNKNOWN = 0x0000 ; // unknown. Unused. diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc index 421d2c97c..8ed41178c 100644 --- a/libretroshare/src/grouter/p3grouter.cc +++ b/libretroshare/src/grouter/p3grouter.cc @@ -252,6 +252,7 @@ int p3GRouter::tick() _last_matrix_update_time = now ; _routing_matrix.updateRoutingProbabilities() ; // This should be locked. + _routing_matrix.cleanUp() ; // This should be locked. } #ifdef GROUTER_DEBUG @@ -1698,6 +1699,15 @@ bool p3GRouter::locked_getClientAndServiceId(const TurtleFileHash& hash, const R return true ; } +void p3GRouter::addTrackingInfo(const RsGxsMessageId& mid,const RsPeerId& peer_id) +{ + RS_STACK_MUTEX(grMtx) ; +#ifdef GROUTER_DEBUG + grouter_debug() << "Received new routing clue for key " << mid << " from peer " << peer_id << std::endl; +#endif + _routing_matrix.addTrackingInfo(mid,peer_id) ; + _changed = true ; +} void p3GRouter::addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) { RS_STACK_MUTEX(grMtx) ; @@ -1705,6 +1715,7 @@ void p3GRouter::addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) grouter_debug() << "Received new routing clue for key " << id << " from peer " << peer_id << std::endl; #endif _routing_matrix.addRoutingClue(id,peer_id,RS_GROUTER_BASE_WEIGHT_GXS_PACKET) ; + _changed = true ; } bool p3GRouter::registerClientService(const GRouterServiceId& id,GRouterClientService *service) @@ -2154,6 +2165,13 @@ bool p3GRouter::getRoutingCacheInfo(std::vector& infos) return true ; } +bool p3GRouter::getTrackingInfo(const RsGxsMessageId &mid, RsPeerId &provider_id) +{ + RS_STACK_MUTEX(grMtx) ; + + return _routing_matrix.getTrackingInfo(mid,provider_id) ; +} + // Dump everything // void p3GRouter::debugDump() @@ -2214,8 +2232,8 @@ void p3GRouter::debugDump() grouter_debug() << " Routing matrix: " << std::endl; -// if(_debug_enabled) - // _routing_matrix.debugDump() ; + if(_debug_enabled) + _routing_matrix.debugDump() ; } diff --git a/libretroshare/src/grouter/p3grouter.h b/libretroshare/src/grouter/p3grouter.h index 2d8f744cd..0dbadd345 100644 --- a/libretroshare/src/grouter/p3grouter.h +++ b/libretroshare/src/grouter/p3grouter.h @@ -130,6 +130,7 @@ public: //===================================================// virtual void addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) ; + virtual void addTrackingInfo(const RsGxsMessageId& mid,const RsPeerId& peer_id) ; //===================================================// // Client/server request services // @@ -167,6 +168,7 @@ public: // - Cache state (memory size, etc) // virtual bool getRoutingCacheInfo(std::vector& info) ; + virtual bool getTrackingInfo(const RsGxsMessageId& mid, RsPeerId& provider_id) ; //===================================================// // Derived from p3Service // @@ -300,7 +302,6 @@ private: // GRouterMatrix _routing_matrix ; - // Stores the keys which identify the router's node. For each key, a structure holds: // - the client service // - flags diff --git a/libretroshare/src/gxs/gxssecurity.cc b/libretroshare/src/gxs/gxssecurity.cc index 6c1474f3f..1895993ee 100644 --- a/libretroshare/src/gxs/gxssecurity.cc +++ b/libretroshare/src/gxs/gxssecurity.cc @@ -681,12 +681,25 @@ bool GxsSecurity::validateNxsGrp(const RsNxsGrp& grp, const RsTlvKeySignature& s EVP_VerifyInit(mdctx, EVP_sha1()); EVP_VerifyUpdate(mdctx, allGrpData, allGrpDataLen); int signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); + EVP_MD_CTX_destroy(mdctx); - delete[] allGrpData ; + if(signOk != 1) // try previous API. This is a hack to accept groups previously signed with old APIs. + { + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_VerifyInit(mdctx, EVP_sha1()); + EVP_VerifyUpdate(mdctx, allGrpData, allGrpDataLen-4); // that means ommit the last + signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); + EVP_MD_CTX_destroy(mdctx); + + if(signOk) + std::cerr << "(WW) GXS group with old API found. Signature still checks!" << std::endl; + } + + delete[] allGrpData ; /* clean up */ EVP_PKEY_free(signKey); - EVP_MD_CTX_destroy(mdctx); grpMeta.signSet = signSet; diff --git a/libretroshare/src/gxs/rsdataservice.cc b/libretroshare/src/gxs/rsdataservice.cc index 68308d207..fe53c03e4 100644 --- a/libretroshare/src/gxs/rsdataservice.cc +++ b/libretroshare/src/gxs/rsdataservice.cc @@ -49,19 +49,19 @@ #define MSG_INDEX_GRPID std::string("INDEX_MESSAGES_GRPID") // generic -#define KEY_NXS_DATA std::string("nxsData") -#define KEY_NXS_DATA_LEN std::string("nxsDataLen") -#define KEY_NXS_IDENTITY std::string("identity") -#define KEY_GRP_ID std::string("grpId") -#define KEY_ORIG_GRP_ID std::string("origGrpId") -#define KEY_PARENT_GRP_ID std::string("parentGrpId") -#define KEY_SIGN_SET std::string("signSet") -#define KEY_TIME_STAMP std::string("timeStamp") -#define KEY_NXS_FLAGS std::string("flags") -#define KEY_NXS_META std::string("meta") +#define KEY_NXS_DATA std::string("nxsData") +#define KEY_NXS_DATA_LEN std::string("nxsDataLen") +#define KEY_NXS_IDENTITY std::string("identity") +#define KEY_GRP_ID std::string("grpId") +#define KEY_ORIG_GRP_ID std::string("origGrpId") +#define KEY_PARENT_GRP_ID std::string("parentGrpId") +#define KEY_SIGN_SET std::string("signSet") +#define KEY_TIME_STAMP std::string("timeStamp") +#define KEY_NXS_FLAGS std::string("flags") +#define KEY_NXS_META std::string("meta") #define KEY_NXS_SERV_STRING std::string("serv_str") -#define KEY_NXS_HASH std::string("hash") -#define KEY_RECV_TS std::string("recv_time_stamp") +#define KEY_NXS_HASH std::string("hash") +#define KEY_RECV_TS std::string("recv_time_stamp") // remove later #define KEY_NXS_FILE_OLD std::string("nxsFile") @@ -94,8 +94,8 @@ #define KEY_MSG_NAME std::string("msgName") // msg local -#define KEY_MSG_STATUS std::string("msgStatus") -#define KEY_CHILD_TS std::string("childTs") +#define KEY_MSG_STATUS std::string("msgStatus") +#define KEY_CHILD_TS std::string("childTs") // database release columns #define KEY_DATABASE_RELEASE_ID std::string("id") @@ -129,22 +129,22 @@ RsDataService::RsDataService(const std::string &serviceDir, const std::string &d initialise(isNewDatabase); // for retrieving msg meta - mColMsgMeta_GrpId = addColumn(mMsgMetaColumns, KEY_GRP_ID); - mColMsgMeta_TimeStamp = addColumn(mMsgMetaColumns, KEY_TIME_STAMP); - mColMsgMeta_NxsFlags = addColumn(mMsgMetaColumns, KEY_NXS_FLAGS); - mColMsgMeta_SignSet = addColumn(mMsgMetaColumns, KEY_SIGN_SET); - mColMsgMeta_NxsIdentity = addColumn(mMsgMetaColumns, KEY_NXS_IDENTITY); - mColMsgMeta_NxsHash = addColumn(mMsgMetaColumns, KEY_NXS_HASH); - mColMsgMeta_MsgId = addColumn(mMsgMetaColumns, KEY_MSG_ID); - mColMsgMeta_OrigMsgId = addColumn(mMsgMetaColumns, KEY_ORIG_MSG_ID); - mColMsgMeta_MsgStatus = addColumn(mMsgMetaColumns, KEY_MSG_STATUS); - mColMsgMeta_ChildTs = addColumn(mMsgMetaColumns, KEY_CHILD_TS); - mColMsgMeta_MsgParentId = addColumn(mMsgMetaColumns, KEY_MSG_PARENT_ID); - mColMsgMeta_MsgThreadId = addColumn(mMsgMetaColumns, KEY_MSG_THREAD_ID); - mColMsgMeta_Name = addColumn(mMsgMetaColumns, KEY_MSG_NAME); + mColMsgMeta_GrpId = addColumn(mMsgMetaColumns, KEY_GRP_ID); + mColMsgMeta_TimeStamp = addColumn(mMsgMetaColumns, KEY_TIME_STAMP); + mColMsgMeta_NxsFlags = addColumn(mMsgMetaColumns, KEY_NXS_FLAGS); + mColMsgMeta_SignSet = addColumn(mMsgMetaColumns, KEY_SIGN_SET); + mColMsgMeta_NxsIdentity = addColumn(mMsgMetaColumns, KEY_NXS_IDENTITY); + mColMsgMeta_NxsHash = addColumn(mMsgMetaColumns, KEY_NXS_HASH); + mColMsgMeta_MsgId = addColumn(mMsgMetaColumns, KEY_MSG_ID); + mColMsgMeta_OrigMsgId = addColumn(mMsgMetaColumns, KEY_ORIG_MSG_ID); + mColMsgMeta_MsgStatus = addColumn(mMsgMetaColumns, KEY_MSG_STATUS); + mColMsgMeta_ChildTs = addColumn(mMsgMetaColumns, KEY_CHILD_TS); + mColMsgMeta_MsgParentId = addColumn(mMsgMetaColumns, KEY_MSG_PARENT_ID); + mColMsgMeta_MsgThreadId = addColumn(mMsgMetaColumns, KEY_MSG_THREAD_ID); + mColMsgMeta_Name = addColumn(mMsgMetaColumns, KEY_MSG_NAME); mColMsgMeta_NxsServString = addColumn(mMsgMetaColumns, KEY_NXS_SERV_STRING); - mColMsgMeta_RecvTs = addColumn(mMsgMetaColumns, KEY_RECV_TS); - mColMsgMeta_NxsDataLen = addColumn(mMsgMetaColumns, KEY_NXS_DATA_LEN); + mColMsgMeta_RecvTs = addColumn(mMsgMetaColumns, KEY_RECV_TS); + mColMsgMeta_NxsDataLen = addColumn(mMsgMetaColumns, KEY_NXS_DATA_LEN); // for retrieving actual data mColMsg_GrpId = addColumn(mMsgColumns, KEY_GRP_ID); @@ -158,31 +158,31 @@ RsDataService::RsDataService(const std::string &serviceDir, const std::string &d mMsgColumnsWithMeta.insert(mMsgColumnsWithMeta.end(), mMsgMetaColumns.begin(), mMsgMetaColumns.end()); // for retrieving grp meta data - mColGrpMeta_GrpId = addColumn(mGrpMetaColumns, KEY_GRP_ID); - mColGrpMeta_TimeStamp = addColumn(mGrpMetaColumns, KEY_TIME_STAMP); - mColGrpMeta_NxsFlags = addColumn(mGrpMetaColumns, KEY_NXS_FLAGS); + mColGrpMeta_GrpId = addColumn(mGrpMetaColumns, KEY_GRP_ID); + mColGrpMeta_TimeStamp = addColumn(mGrpMetaColumns, KEY_TIME_STAMP); + mColGrpMeta_NxsFlags = addColumn(mGrpMetaColumns, KEY_NXS_FLAGS); // mColGrpMeta_SignSet = addColumn(mGrpMetaColumns, KEY_SIGN_SET); mColGrpMeta_NxsIdentity = addColumn(mGrpMetaColumns, KEY_NXS_IDENTITY); - mColGrpMeta_NxsHash = addColumn(mGrpMetaColumns, KEY_NXS_HASH); - mColGrpMeta_KeySet = addColumn(mGrpMetaColumns, KEY_KEY_SET); - mColGrpMeta_SubscrFlag = addColumn(mGrpMetaColumns, KEY_GRP_SUBCR_FLAG); - mColGrpMeta_Pop = addColumn(mGrpMetaColumns, KEY_GRP_POP); - mColGrpMeta_MsgCount = addColumn(mGrpMetaColumns, KEY_MSG_COUNT); - mColGrpMeta_Status = addColumn(mGrpMetaColumns, KEY_GRP_STATUS); - mColGrpMeta_Name = addColumn(mGrpMetaColumns, KEY_GRP_NAME); - mColGrpMeta_LastPost = addColumn(mGrpMetaColumns, KEY_GRP_LAST_POST); - mColGrpMeta_OrigGrpId = addColumn(mGrpMetaColumns, KEY_ORIG_GRP_ID); - mColGrpMeta_ServString = addColumn(mGrpMetaColumns, KEY_NXS_SERV_STRING); - mColGrpMeta_SignFlags = addColumn(mGrpMetaColumns, KEY_GRP_SIGN_FLAGS); - mColGrpMeta_CircleId = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_ID); - mColGrpMeta_CircleType = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_TYPE); + mColGrpMeta_NxsHash = addColumn(mGrpMetaColumns, KEY_NXS_HASH); + mColGrpMeta_KeySet = addColumn(mGrpMetaColumns, KEY_KEY_SET); + mColGrpMeta_SubscrFlag = addColumn(mGrpMetaColumns, KEY_GRP_SUBCR_FLAG); + mColGrpMeta_Pop = addColumn(mGrpMetaColumns, KEY_GRP_POP); + mColGrpMeta_MsgCount = addColumn(mGrpMetaColumns, KEY_MSG_COUNT); + mColGrpMeta_Status = addColumn(mGrpMetaColumns, KEY_GRP_STATUS); + mColGrpMeta_Name = addColumn(mGrpMetaColumns, KEY_GRP_NAME); + mColGrpMeta_LastPost = addColumn(mGrpMetaColumns, KEY_GRP_LAST_POST); + mColGrpMeta_OrigGrpId = addColumn(mGrpMetaColumns, KEY_ORIG_GRP_ID); + mColGrpMeta_ServString = addColumn(mGrpMetaColumns, KEY_NXS_SERV_STRING); + mColGrpMeta_SignFlags = addColumn(mGrpMetaColumns, KEY_GRP_SIGN_FLAGS); + mColGrpMeta_CircleId = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_ID); + mColGrpMeta_CircleType = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_TYPE); mColGrpMeta_InternCircle = addColumn(mGrpMetaColumns, KEY_GRP_INTERNAL_CIRCLE); - mColGrpMeta_Originator = addColumn(mGrpMetaColumns, KEY_GRP_ORIGINATOR); + mColGrpMeta_Originator = addColumn(mGrpMetaColumns, KEY_GRP_ORIGINATOR); mColGrpMeta_AuthenFlags = addColumn(mGrpMetaColumns, KEY_GRP_AUTHEN_FLAGS); mColGrpMeta_ParentGrpId = addColumn(mGrpMetaColumns, KEY_PARENT_GRP_ID); - mColGrpMeta_RecvTs = addColumn(mGrpMetaColumns, KEY_RECV_TS); - mColGrpMeta_RepCutoff = addColumn(mGrpMetaColumns, KEY_GRP_REP_CUTOFF); - mColGrpMeta_NxsDataLen = addColumn(mGrpMetaColumns, KEY_NXS_DATA_LEN); + mColGrpMeta_RecvTs = addColumn(mGrpMetaColumns, KEY_RECV_TS); + mColGrpMeta_RepCutoff = addColumn(mGrpMetaColumns, KEY_GRP_REP_CUTOFF); + mColGrpMeta_NxsDataLen = addColumn(mGrpMetaColumns, KEY_NXS_DATA_LEN); // for retrieving actual grp data mColGrp_GrpId = addColumn(mGrpColumns, KEY_GRP_ID); @@ -630,7 +630,6 @@ RsGxsMsgMetaData* RsDataService::locked_getMsgMeta(RetroCursor &c, int colOffset c.getString(mColMsgMeta_NxsHash + colOffset, temp); msgMeta->mHash = RsFileHash(temp); msgMeta->recvTS = c.getInt32(mColMsgMeta_RecvTs + colOffset); - offset = 0; data = (char*)c.getData(mColMsgMeta_SignSet + colOffset, data_len); msgMeta->signSet.GetTlv(data, data_len, &offset); diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index a4450a1c6..70d52eb68 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -33,6 +33,7 @@ #include "retroshare/rsgxsflags.h" #include "retroshare/rsgxscircles.h" #include "retroshare/rsgrouter.h" +#include "retroshare/rspeers.h" #include "rsgixs.h" #include "rsgxsutil.h" #include "rsserver/p3face.h" @@ -49,6 +50,14 @@ #define PRIV_GRP_OFFSET 16 #define GRP_OPTIONS_OFFSET 24 +// Authentication key indices. Used to store them in a map +// these where originally flags, but used as indexes. Still, we need +// to keep their old values to ensure backward compatibility. + +static const uint32_t INDEX_AUTHEN_IDENTITY = 0x00000010; // identity +static const uint32_t INDEX_AUTHEN_PUBLISH = 0x00000020; // publish key +static const uint32_t INDEX_AUTHEN_ADMIN = 0x00000040; // admin key + #define GXS_MASK "GXS_MASK_HACK" //#define GEN_EXCH_DEBUG 1 @@ -416,7 +425,7 @@ uint8_t RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& privateKe bool ok = GxsSecurity::getSignature(allGrpData, allGrpDataLen, privAdminKey, adminSign); // add admin sign to grpMeta - meta->signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_ADMIN] = adminSign; + meta->signSet.keySignSet[INDEX_AUTHEN_ADMIN] = adminSign; RsTlvBinaryData grpData(mServType); grpData.setBinData(allGrpData, allGrpDataLen); @@ -462,8 +471,10 @@ int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBin if ((!grpMeta.mAuthorId.isNull()) || checkAuthenFlag(pos, author_flag)) { needIdentitySign = true; +#ifdef GEN_EXCH_DEBUG std::cerr << "Needs Identity sign! (Service Flags)"; std::cerr << std::endl; +#endif } if (needIdentitySign) @@ -494,25 +505,29 @@ int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBin id_ret = SIGN_FAIL; } - signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_IDENTITY] = sign; + signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign; } else { mGixs->requestPrivateKey(grpMeta.mAuthorId); +#ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::createGroupSignatures(): "; std::cerr << " ERROR AUTHOR KEY: " << grpMeta.mAuthorId << " is not Cached / available for Message Signing\n"; std::cerr << "RsGenExchange::createGroupSignatures(): Requestiong AUTHOR KEY"; std::cerr << std::endl; +#endif id_ret = SIGN_FAIL_TRY_LATER; } } else { +#ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::createGroupSignatures()"; std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; +#endif id_ret = SIGN_FAIL; } } @@ -532,8 +547,10 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar bool publishSignSuccess = false; +#ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::createMsgSignatures() for Msg.mMsgName: " << msgMeta.mMsgName; std::cerr << std::endl; +#endif // publish signature is determined by whether group is public or not @@ -568,23 +585,29 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar if (checkAuthenFlag(pos, publish_flag)) { needPublishSign = true; +#ifdef GEN_EXCH_DEBUG std::cerr << "Needs Publish sign! (Service Flags)"; std::cerr << std::endl; +#endif } // Check required permissions, and allow them to sign it - if they want too - as well! if (checkAuthenFlag(pos, author_flag)) { needIdentitySign = true; +#ifdef GEN_EXCH_DEBUG std::cerr << "Needs Identity sign! (Service Flags)"; std::cerr << std::endl; +#endif } if (!msgMeta.mAuthorId.isNull()) { needIdentitySign = true; +#ifdef GEN_EXCH_DEBUG std::cerr << "Needs Identity sign! (AuthorId Exists)"; std::cerr << std::endl; +#endif } if(needPublishSign) @@ -609,12 +632,12 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar // private publish key publishKey = &(mit->second); - RsTlvKeySignature publishSign = signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH]; + RsTlvKeySignature publishSign = signSet.keySignSet[INDEX_AUTHEN_PUBLISH]; publishSignSuccess = GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, *publishKey, publishSign); //place signature in msg meta - signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH] = publishSign; + signSet.keySignSet[INDEX_AUTHEN_PUBLISH] = publishSign; }else { std::cerr << "RsGenExchange::createMsgSignatures()"; @@ -653,25 +676,29 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar id_ret = SIGN_FAIL; } - signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_IDENTITY] = sign; + signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign; } else { mGixs->requestPrivateKey(msgMeta.mAuthorId); +#ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::createMsgSignatures(): "; std::cerr << " ERROR AUTHOR KEY: " << msgMeta.mAuthorId << " is not Cached / available for Message Signing\n"; std::cerr << "RsGenExchange::createMsgSignatures(): Requestiong AUTHOR KEY"; std::cerr << std::endl; +#endif id_ret = SIGN_FAIL_TRY_LATER; } } else { +#ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::createMsgSignatures()"; std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; +#endif id_ret = SIGN_FAIL; } } @@ -763,7 +790,7 @@ int RsGenExchange::createMessage(RsNxsMsg* msg) } } -int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecurityKeySet& grpKeySet) +int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uint32_t& signFlag, RsTlvSecurityKeySet& grpKeySet) { bool needIdentitySign = false; bool needPublishSign = false; @@ -796,12 +823,16 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecu if ((checkAuthenFlag(pos, author_flag)) || (!msg->metaData->mAuthorId.isNull())) needIdentitySign = true; +#ifdef GEN_EXCH_DEBUG + std::cerr << "Validate message: msgId=" << msg->msgId << ", grpId=" << msg->grpId << " grpFlags=" << std::hex << grpFlag << std::dec + << ". Need publish=" << needPublishSign << ", needIdentitySign=" << needIdentitySign ; +#endif RsGxsMsgMetaData& metaData = *(msg->metaData); if(needPublishSign) { - RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH]; + RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_PUBLISH]; std::map& keys = grpKeySet.keys; std::map::iterator mit = keys.begin(); @@ -849,31 +880,65 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecu bool haveKey = mGixs->haveKey(metaData.mAuthorId); if(haveKey) - { + { - RsTlvSecurityKey authorKey; - bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ; + RsTlvSecurityKey authorKey; + bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ; - if (auth_key_fetched) + if (auth_key_fetched) + { + RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY]; + idValidate &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey); + mGixs->timeStampKey(metaData.mAuthorId) ; + } + else + { + std::cerr << "RsGenExchange::validateMsg()"; + std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Message Validation"; + std::cerr << std::endl; + idValidate = false; + } + + if(idValidate) + { + // get key data and check that the key is actually PGP-linked. If not, reject the post. + + RsIdentityDetails details ; + + if(!mGixs->getIdDetails(metaData.mAuthorId,details)) + { + // the key cannot ke reached, although it's in cache. Weird situation. + std::cerr << "RsGenExchange::validateMsg(): cannot get key data for ID=" << metaData.mAuthorId << ", although it's supposed to be already in cache. Cannot validate." << std::endl; + idValidate = false ; + } + else + { + + // now check reputation of the message author + float reputation_threshold = ( (signFlag & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) && !details.mPgpLinked) ? (RsReputations::REPUTATION_THRESHOLD_ANTI_SPAM): (RsReputations::REPUTATION_THRESHOLD_DEFAULT) ; + + if(details.mReputation.mOverallReputationScore < reputation_threshold) { - - RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_IDENTITY]; - idValidate &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey); - mGixs->timeStampKey(metaData.mAuthorId) ; +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::validateMsg(): message from " << metaData.mAuthorId << ", rejected because reputation score (" << details.mReputation.mOverallReputationScore <<") is below the accepted threshold (" << reputation_threshold << ")" << std::endl; +#endif + idValidate = false ; } else - { - std::cerr << "RsGenExchange::validateMsg()"; - std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Message Validation"; - std::cerr << std::endl; - idValidate = false; - } + std::cerr << "RsGenExchange::validateMsg(): message from " << metaData.mAuthorId << ", accepted. Reputation score (" << details.mReputation.mOverallReputationScore <<") is above accepted threshold (" << reputation_threshold << ")" << std::endl; + } - }else + } + } + else { std::list peers; peers.push_back(msg->PeerId()); mGixs->requestKey(metaData.mAuthorId, peers); + +#ifdef GEN_EXCH_DEBUG + std::cerr << ", Key missing. Retry later." << std::endl; +#endif return VALIDATE_FAIL_TRY_LATER; } } @@ -890,6 +955,10 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecu idValidate = true; } +#ifdef GEN_EXCH_DEBUG + std::cerr << ", publish val=" << publishValidate << ", idValidate=" << idValidate << ". Result=" << (publishValidate && idValidate) << std::endl; +#endif + if(publishValidate && idValidate) return VALIDATE_SUCCESS; else @@ -911,8 +980,10 @@ int RsGenExchange::validateGrp(RsNxsGrp* grp) if ((!metaData.mAuthorId.isNull()) || checkAuthenFlag(pos, author_flag)) { needIdentitySign = true; +#ifdef GEN_EXCH_DEBUG std::cerr << "Needs Identity sign! (Service Flags)"; std::cerr << std::endl; +#endif } if(needIdentitySign) @@ -930,7 +1001,7 @@ int RsGenExchange::validateGrp(RsNxsGrp* grp) if (auth_key_fetched) { - RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_IDENTITY]; + RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY]; idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey); mGixs->timeStampKey(metaData.mAuthorId) ; @@ -1753,8 +1824,10 @@ bool RsGenExchange::processGrpMask(const RsGxsGroupId& grpId, ContentValue &grpC grpMeta = mit->second; if (!grpMeta) { +#ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::processGrpMask() Ignore update for not existing grp id " << grpId.toStdString(); std::cerr << std::endl; +#endif return false; } ok = true; @@ -1927,6 +2000,10 @@ void RsGenExchange::publishMsgs() msgId = msg->msgId; grpId = msg->grpId; msg->metaData->recvTS = time(NULL); + + mRoutingClues[msg->metaData->mAuthorId].insert(rsPeers->getOwnId()) ; + mTrackingClues.push_back(std::make_pair(msg->msgId,rsPeers->getOwnId())) ; + computeHash(msg->msg, msg->metaData->mHash); mDataAccess->addMsgData(msg); msgChangeMap[grpId].push_back(msgId); @@ -2060,13 +2137,18 @@ void RsGenExchange::processGroupUpdatePublish() void RsGenExchange::processRoutingClues() { - RS_STACK_MUTEX(mGenMtx) ; + RS_STACK_MUTEX(mGenMtx) ; for(std::map >::const_iterator it = mRoutingClues.begin();it!=mRoutingClues.end();++it) for(std::set::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - rsGRouter->addRoutingClue(GRouterKeyId(it->first),(*it2)) ; + rsGRouter->addRoutingClue(GRouterKeyId(it->first),(*it2) ) ; mRoutingClues.clear() ; + + for(std::list >::const_iterator it = mTrackingClues.begin();it!=mTrackingClues.end();++it) + rsGRouter->addTrackingInfo((*it).first,(*it).second) ; + + mTrackingClues.clear() ; } void RsGenExchange::processGroupDelete() { @@ -2439,201 +2521,208 @@ void RsGenExchange::computeHash(const RsTlvBinaryData& data, RsFileHash& hash) void RsGenExchange::processRecvdMessages() { - RS_STACK_MUTEX(mGenMtx) ; + RS_STACK_MUTEX(mGenMtx) ; #ifdef GEN_EXCH_DEBUG - if(!mMsgPendingValidate.empty()) - std::cerr << "processing received messages" << std::endl; + if(!mMsgPendingValidate.empty()) + std::cerr << "processing received messages" << std::endl; #endif - NxsMsgPendingVect::iterator pend_it = mMsgPendingValidate.begin(); + NxsMsgPendingVect::iterator pend_it = mMsgPendingValidate.begin(); #ifdef GEN_EXCH_DEBUG - if(!mMsgPendingValidate.empty()) - std::cerr << " pending validation" << std::endl; + if(!mMsgPendingValidate.empty()) + std::cerr << " pending validation" << std::endl; #endif - for(; pend_it != mMsgPendingValidate.end();) - { - GxsPendingItem& gpsi = *pend_it; + for(; pend_it != mMsgPendingValidate.end();) + { + GxsPendingItem& gpsi = *pend_it; #ifdef GEN_EXCH_DEBUG - std::cerr << " grp=" << gpsi.mId.first << ", msg=" << gpsi.mId.second << ", attempts=" << gpsi.mAttempts ; + std::cerr << " grp=" << gpsi.mId.first << ", msg=" << gpsi.mId.second << ", attempts=" << gpsi.mAttempts ; #endif - if(gpsi.mAttempts == VALIDATE_MAX_ATTEMPTS) - { + if(gpsi.mAttempts == VALIDATE_MAX_ATTEMPTS) + { #ifdef GEN_EXCH_DEBUG std::cerr << " = max! deleting." << std::endl; #endif - delete gpsi.mItem; - pend_it = mMsgPendingValidate.erase(pend_it); - } - else - { + delete gpsi.mItem; + pend_it = mMsgPendingValidate.erase(pend_it); + } + else + { #ifdef GEN_EXCH_DEBUG std::cerr << " movign to recvd." << std::endl; #endif - mReceivedMsgs.push_back(gpsi.mItem); - ++pend_it; - } - } + mReceivedMsgs.push_back(gpsi.mItem); + ++pend_it; + } + } - if(mReceivedMsgs.empty()) - return; + if(mReceivedMsgs.empty()) + return; - std::vector::iterator vit = mReceivedMsgs.begin(); - GxsMsgReq msgIds; - std::map msgs; + std::vector::iterator vit = mReceivedMsgs.begin(); + GxsMsgReq msgIds; + std::map msgs; - std::map grpMetas; + std::map grpMetas; - // coalesce group meta retrieval for performance - for(; vit != mReceivedMsgs.end(); ++vit) - { - RsNxsMsg* msg = *vit; - grpMetas.insert(std::make_pair(msg->grpId, (RsGxsGrpMetaData*)NULL)); - } + // coalesce group meta retrieval for performance + for(; vit != mReceivedMsgs.end(); ++vit) + { + RsNxsMsg* msg = *vit; + grpMetas.insert(std::make_pair(msg->grpId, (RsGxsGrpMetaData*)NULL)); + } - mDataStore->retrieveGxsGrpMetaData(grpMetas); + mDataStore->retrieveGxsGrpMetaData(grpMetas); #ifdef GEN_EXCH_DEBUG - std::cerr << " updating received messages:" << std::endl; + std::cerr << " updating received messages:" << std::endl; #endif - for(vit = mReceivedMsgs.begin(); vit != mReceivedMsgs.end(); ++vit) - { - RsNxsMsg* msg = *vit; - RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); + for(vit = mReceivedMsgs.begin(); vit != mReceivedMsgs.end(); ++vit) + { + RsNxsMsg* msg = *vit; + RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); - bool ok = false; + bool ok = false; - if(msg->meta.bin_len != 0) - ok = meta->deserialise(msg->meta.bin_data, &(msg->meta.bin_len)); + if(msg->meta.bin_len != 0) + ok = meta->deserialise(msg->meta.bin_data, &(msg->meta.bin_len)); - msg->metaData = meta; + msg->metaData = meta; #ifdef GEN_EXCH_DEBUG - std::cerr << " deserialised info: grp id=" << meta->mGroupId << ", msg id=" << meta->mMsgId ; + std::cerr << " deserialised info: grp id=" << meta->mGroupId << ", msg id=" << meta->mMsgId ; #endif - uint8_t validateReturn = VALIDATE_FAIL; + uint8_t validateReturn = VALIDATE_FAIL; - if(ok) - { - std::map::iterator mit = grpMetas.find(msg->grpId); + if(ok) + { + std::map::iterator mit = grpMetas.find(msg->grpId); #ifdef GEN_EXCH_DEBUG - std::cerr << " msg info : grp id=" << msg->grpId << ", msg id=" << msg->msgId << std::endl; + std::cerr << " msg info : grp id=" << msg->grpId << ", msg id=" << msg->msgId << std::endl; #endif + RsGxsGrpMetaData* grpMeta = NULL ; - // validate msg - if(mit != grpMetas.end()) - { - RsGxsGrpMetaData* grpMeta = mit->second; - validateReturn = validateMsg(msg, grpMeta->mGroupFlags, grpMeta->keys); -#ifdef GEN_EXCH_DEBUG - std::cerr << " message validation result: " << validateReturn << std::endl; -#endif - } - - if(validateReturn == VALIDATE_SUCCESS) - { - meta->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - msgs.insert(std::make_pair(msg, meta)); - - std::vector &msgv = msgIds[msg->grpId]; - if (std::find(msgv.begin(), msgv.end(), msg->msgId) == msgv.end()) - { - msgv.push_back(msg->msgId); - } - - NxsMsgPendingVect::iterator validated_entry = std::find(mMsgPendingValidate.begin(), mMsgPendingValidate.end(), - getMsgIdPair(*msg)); - - if(validated_entry != mMsgPendingValidate.end()) mMsgPendingValidate.erase(validated_entry); - - computeHash(msg->msg, meta->mHash); - meta->recvTS = time(NULL); -#ifdef GEN_EXCH_DEBUG - std::cerr << " new status flags: " << meta->mMsgStatus << std::endl; - std::cerr << " computed hash: " << meta->mHash << std::endl; - std::cerr << "Message received. Identity=" << msg->metaData->mAuthorId << ", from peer " << msg->PeerId() << std::endl; -#endif - - if(!msg->metaData->mAuthorId.isNull()) - mRoutingClues[msg->metaData->mAuthorId].insert(msg->PeerId()) ; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " deserialisation failed!" <second; + validateReturn = validateMsg(msg, grpMeta->mGroupFlags, grpMeta->mSignFlags, grpMeta->keys); #ifdef GEN_EXCH_DEBUG - std::cerr << "failed to deserialise incoming meta, msgId: " - << "msg->grpId: " << msg->grpId << ", msgId: " << msg->msgId << std::endl; + std::cerr << " grpMeta.mSignFlags: " << std::hex << grpMeta->mSignFlags << std::dec << std::endl; + std::cerr << " grpMeta.mAuthFlags: " << std::hex << grpMeta->mAuthenFlags << std::dec << std::endl; + std::cerr << " message validation result: " << (int)validateReturn << std::endl; +#endif + } + + if(validateReturn == VALIDATE_SUCCESS) + { + meta->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + msgs.insert(std::make_pair(msg, meta)); + + std::vector &msgv = msgIds[msg->grpId]; + if (std::find(msgv.begin(), msgv.end(), msg->msgId) == msgv.end()) + { + msgv.push_back(msg->msgId); + } + + NxsMsgPendingVect::iterator validated_entry = std::find(mMsgPendingValidate.begin(), mMsgPendingValidate.end(), + getMsgIdPair(*msg)); + + if(validated_entry != mMsgPendingValidate.end()) mMsgPendingValidate.erase(validated_entry); + + computeHash(msg->msg, meta->mHash); + meta->recvTS = time(NULL); +#ifdef GEN_EXCH_DEBUG + std::cerr << " new status flags: " << meta->mMsgStatus << std::endl; + std::cerr << " computed hash: " << meta->mHash << std::endl; + std::cerr << "Message received. Identity=" << msg->metaData->mAuthorId << ", from peer " << msg->PeerId() << std::endl; #endif - NxsMsgPendingVect::iterator failed_entry = std::find(mMsgPendingValidate.begin(), mMsgPendingValidate.end(), - getMsgIdPair(*msg)); + if(!msg->metaData->mAuthorId.isNull()) + mRoutingClues[msg->metaData->mAuthorId].insert(msg->PeerId()) ; - if(failed_entry != mMsgPendingValidate.end()) mMsgPendingValidate.erase(failed_entry); + if(grpMeta->mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) + mTrackingClues.push_back(std::make_pair(msg->msgId,msg->PeerId())) ; + } + } + else + { +#ifdef GEN_EXCH_DEBUG + std::cerr << " deserialisation failed!" <grpId: " << msg->grpId << ", msgId: " << msg->msgId << std::endl; +#endif + + NxsMsgPendingVect::iterator failed_entry = std::find(mMsgPendingValidate.begin(), mMsgPendingValidate.end(), + getMsgIdPair(*msg)); + + if(failed_entry != mMsgPendingValidate.end()) mMsgPendingValidate.erase(failed_entry); delete msg; - } - else if(validateReturn == VALIDATE_FAIL_TRY_LATER) - { + } + else if(validateReturn == VALIDATE_FAIL_TRY_LATER) + { #ifdef GEN_EXCH_DEBUG - std::cerr << "failed to validate msg, trying again: " - << "msg->grpId: " << msg->grpId << ", msgId: " << msg->msgId << std::endl; + std::cerr << "failed to validate msg, trying again: " + << "msg->grpId: " << msg->grpId << ", msgId: " << msg->msgId << std::endl; #endif - RsGxsGrpMsgIdPair id; - id.first = msg->grpId; - id.second = msg->msgId; + RsGxsGrpMsgIdPair id; + id.first = msg->grpId; + id.second = msg->msgId; - // first check you haven't made too many attempts + // first check you haven't made too many attempts - NxsMsgPendingVect::iterator vit = std::find( - mMsgPendingValidate.begin(), mMsgPendingValidate.end(), id); + NxsMsgPendingVect::iterator vit = std::find( + mMsgPendingValidate.begin(), mMsgPendingValidate.end(), id); - if(vit == mMsgPendingValidate.end()) - { - GxsPendingItem item(msg, id); - mMsgPendingValidate.push_back(item); - }else - { + if(vit == mMsgPendingValidate.end()) + { + GxsPendingItem item(msg, id); + mMsgPendingValidate.push_back(item); + }else + { vit->mAttempts++; - } - } - } + } + } + } - // clean up resources from group meta retrieval - freeAndClearContainerResource, - RsGxsGrpMetaData*>(grpMetas); + // clean up resources from group meta retrieval + freeAndClearContainerResource, + RsGxsGrpMetaData*>(grpMetas); - if(!msgIds.empty()) - { + if(!msgIds.empty()) + { #ifdef GEN_EXCH_DEBUG - std::cerr << " removing existing and old messages from incoming list." << std::endl; + std::cerr << " removing existing and old messages from incoming list." << std::endl; #endif - removeDeleteExistingMessages(msgs, msgIds); + removeDeleteExistingMessages(msgs, msgIds); #ifdef GEN_EXCH_DEBUG - std::cerr << " storing remaining messages" << std::endl; + std::cerr << " storing remaining messages" << std::endl; #endif - mDataStore->storeMessage(msgs); + mDataStore->storeMessage(msgs); - RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_RECEIVE, false); - c->msgChangeMap = msgIds; - mNotifications.push_back(c); - } + RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_RECEIVE, false); + c->msgChangeMap = msgIds; + mNotifications.push_back(c); + } - mReceivedMsgs.clear(); + mReceivedMsgs.clear(); } void RsGenExchange::processRecvdGroups() @@ -2706,8 +2795,7 @@ void RsGenExchange::processRecvdGroups() else if(ret == VALIDATE_FAIL) { #ifdef GEN_EXCH_DEBUG - std::cerr << "failed to deserialise incoming meta, grpId: " - << grp->grpId << std::endl; + std::cerr << "failed to validate incoming meta, grpId: " << grp->grpId << ": wrong signature" << std::endl; #endif delete grp; erase = true; @@ -2716,8 +2804,7 @@ void RsGenExchange::processRecvdGroups() { #ifdef GEN_EXCH_DEBUG - std::cerr << "failed to validate incoming grp, trying again. grpId: " - << grp->grpId << std::endl; + std::cerr << "failed to validate incoming grp, trying again. grpId: " << grp->grpId << std::endl; #endif if(gpsi.mAttempts == VALIDATE_MAX_ATTEMPTS) @@ -2733,6 +2820,7 @@ void RsGenExchange::processRecvdGroups() } else { + std::cerr << "(EE) deserialise error in group meta data" << std::endl; delete grp; delete meta; erase = true; @@ -2817,7 +2905,7 @@ void RsGenExchange::performUpdateValidation() bool RsGenExchange::updateValid(RsGxsGrpMetaData& oldGrpMeta, RsNxsGrp& newGrp) const { std::map& signSet = newGrp.metaData->signSet.keySignSet; - std::map::iterator mit = signSet.find(GXS_SERV::FLAG_AUTHEN_ADMIN); + std::map::iterator mit = signSet.find(INDEX_AUTHEN_ADMIN); if(mit == signSet.end()) { @@ -2896,7 +2984,9 @@ void RsGenExchange::removeDeleteExistingMessages( RsGeneralDataService::MsgStore { const RsGxsMessageId::std_vector& msgIds = msgIdReq[cit2->second->mGroupId]; +#ifdef GEN_EXCH_DEBUG std::cerr << " grpid=" << cit2->second->mGroupId << ", msgid=" << cit2->second->mMsgId ; +#endif // Avoid storing messages that are already in the database, as well as messages that are too old (or generally do not pass the database storage test) // diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index ba59dcaac..1462b0285 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -739,12 +739,13 @@ private: /*! * Attempts to validate msg signatures * @param msg message to be validated - * @param grpFlag the flag for the group the message belongs to + * @param grpFlag the distribution flag for the group the message belongs to + * @param grpFlag the signature flag for the group the message belongs to * @param grpKeySet the key set user has for the message's group * @return VALIDATE_SUCCESS for success, VALIDATE_FAIL for fail, * VALIDATE_ID_SIGN_NOT_AVAIL for Id sign key not avail (but requested) */ - int validateMsg(RsNxsMsg* msg, const uint32_t& grpFlag, RsTlvSecurityKeySet& grpKeySet); + int validateMsg(RsNxsMsg* msg, const uint32_t& grpFlag, const uint32_t &signFlag, RsTlvSecurityKeySet& grpKeySet); /*! * Attempts to validate group signatures @@ -862,7 +863,7 @@ private: std::vector mGroupDeletePublish; std::map > mRoutingClues ; - + std::list > mTrackingClues ; }; #endif // RSGENEXCHANGE_H diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h index 19590baa9..cf13a77d3 100644 --- a/libretroshare/src/gxs/rsgixs.h +++ b/libretroshare/src/gxs/rsgixs.h @@ -166,6 +166,7 @@ public: */ virtual bool getKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; virtual bool getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; // For signing outgoing messages. + virtual bool getIdDetails(const RsGxsId& id, RsIdentityDetails& details) = 0 ; // Proxy function so that we get p3Identity info from Gxs #ifdef SUSPENDED #endif diff --git a/libretroshare/src/gxs/rsgxsdata.cc b/libretroshare/src/gxs/rsgxsdata.cc index 36ae1f155..927c73dda 100644 --- a/libretroshare/src/gxs/rsgxsdata.cc +++ b/libretroshare/src/gxs/rsgxsdata.cc @@ -28,6 +28,11 @@ #include "serialiser/rsbaseserial.h" #include "serialiser/rstlvbase.h" +static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0001 = 0x0000 ; // change this, and keep old values if the content changes +static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0002 = 0xaf01 ; // current API + +static const uint32_t RS_GXS_MSG_META_DATA_VERSION_ID_0001 = 0x0000 ; // current API + RsGxsGrpMetaData::RsGxsGrpMetaData() { clear(); @@ -46,10 +51,11 @@ uint32_t RsGxsGrpMetaData::serial_size() s += GetTlvStringSize(mServiceString); s += signSet.TlvSize(); s += keys.TlvSize(); - s += 4; // for mCircleType + s += 4; // for mCircleType s += mCircleId.serial_size(); - s += 4; // mAuthenFlag - s += mParentGrpId.serial_size(); + s += 4; // mAuthenFlag + s += mParentGrpId.serial_size(); // mParentGroupId + s += 4; // mSignFlag return s; } @@ -104,7 +110,7 @@ bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize) bool ok = true; - ok &= setRsItemHeader(data, tlvsize, 0, tlvsize); + ok &= setRsItemHeader(data, tlvsize, RS_GXS_GRP_META_DATA_VERSION_ID_0002, tlvsize); #ifdef GXS_DEBUG std::cerr << "RsGxsGrpMetaData serialise()" << std::endl; @@ -130,6 +136,7 @@ bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize) ok &= signSet.SetTlv(data, tlvsize, &offset); ok &= keys.SetTlv(data, tlvsize, &offset); + ok &= setRawUInt32(data, tlvsize, &offset, mSignFlags); // new in API v2. Was previously missing. Kept in the end for backward compatibility return ok; } @@ -154,12 +161,31 @@ bool RsGxsGrpMetaData::deserialise(void *data, uint32_t &pktsize) ok &= getRawUInt32(data, pktsize, &offset, &mPublishTs); ok &= getRawUInt32(data, pktsize, &offset, &mCircleType); ok &= getRawUInt32(data, pktsize, &offset, &mAuthenFlags); + + ok &= mAuthorId.deserialise(data, pktsize, offset); ok &= GetTlvString(data, pktsize, &offset, 0, mServiceString); ok &= mCircleId.deserialise(data, pktsize, offset); ok &= signSet.GetTlv(data, pktsize, &offset); ok &= keys.GetTlv(data, pktsize, &offset); + + switch(getRsItemId(data)) + { + case RS_GXS_GRP_META_DATA_VERSION_ID_0002: ok &= getRawUInt32(data, pktsize, &offset, &mSignFlags); // current API + break ; + case RS_GXS_GRP_META_DATA_VERSION_ID_0001: mSignFlags = 0; // old API. Do not leave this uninitialised! + break ; + + default: + std::cerr << "(EE) RsGxsGrpMetaData::deserialise(): ERROR: unknown API version " << std::hex << getRsItemId(data) << std::dec << std::endl; + } + + if(offset != pktsize) + { + std::cerr << "(EE) RsGxsGrpMetaData::deserialise(): ERROR: unmatched size " << offset << ", expected: " << pktsize << std::dec << std::endl; + return false ; + } #ifdef DROP_NON_CANONICAL_ITEMS if(mGroupName.length() > RsGxsGrpMetaData::MAX_ALLOWED_STRING_SIZE) { @@ -202,8 +228,8 @@ uint32_t RsGxsMsgMetaData::serial_size() s += signSet.TlvSize(); s += GetTlvStringSize(mMsgName); - s += 4; - s += 4; + s += 4; // mPublishTS + s += 4; // mMsgFlags return s; } @@ -239,7 +265,7 @@ bool RsGxsMsgMetaData::serialise(void *data, uint32_t *size) bool ok = true; - ok &= setRsItemHeader(data, tlvsize, 0, tlvsize); + ok &= setRsItemHeader(data, tlvsize, RS_GXS_MSG_META_DATA_VERSION_ID_0001, tlvsize); #ifdef GXS_DEBUG std::cerr << "RsGxsGrpMetaData serialise()" << std::endl; diff --git a/libretroshare/src/gxs/rsgxsdata.h b/libretroshare/src/gxs/rsgxsdata.h index 9829b8bd6..f80dbb862 100644 --- a/libretroshare/src/gxs/rsgxsdata.h +++ b/libretroshare/src/gxs/rsgxsdata.h @@ -52,7 +52,7 @@ public: RsGxsGroupId mGroupId; RsGxsGroupId mOrigGrpId; std::string mGroupName; - uint32_t mGroupFlags; + uint32_t mGroupFlags; // GXS_SERV::FLAG_PRIVACY_RESTRICTED | GXS_SERV::FLAG_PRIVACY_PRIVATE | GXS_SERV::FLAG_PRIVACY_PUBLIC uint32_t mPublishTs; uint32_t mSignFlags; RsGxsId mAuthorId; @@ -123,7 +123,6 @@ public: uint32_t recvTS; RsFileHash mHash; bool validated; - }; diff --git a/libretroshare/src/retroshare/rsgrouter.h b/libretroshare/src/retroshare/rsgrouter.h index 8db40b194..acd3aee10 100644 --- a/libretroshare/src/retroshare/rsgrouter.h +++ b/libretroshare/src/retroshare/rsgrouter.h @@ -102,6 +102,9 @@ public: //===================================================// virtual void addRoutingClue(const GRouterKeyId& destination, const RsPeerId& source) =0; + virtual void addTrackingInfo(const RsGxsMessageId& mid,const RsPeerId& peer_id) =0; + + virtual bool getTrackingInfo(const RsGxsMessageId& mid, RsPeerId& provider_id) =0; }; // To access the GRouter from anywhere diff --git a/libretroshare/src/retroshare/rsgxsflags.h b/libretroshare/src/retroshare/rsgxsflags.h index a7cc27ee4..0b2d78a08 100644 --- a/libretroshare/src/retroshare/rsgxsflags.h +++ b/libretroshare/src/retroshare/rsgxsflags.h @@ -18,48 +18,36 @@ namespace GXS_SERV { /** START privacy **/ - static const uint32_t FLAG_PRIVACY_MASK = 0x0000000f; - - // pub key encrypted - static const uint32_t FLAG_PRIVACY_PRIVATE = 0x00000001; - - // publish private key needed to publish - static const uint32_t FLAG_PRIVACY_RESTRICTED = 0x00000002; - - // anyone can publish, publish key pair not needed - static const uint32_t FLAG_PRIVACY_PUBLIC = 0x00000004; + static const uint32_t FLAG_PRIVACY_MASK = 0x0000000f; + static const uint32_t FLAG_PRIVACY_PRIVATE = 0x00000001; // pub key encrypted + static const uint32_t FLAG_PRIVACY_RESTRICTED = 0x00000002; // publish private key needed to publish + static const uint32_t FLAG_PRIVACY_PUBLIC = 0x00000004; // anyone can publish, publish key pair not needed /** END privacy **/ - /** START authentication **/ - - static const uint32_t FLAG_AUTHEN_MASK = 0x000000f0; - - // identity - static const uint32_t FLAG_AUTHEN_IDENTITY = 0x000000010; - - // publish key - static const uint32_t FLAG_AUTHEN_PUBLISH = 0x000000020; - - // admin key - static const uint32_t FLAG_AUTHEN_ADMIN = 0x00000040; - - // pgp sign identity - static const uint32_t FLAG_AUTHEN_PGP_IDENTITY = 0x00000080; - /** END authentication **/ + + /** START author authentication flags **/ + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_MASK = 0x0000ff00; + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_NONE = 0x00000000; + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG = 0x00000100; + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200; + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400; + static const uint32_t FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES = 0x00000800; + static const uint32_t FLAG_GROUP_SIGN_PUBLISH_MASK = 0x000000ff; + static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED = 0x00000001; + static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002; + static const uint32_t FLAG_GROUP_SIGN_PUBLISH_THREADHEAD = 0x00000004; + static const uint32_t FLAG_GROUP_SIGN_PUBLISH_NONEREQ = 0x00000008; + /** START msg authentication flags **/ - static const uint8_t MSG_AUTHEN_MASK = 0x0f; - - static const uint8_t MSG_AUTHEN_ROOT_PUBLISH_SIGN = 0x01; - + static const uint8_t MSG_AUTHEN_MASK = 0x0f; + static const uint8_t MSG_AUTHEN_ROOT_PUBLISH_SIGN = 0x01; static const uint8_t MSG_AUTHEN_CHILD_PUBLISH_SIGN = 0x02; - - static const uint8_t MSG_AUTHEN_ROOT_AUTHOR_SIGN = 0x04; - - static const uint8_t MSG_AUTHEN_CHILD_AUTHOR_SIGN = 0x08; + static const uint8_t MSG_AUTHEN_ROOT_AUTHOR_SIGN = 0x04; + static const uint8_t MSG_AUTHEN_CHILD_AUTHOR_SIGN = 0x08; /** END msg authentication flags **/ @@ -71,12 +59,9 @@ namespace GXS_SERV { /** START Subscription Flags. (LOCAL) **/ - static const uint32_t GROUP_SUBSCRIBE_ADMIN = 0x01; - - static const uint32_t GROUP_SUBSCRIBE_PUBLISH = 0x02; - - static const uint32_t GROUP_SUBSCRIBE_SUBSCRIBED = 0x04; - + static const uint32_t GROUP_SUBSCRIBE_ADMIN = 0x01; + static const uint32_t GROUP_SUBSCRIBE_PUBLISH = 0x02; + static const uint32_t GROUP_SUBSCRIBE_SUBSCRIBED = 0x04; static const uint32_t GROUP_SUBSCRIBE_NOT_SUBSCRIBED = 0x08; /*! @@ -95,17 +80,12 @@ namespace GXS_SERV { * * NOTE: RsGxsCommentService uses 0x000f0000. */ - static const uint32_t GXS_MSG_STATUS_GEN_MASK = 0x0000ffff; - + static const uint32_t GXS_MSG_STATUS_GEN_MASK = 0x0000ffff; static const uint32_t GXS_MSG_STATUS_UNPROCESSED = 0x00000001; - - static const uint32_t GXS_MSG_STATUS_GUI_UNREAD = 0x00000002; - - static const uint32_t GXS_MSG_STATUS_GUI_NEW = 0x00000004; - - static const uint32_t GXS_MSG_STATUS_KEEP = 0x00000008; - - static const uint32_t GXS_MSG_STATUS_DELETE = 0x000000020; + static const uint32_t GXS_MSG_STATUS_GUI_UNREAD = 0x00000002; + static const uint32_t GXS_MSG_STATUS_GUI_NEW = 0x00000004; + static const uint32_t GXS_MSG_STATUS_KEEP = 0x00000008; + static const uint32_t GXS_MSG_STATUS_DELETE = 0x00000020; /** END GXS Msg status flags **/ @@ -123,10 +103,13 @@ namespace GXS_SERV { #define IS_MSG_NEW(status) (status & GXS_SERV::GXS_MSG_STATUS_GUI_NEW) #define IS_MSG_UNREAD(status) (status & GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD) +#define IS_GROUP_PGP_AUTHED(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) +#define IS_GROUP_MESSAGE_TRACKING(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) + #define IS_GROUP_ADMIN(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) -#define IS_GROUP_PUBLISHER(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH) +#define IS_GROUP_PUBLISHER(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH) #define IS_GROUP_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) -#define IS_GROUP_NOT_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED) +#define IS_GROUP_NOT_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED) #define IS_MSG_UNPROCESSED(status) (status & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h index 433eb8368..807f45f40 100644 --- a/libretroshare/src/retroshare/rsreputations.h +++ b/libretroshare/src/retroshare/rsreputations.h @@ -31,6 +31,9 @@ class RsReputations { public: + static const float REPUTATION_THRESHOLD_ANTI_SPAM = 1.4f ; + static const float REPUTATION_THRESHOLD_DEFAULT = 1.0f ; + // This is the interface file for the reputation system // enum Opinion { OPINION_NEGATIVE = 0, OPINION_NEUTRAL = 1, OPINION_POSITIVE = 2 } ; diff --git a/libretroshare/src/serialiser/rsgxsitems.cc b/libretroshare/src/serialiser/rsgxsitems.cc index 2fc738cab..9971514ec 100644 --- a/libretroshare/src/serialiser/rsgxsitems.cc +++ b/libretroshare/src/serialiser/rsgxsitems.cc @@ -24,7 +24,6 @@ this->mPublishTs = rGxsMeta.mPublishTs; this->mThreadId = rGxsMeta.mThreadId; this->mServiceString = rGxsMeta.mServiceString; - } diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.cc b/libretroshare/src/serialiser/rsgxsreputationitems.cc index cdd82f733..379cf4330 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.cc +++ b/libretroshare/src/serialiser/rsgxsreputationitems.cc @@ -34,6 +34,9 @@ #include +// re-defined here, in order to avoid cross-includes +#define REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE 0x0100 + /*************************************************************************/ bool RsReputationItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) const @@ -148,6 +151,7 @@ uint32_t RsGxsReputationSetItem::serial_size() const s += mGxsId.serial_size() ; s += 4 ; // mOwnOpinion s += 4 ; // mOwnOpinionTS + s += 4 ; // mIdentityFlags s += 4 ; // mOpinions.size() @@ -201,6 +205,7 @@ bool RsGxsReputationConfigItem::serialise(void *data, uint32_t& pktsize) const return ok; } + bool RsGxsReputationSetItem::serialise(void *data, uint32_t& pktsize) const { uint32_t tlvsize ; @@ -214,6 +219,7 @@ bool RsGxsReputationSetItem::serialise(void *data, uint32_t& pktsize) const ok &= mGxsId.serialise(data,tlvsize,offset) ; ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinion); ok &= setRawUInt32(data, tlvsize, &offset, mOwnOpinionTS); + ok &= setRawUInt32(data, tlvsize, &offset, mIdentityFlags) ; ok &= setRawUInt32(data, tlvsize, &offset, mOpinions.size()); for(std::map::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it) @@ -303,6 +309,45 @@ RsGxsReputationConfigItem *RsGxsReputationSerialiser::deserialiseReputationConfi return item; } +RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem_deprecated(void *data,uint32_t tlvsize) +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + + RsGxsReputationSetItem *item = new RsGxsReputationSetItem() ; + + /* add mandatory parts first */ + ok &= item->mGxsId.deserialise(data, tlvsize, offset) ; + ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinion); + ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinionTS); + + item->mIdentityFlags = REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE; // special value that means please update me. + + uint32_t S ; + ok &= getRawUInt32(data, tlvsize, &offset, &S); + + for(int i=0;ok && imOpinions[pid] = op ; + } + + if (offset != rssize || !ok) + { + std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl; + delete item; + return NULL ; + } + + return item; +} RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem(void *data,uint32_t tlvsize) { uint32_t offset = 8; // skip the header @@ -315,6 +360,7 @@ RsGxsReputationSetItem *RsGxsReputationSerialiser::deserialiseReputationSetItem( ok &= item->mGxsId.deserialise(data, tlvsize, offset) ; ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinion); ok &= getRawUInt32(data, tlvsize, &offset, &item->mOwnOpinionTS); + ok &= getRawUInt32(data, tlvsize, &offset, &item->mIdentityFlags); uint32_t S ; ok &= getRawUInt32(data, tlvsize, &offset, &S); @@ -413,10 +459,11 @@ RsItem *RsGxsReputationSerialiser::deserialise(void *data, uint32_t *pktsize) switch(getRsItemSubType(rstype)) { - case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM : return deserialiseReputationSetItem (data, *pktsize); - case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM : return deserialiseReputationUpdateItem (data, *pktsize); - case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM: return deserialiseReputationRequestItem(data, *pktsize); - case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM : return deserialiseReputationConfigItem (data, *pktsize); + case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM : return deserialiseReputationSetItem (data, *pktsize); + case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated: return deserialiseReputationSetItem_deprecated(data, *pktsize); + case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM : return deserialiseReputationUpdateItem (data, *pktsize); + case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM : return deserialiseReputationRequestItem (data, *pktsize); + case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM : return deserialiseReputationConfigItem (data, *pktsize); default: std::cerr << "RsGxsReputationSerialiser::deserialise(): unknown item subtype " << std::hex<< rstype << std::dec << std::endl; diff --git a/libretroshare/src/serialiser/rsgxsreputationitems.h b/libretroshare/src/serialiser/rsgxsreputationitems.h index 16b90847c..84dcecdc9 100644 --- a/libretroshare/src/serialiser/rsgxsreputationitems.h +++ b/libretroshare/src/serialiser/rsgxsreputationitems.h @@ -32,10 +32,11 @@ #include "serialiser/rsserial.h" #include "retroshare/rsgxsifacetypes.h" -#define RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM 0x01 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM 0x02 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM 0x03 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM 0x04 +#define RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM 0x01 +#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated 0x02 +#define RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM 0x03 +#define RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM 0x04 +#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM 0x05 /**************************************************************************/ class RsReputationItem: public RsItem @@ -90,6 +91,7 @@ public: RsGxsId mGxsId; uint32_t mOwnOpinion; uint32_t mOwnOpinionTS; + uint32_t mIdentityFlags ; std::map mOpinions; // RsPeerId -> Opinion. }; @@ -143,10 +145,11 @@ public: virtual RsItem * deserialise(void *data, uint32_t *size); private: - static RsGxsReputationConfigItem *deserialiseReputationConfigItem (void *data, uint32_t size); - static RsGxsReputationSetItem *deserialiseReputationSetItem (void *data, uint32_t size); - static RsGxsReputationUpdateItem *deserialiseReputationUpdateItem (void *data, uint32_t size); - static RsGxsReputationRequestItem *deserialiseReputationRequestItem(void *data, uint32_t size); + static RsGxsReputationConfigItem *deserialiseReputationConfigItem (void *data, uint32_t size); + static RsGxsReputationSetItem *deserialiseReputationSetItem (void *data, uint32_t size); + static RsGxsReputationSetItem *deserialiseReputationSetItem_deprecated (void *data, uint32_t size); + static RsGxsReputationUpdateItem *deserialiseReputationUpdateItem (void *data, uint32_t size); + static RsGxsReputationRequestItem *deserialiseReputationRequestItem (void *data, uint32_t size); }; /**************************************************************************/ diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc index e84500280..c1eef988a 100644 --- a/libretroshare/src/services/p3gxsreputation.cc +++ b/libretroshare/src/services/p3gxsreputation.cc @@ -23,6 +23,7 @@ * */ +#include #include "pqi/p3linkmgr.h" #include "retroshare/rspeers.h" @@ -126,14 +127,13 @@ static const uint32_t LOWER_LIMIT = 0; // used to filter valid Opinion values from serialized data static const uint32_t UPPER_LIMIT = 2; // used to filter valid Opinion values from serialized data -static const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; // reputation under which the peer gets killed static const int kMaximumPeerAge = 180; // half a year. static const int kMaximumSetSize = 100; // max set of updates to send at once. static const int ACTIVE_FRIENDS_UPDATE_PERIOD = 600 ; // 10 minutes static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. static const int kReputationRequestPeriod = 600; // 10 mins static const int kReputationStoreWait = 180; // 3 minutes. - +static const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; // reputation under which the peer gets killed p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) @@ -180,6 +180,17 @@ int p3GxsReputation::tick() mLastActiveFriendsUpdate = now ; } + static time_t last_identity_flags_update = 0 ; + + // no more than once per 5 second chunk. + + if(now > 100+last_identity_flags_update) + { + last_identity_flags_update = now ; + + updateIdentityFlags() ; + } + #ifdef DEBUG_REPUTATION static time_t last_debug_print = time(NULL) ; @@ -197,6 +208,58 @@ int p3GxsReputation::status() return 1; } +void p3GxsReputation::updateIdentityFlags() +{ + std::list to_update ; + + // we need to gather the list to be used in a non locked frame + { + RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ + +#ifdef DEBUG_REPUTATION + std::cerr << "Updating reputation identity flags" << std::endl; +#endif + + for( std::map::iterator rit = mReputations.begin();rit!=mReputations.end();++rit) + if(rit->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE) + to_update.push_back(rit->first) ; + } + + for(std::list::const_iterator rit(to_update.begin());rit!=to_update.end();++rit) + { + RsIdentityDetails details; + + if(!rsIdentity->getIdDetails(*rit,details)) + { +#ifdef DEBUG_REPUTATION + std::cerr << " cannot obtain info for " << *rit << ". Will do it later." << std::endl; +#endif + continue ; + } + + RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ + + std::map::iterator it = mReputations.find(*rit) ; + + if(it == mReputations.end()) + { + std::cerr << " Weird situation: item " << *rit << " has been deleted from the list??" << std::endl; + continue ; + } + it->second.mIdentityFlags = 0 ; + + if(details.mPgpLinked) it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_LINKED ; + if(details.mPgpKnown ) it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_KNOWN ; + +#ifdef DEBUG_REPUTATION + std::cerr << " updated flags for " << *rit << " to " << std::hex << it->second.mIdentityFlags << std::dec << std::endl; +#endif + + it->second.updateReputation() ; + IndicateConfigChanged(); + } +} + void p3GxsReputation::cleanup() { // remove opinions from friends that havn't been seen online for more than the specified delay @@ -478,7 +541,7 @@ void p3GxsReputation::locked_updateOpinion(const RsPeerId& from,const RsGxsId& a #ifdef DEBUG_REPUTATION std::cerr << " reputation changed. re-calculating." << std::endl; #endif - reputation.updateReputation(mAverageActiveFriends) ; + reputation.updateReputation() ; } if(updated) @@ -533,39 +596,28 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid,time_t latest_update) bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::ReputationInfo& info) { + if(gxsid.isNull()) + return false ; + RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ #ifdef DEBUG_REPUTATION std::cerr << "getReputationInfo() for " << gxsid << std::endl; #endif - - std::map::const_iterator it = mReputations.find(gxsid); + Reputation& rep(mReputations[gxsid]) ; - if (it == mReputations.end()) - { - info.mOwnOpinion = RsReputations::OPINION_NEUTRAL ; - info.mFriendAverage = RsReputations::OPINION_NEUTRAL ; - info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ; + info.mOwnOpinion = RsReputations::Opinion(rep.mOwnOpinion) ; + info.mOverallReputationScore = rep.mReputation ; + info.mFriendAverage = rep.mFriendAverage ; + + if(info.mOverallReputationScore > REPUTATION_ASSESSMENT_THRESHOLD_X1) info.mAssessment = RsReputations::ASSESSMENT_OK ; -#ifdef DEBUG_REPUTATION - std::cerr << " no information present. Returning default. OwnOp = " << info.mOwnOpinion << ", overall score=" << info.mAssessment << std::endl; -#endif - } else - { - info.mOwnOpinion = RsReputations::Opinion(it->second.mOwnOpinion) ; - info.mOverallReputationScore = it->second.mReputation ; - info.mFriendAverage = it->second.mFriendAverage ; + info.mAssessment = RsReputations::ASSESSMENT_BAD ; - if(info.mOverallReputationScore > REPUTATION_ASSESSMENT_THRESHOLD_X1) - info.mAssessment = RsReputations::ASSESSMENT_OK ; - else - info.mAssessment = RsReputations::ASSESSMENT_BAD ; - #ifdef DEBUG_REPUTATION std::cerr << " information present. OwnOp = " << info.mOwnOpinion << ", overall score=" << info.mAssessment << std::endl; #endif - } return true ; } @@ -632,7 +684,7 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O time_t now = time(NULL); reputation.mOwnOpinion = opinion; reputation.mOwnOpinionTs = now; - reputation.updateReputation(mAverageActiveFriends); + reputation.updateReputation(); mUpdated.insert(std::make_pair(now, gxsid)); mUpdatedReputations.insert(gxsid); @@ -689,6 +741,7 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) item->mGxsId = rit->first; item->mOwnOpinion = rit->second.mOwnOpinion; item->mOwnOpinionTS = rit->second.mOwnOpinionTs; + item->mIdentityFlags = rit->second.mIdentityFlags; std::map::iterator oit; for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit) @@ -719,6 +772,7 @@ bool p3GxsReputation::loadList(std::list& loadList) for(it = loadList.begin(); it != loadList.end(); ++it) { RsGxsReputationConfigItem *item = dynamic_cast(*it); + // Configurations are loaded first. (to establish peerSet). if (item) { @@ -728,13 +782,14 @@ bool p3GxsReputation::loadList(std::list& loadList) config.mPeerId = peerId; config.mLatestUpdate = item->mLatestUpdate; config.mLastQuery = 0; - + peerSet.insert(peerId); } + RsGxsReputationSetItem *set = dynamic_cast(*it); if (set) loadReputationSet(set, peerSet); - + delete (*it); } @@ -779,7 +834,7 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std: //float old_reputation = reputation.mReputation ; //mUpdatedReputations.insert(gxsId) ; - reputation.updateReputation(mAverageActiveFriends) ; + reputation.updateReputation() ; mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId)); return true; @@ -888,7 +943,7 @@ int p3GxsReputation::sendReputationRequest(RsPeerId peerid) return 1; } -void Reputation::updateReputation(uint32_t average_active_friends) +void Reputation::updateReputation() { // the calculation of reputation makes the whole thing @@ -903,8 +958,55 @@ void Reputation::updateReputation(uint32_t average_active_friends) if(mOpinions.empty()) // includes the case of no friends! mFriendAverage = 1.0f ; else - mFriendAverage = 1.0+friend_total / float(std::max(average_active_friends,(uint32_t)mOpinions.size())); + { + static const float REPUTATION_FRIEND_FACTOR_ANON = 2.0f ; + static const float REPUTATION_FRIEND_FACTOR_PGP_LINKED = 5.0f ; + static const float REPUTATION_FRIEND_FACTOR_PGP_KNOWN = 10.0f ; + // For positive votes, start from 1 and slowly tend to 2 + // for negative votes, start from 1 and slowly tend to 0 + // depending on signature state, the ID is harder (signed ids) or easier (anon ids) to ban or to promote. + // + // when REPUTATION_FRIEND_VARIANCE = 3, that gives the following values: + // + // total votes | mFriendAverage anon | mFriendAverage PgpLinked | mFriendAverage PgpKnown | + // | F=2.0 | F=5.0 | F=10.0 | + // -------------+----------------------+---------------------------+--------------------------+ + // -10 | 0.00 Banned | 0.13 Banned | 0.36 Banned | + // -5 | 0.08 Banned | 0.36 Banned | 0.60 | + // -4 | 0.13 Banned | 0.44 Banned | 0.67 | + // -3 | 0.22 Banned | 0.54 | 0.74 | + // -2 | 0.36 Banned | 0.67 | 0.81 | + // -1 | 0.60 | 0.81 | 0.90 | + // 0 | 1.0 | 1.0 | 1.00 | + // 1 | 1.39 | 1.18 | 1.09 | + // 2 | 1.63 | 1.32 | 1.18 | + // 3 | 1.77 | 1.45 | 1.25 | + // 4 | 1.86 | 1.55 | 1.32 | + // 5 | 1.91 | 1.63 | 1.39 | + // + // Banning info is provided by the reputation system, and does not depend on PGP-sign state. + // + // However, each service might have its own rules for the different cases. For instance + // PGP-favoring forums might want a score > 1.4 for anon ids, and >= 1.0 for PGP-signed. + + float reputation_bias ; + + if(mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_KNOWN) + reputation_bias = REPUTATION_FRIEND_FACTOR_PGP_KNOWN ; + else if(mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_LINKED) + reputation_bias = REPUTATION_FRIEND_FACTOR_PGP_LINKED ; + else + reputation_bias = REPUTATION_FRIEND_FACTOR_ANON ; + + if(friend_total > 0) + mFriendAverage = 2.0f-exp(-friend_total / reputation_bias) ; + else + mFriendAverage = exp( friend_total / reputation_bias) ; + } + + // now compute a bias for PGP-signed ids. + if(mOwnOpinion == RsReputations::OPINION_NEUTRAL) mReputation = mFriendAverage ; else diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h index 26beca518..6bda150ff 100644 --- a/libretroshare/src/services/p3gxsreputation.h +++ b/libretroshare/src/services/p3gxsreputation.h @@ -32,6 +32,10 @@ #include #include +#define REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE 0x0100 +#define REPUTATION_IDENTITY_FLAG_PGP_LINKED 0x0001 +#define REPUTATION_IDENTITY_FLAG_PGP_KNOWN 0x0002 + #include "serialiser/rsgxsreputationitems.h" #include "retroshare/rsidentity.h" @@ -59,12 +63,12 @@ class Reputation { public: Reputation() - :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { } + :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputation(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ } + + Reputation(const RsGxsId& about) + :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0),mFriendAverage(1.0f), mReputation(RsReputations::OPINION_NEUTRAL),mIdentityFlags(REPUTATION_IDENTITY_FLAG_NEEDS_UPDATE){ } - Reputation(const RsGxsId& about) - :mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { } - - void updateReputation(uint32_t average_active_friends); + void updateReputation(); std::map mOpinions; int32_t mOwnOpinion; @@ -72,6 +76,8 @@ public: float mFriendAverage ; float mReputation; + + uint32_t mIdentityFlags; }; @@ -124,6 +130,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations / void sendReputationRequests(); int sendReputationRequest(RsPeerId peerid); void debug_print() ; + void updateIdentityFlags(); private: RsMutex mReputationMtx; diff --git a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp index e4bbc7662..9cd8c60e9 100644 --- a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp @@ -113,10 +113,16 @@ void IdEditDialog::changeAvatar() } } -void IdEditDialog::setupNewId(bool pseudo) +void IdEditDialog::setupNewId(bool pseudo,bool enable_anon) { setWindowTitle(tr("New identity")); + if(pseudo && !enable_anon) + { + std::cerr << "IdEditDialog::setupNewId: Error. Cannot init with pseudo-anonymous id when anon ids are disabled." << std::endl; + pseudo = false ; + } + mIsNew = true; mGroupId.clear(); @@ -139,7 +145,11 @@ void IdEditDialog::setupNewId(bool pseudo) ui->frame_Tags->setHidden(true); ui->radioButton_GpgId->setEnabled(true); - ui->radioButton_Pseudo->setEnabled(true); + + if(enable_anon) + ui->radioButton_Pseudo->setEnabled(true); + else + ui->radioButton_Pseudo->setEnabled(false); setAvatar(QPixmap()); diff --git a/retroshare-gui/src/gui/Identity/IdEditDialog.h b/retroshare-gui/src/gui/Identity/IdEditDialog.h index d46cd7de3..d97aee090 100644 --- a/retroshare-gui/src/gui/Identity/IdEditDialog.h +++ b/retroshare-gui/src/gui/Identity/IdEditDialog.h @@ -45,7 +45,7 @@ public: IdEditDialog(QWidget *parent = 0); ~IdEditDialog(); - void setupNewId(bool pseudo); + void setupNewId(bool pseudo, bool enable_anon = true); void setupExistingId(const RsGxsGroupId &keyId); void enforceNoAnonIds() ; diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp index 19b315164..32e9ce763 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp @@ -37,18 +37,24 @@ #include // Control of Publish Signatures. -#define RSGXS_GROUP_SIGN_PUBLISH_MASK 0x000000ff -#define RSGXS_GROUP_SIGN_PUBLISH_ENCRYPTED 0x00000001 -#define RSGXS_GROUP_SIGN_PUBLISH_ALLSIGNED 0x00000002 -#define RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD 0x00000004 -#define RSGXS_GROUP_SIGN_PUBLISH_NONEREQ 0x00000008 +// +// These are now defined in rsgxsflags.h +// +// #define FLAG_GROUP_SIGN_PUBLISH_MASK 0x000000ff +// #define FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED 0x00000001 +// #define FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED 0x00000002 +// #define FLAG_GROUP_SIGN_PUBLISH_THREADHEAD 0x00000004 +// #define FLAG_GROUP_SIGN_PUBLISH_NONEREQ 0x00000008 -// Author Signature. -#define RSGXS_GROUP_SIGN_AUTHOR_MASK 0x0000ff00 -#define RSGXS_GROUP_SIGN_AUTHOR_GPG 0x00000100 -#define RSGXS_GROUP_SIGN_AUTHOR_REQUIRED 0x00000200 -#define RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN 0x00000400 -#define RSGXS_GROUP_SIGN_AUTHOR_NONE 0x00000800 +// // Author Signature. +// +// These are now defined in rsgxsflags.h +// +// #define FLAG_AUTHOR_AUTHENTICATION_MASK 0x0000ff00 +// #define FLAG_AUTHOR_AUTHENTICATION_NONE 0x00000000 +// #define FLAG_AUTHOR_AUTHENTICATION_GPG 0x00000100 +// #define FLAG_AUTHOR_AUTHENTICATION_REQUIRED 0x00000200 +// #define FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN 0x00000400 #define GXSGROUP_NEWGROUPID 1 #define GXSGROUP_LOADGROUP 2 @@ -123,6 +129,10 @@ void GxsGroupDialog::init() ui.groupDesc->setPlaceholderText(tr("Set a descriptive description here")); + ui.personal_ifnopub->hide() ; + ui.personal_required->hide() ; + ui.personal_required->setChecked(true) ; // this is always true + initMode(); } @@ -288,7 +298,10 @@ void GxsGroupDialog::setupDefaults() ui.comments_no->setChecked(true); ui.comments_no_3->setChecked(true); } - } + } + ui.antispam_keepTrackOfPosts->setChecked((bool)(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_TRACK)); + ui.antispam_favorSignedIds->setChecked((bool)(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_FAVOR_PGP)); + #ifndef RS_USE_CIRCLES ui.typeGroup->setEnabled(false); ui.typeLocal->setEnabled(false); @@ -576,54 +589,55 @@ uint32_t GxsGroupDialog::getGroupSignFlags() /* grab from the ui options -> */ uint32_t signFlags = 0; if (ui.publish_encrypt->isChecked()) { - signFlags |= RSGXS_GROUP_SIGN_PUBLISH_ENCRYPTED; + signFlags |= GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED; } else if (ui.publish_required->isChecked()) { - signFlags |= RSGXS_GROUP_SIGN_PUBLISH_ALLSIGNED; + signFlags |= GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED; } else if (ui.publish_threads->isChecked()) { - signFlags |= RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD; + signFlags |= GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD; } else { // publish_open (default). - signFlags |= RSGXS_GROUP_SIGN_PUBLISH_NONEREQ; + signFlags |= GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ; } + if (ui.personal_required->isChecked()) + signFlags |= GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; + + if (ui.personal_ifnopub->isChecked()) + signFlags |= GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN; + // Author Signature. - if (ui.personal_pgp->isChecked()) { - signFlags |= RSGXS_GROUP_SIGN_AUTHOR_GPG; - } else if (ui.personal_required->isChecked()) { - signFlags |= RSGXS_GROUP_SIGN_AUTHOR_REQUIRED; - } else if (ui.personal_ifnopub->isChecked()) { - signFlags |= RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN; - } else { // shouldn't allow this one. - signFlags |= RSGXS_GROUP_SIGN_AUTHOR_NONE; - } + if (ui.antispam_favorSignedIds->isChecked()) + signFlags |= GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG; + + if (ui.antispam_keepTrackOfPosts->isChecked()) + signFlags |= GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES; + return signFlags; } void GxsGroupDialog::setGroupSignFlags(uint32_t signFlags) { - if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_ENCRYPTED) { + if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED) { ui.publish_encrypt->setChecked(true); - } else if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_ALLSIGNED) { + } else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED) { ui.publish_required->setChecked(true); - } else if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD) { + } else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD) { ui.publish_threads->setChecked(true); - } else if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_NONEREQ) { + } else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ) { ui.publish_open->setChecked(true); } - if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_GPG) { - ui.personal_pgp->setChecked(true); - } else if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_REQUIRED) { + if (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED) ui.personal_required->setChecked(true); - } else if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN) { + + if (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN) ui.personal_ifnopub->setChecked(true); - } else if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_NONE) { - // Its the same... but not quite. - //ui.personal_noifpub->setChecked(); - } - + + ui.antispam_keepTrackOfPosts->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); + ui.antispam_favorSignedIds ->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); + /* guess at comments */ - if ((signFlags & RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD) && - (signFlags & RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN)) + if ((signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD) && + (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN)) { ui.comments_allowed->setChecked(true); ui.comments_allowed_3->setChecked(true); diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.h b/retroshare-gui/src/gui/gxs/GxsGroupDialog.h index ab93a2038..7f94c32db 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.h +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.h @@ -63,14 +63,14 @@ public: #define GXS_GROUP_FLAGS_SHAREKEYS 0x00000020 #define GXS_GROUP_FLAGS_PERSONALSIGN 0x00000040 #define GXS_GROUP_FLAGS_COMMENTS 0x00000080 - #define GXS_GROUP_FLAGS_EXTRA 0x00000100 +#define GXS_GROUP_FLAGS_ANTI_SPAM 0x00000200 /*** Default flags are used to determine privacy of group, signatures required *** *** whether publish or id and whether comments are allowed or not ***/ -#define GXS_GROUP_DEFAULTS_DISTRIB_MASK 0x0000000f -#define GXS_GROUP_DEFAULTS_PUBLISH_MASK 0x000000f0 +#define GXS_GROUP_DEFAULTS_DISTRIB_MASK 0x0000000f +#define GXS_GROUP_DEFAULTS_PUBLISH_MASK 0x000000f0 #define GXS_GROUP_DEFAULTS_PERSONAL_MASK 0x00000f00 #define GXS_GROUP_DEFAULTS_COMMENTS_MASK 0x0000f000 @@ -78,18 +78,21 @@ public: #define GXS_GROUP_DEFAULTS_DISTRIB_GROUP 0x00000002 #define GXS_GROUP_DEFAULTS_DISTRIB_LOCAL 0x00000004 -#define GXS_GROUP_DEFAULTS_PUBLISH_OPEN 0x00000010 +#define GXS_GROUP_DEFAULTS_PUBLISH_OPEN 0x00000010 #define GXS_GROUP_DEFAULTS_PUBLISH_THREADS 0x00000020 #define GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED 0x00000040 #define GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED 0x00000080 -#define GXS_GROUP_DEFAULTS_PERSONAL_PGP 0x00000100 +#define GXS_GROUP_DEFAULTS_PERSONAL_PGP 0x00000100 #define GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED 0x00000200 #define GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB 0x00000400 -#define GXS_GROUP_DEFAULTS_COMMENTS_YES 0x00001000 +#define GXS_GROUP_DEFAULTS_COMMENTS_YES 0x00001000 #define GXS_GROUP_DEFAULTS_COMMENTS_NO 0x00002000 +#define GXS_GROUP_DEFAULTS_ANTISPAM_FAVOR_PGP 0x00100000 +#define GXS_GROUP_DEFAULTS_ANTISPAM_TRACK 0x00200000 + /*! * The aim of this dialog is to be convenient to encapsulate group * creation code for several GXS services such forums, channels diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui index c8fdc33d9..fa0f2e93f 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui @@ -6,32 +6,23 @@ 0 0 - 685 - 517 + 928 + 914 Create New - - 0 - - - 0 - - - 0 - - - 0 - 6 0 + + 0 + @@ -44,20 +35,98 @@ QFrame::Raised - 1 + 0 - - - 9 - - - 6 - - - 0 - - + + + + + true + + + + 0 + 0 + + + + + 300 + 524287 + + + + + 220 + 0 + + + + + 0 + 0 + + + + check peers you would like to share private publish key with + + + false + + + QDockWidget::NoDockWidgetFeatures + + + Share Key With + + + + + 0 + + + 0 + + + + + + 0 + 4 + + + + + 20 + 0 + + + + + 300 + 16777215 + + + + + 220 + 0 + + + + + 200 + 0 + + + + + + + + + @@ -66,16 +135,7 @@ 0 - - 4 - - - 4 - - - 4 - - + 4 @@ -139,16 +199,7 @@ 9 - - 3 - - - 3 - - - 3 - - + 3 @@ -205,191 +256,19 @@ - - + + - Publish Signatures + Description - - - 6 - - - 9 - - - 4 - - - 9 - - - 4 - + - - - Open - - - - - - - New Thread - - - - - - - Required - - - - - - - Encrypted Msgs - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - + - - - - Personal Signatures - - - - 6 - - - 9 - - - 4 - - - 9 - - - 4 - - - - - PGP Required - - - - - - - Signature Required - - - - - - - If No Publish Signature - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Comments - - - - 6 - - - 9 - - - 4 - - - 9 - - - 4 - - - - - Allow Comments - - - - - - - No Comments - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - + @@ -490,112 +369,230 @@ - - + + - Description + Publish Signatures - + + + 6 + + + 9 + + + 4 + + + 9 + + + 4 + - + + + Open + + + + + + + New Thread + + + + + + + Required + + + + + + + Encrypted Msgs + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + - - - - true + + + + Personal Signatures - - - 0 - 0 - + + + + + PGP Required + + + + + + + Signature Required + + + + + + + If No Publish Signature + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Comments - - - 300 - 524287 - + + + 6 + + + 9 + + + 4 + + + 9 + + + 4 + + + + + Allow Comments + + + + + + + No Comments + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Spam-protection - - - 220 - 0 - + + + 6 + + + 9 + + + 4 + + + 9 + + + 4 + + + + + <html><head/><body><p>This makes the media increase the reputation threshold to 0.4 for anonymous ids, while keeping it to 0.0 for PGP-linked ids. Therefore, anonymous ids can still post, if their local reputation score is above that threshold.</p></body></html> + + + Favor PGP-signed ids + + + + + + + <html><head/><body><p align="justify">This feature allows Retroshare to locally keep a record of who forwarded each message to you, for the last 10 days. Although useless if alone (and already available whatsoever) this information can be used by a group of collaborative friends to easily locate the source of spams. To be used with care, since it significantly decreases the anonymity of message posts.</p></body></html> + + + Keep track of posts + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + QFrame::StyledPanel - - - 0 - 0 - + + QFrame::Raised - - check peers you would like to share private publish key with - - - false - - - QDockWidget::NoDockWidgetFeatures - - - Share Key With - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 4 - - - - - 20 - 0 - - - - - 300 - 16777215 - - - - - 220 - 0 - - - - - 200 - 0 - - - - - - @@ -620,16 +617,7 @@ - - 6 - - - 6 - - - 6 - - + 6 @@ -726,16 +714,7 @@ 6 - - 6 - - - 6 - - - 6 - - + 6 diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp index 71554f31a..522f927ec 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp @@ -27,6 +27,7 @@ #include "gui/Identity/IdEditDialog.h" #include +#include #include #include @@ -140,7 +141,6 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail switch (type) { case GXS_ID_DETAILS_TYPE_EMPTY: case GXS_ID_DETAILS_TYPE_FAILED: -// icons = ; break; case GXS_ID_DETAILS_TYPE_LOADING: @@ -160,11 +160,39 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail chooser->setItemData(index, (type == GXS_ID_DETAILS_TYPE_DONE) ? TYPE_FOUND_ID : TYPE_UNKNOWN_ID, ROLE_TYPE); chooser->setItemIcon(index, icons.empty() ? QIcon() : icons[0]); + std::cerr << "ID=" << details.mId << ", chooser->flags()=" << chooser->flags() << ", pgpLinked=" << details.mPgpLinked ; + + if((chooser->flags() & IDCHOOSER_NON_ANONYMOUS) && !(details.mPgpLinked)) + { + std::cerr << " - disabling ID - entry = " << index << std::endl; + chooser->setEntryEnabled(index,false) ; + } + std::cerr << std::endl; + chooser->model()->sort(0); chooser->blockSignals(false) ; } +void GxsIdChooser::setEntryEnabled(int indx,bool enabled) +{ + bool disable = !enabled ; + + QSortFilterProxyModel* model = qobject_cast(QComboBox::model()); + //QStandardItem* item = model->item(index); + + QModelIndex ii = model->index(indx,0); + + // visually disable by greying out - works only if combobox has been painted already and palette returns the wanted color + //model->setFlags(ii,disable ? (model->flags(ii) & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)) : (Qt::ItemIsSelectable|Qt::ItemIsEnabled)); + + uint32_t v = enabled?(1|32):(0); + + // clear item data in order to use default color + //model->setData(ii,disable ? (QComboBox::palette().color(QPalette::Disabled, QPalette::Text)) : QVariant(), Qt::TextColorRole); + model->setData(ii,QVariant(v),Qt::UserRole-1) ; +} + void GxsIdChooser::loadPrivateIds() { if (mFirstLoad) { @@ -223,6 +251,8 @@ void GxsIdChooser::loadPrivateIds() addItem(QIcon(":/images/identity/identity_create_32.png"), str, id); setItemData(count() - 1, QString("%1_%2").arg(TYPE_CREATE_ID).arg(str), ROLE_SORT); setItemData(count() - 1, TYPE_CREATE_ID, ROLE_TYPE); + + } setDefaultItem(); emit idsLoaded(); @@ -305,7 +335,7 @@ void GxsIdChooser::indexActivated(int index) int type = itemData(index, ROLE_TYPE).toInt(); if (type == TYPE_CREATE_ID) { IdEditDialog dlg(this); - dlg.setupNewId(false); + dlg.setupNewId(false, !(mFlags & IDCHOOSER_NON_ANONYMOUS)); if (dlg.exec() == QDialog::Accepted) { setDefaultId(RsGxsId(dlg.groupId())); } diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.h b/retroshare-gui/src/gui/gxs/GxsIdChooser.h index e785fb227..98c33a052 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.h +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.h @@ -37,6 +37,7 @@ class RsGxsUpdateBroadcastBase; #define IDCHOOSER_ID_REQUIRED 0x0001 #define IDCHOOSER_ANON_DEFAULT 0x0002 #define IDCHOOSER_NO_CREATE 0x0004 +#define IDCHOOSER_NON_ANONYMOUS 0x0008 class GxsIdChooser : public QComboBox { @@ -48,6 +49,7 @@ public: virtual ~GxsIdChooser(); void setFlags(uint32_t flags) ; + uint32_t flags() const { return mFlags ; } enum ChosenId_Ret {None, KnowId, UnKnowId, NoId} ; void loadIds(uint32_t chooserFlags, const RsGxsId &defId); @@ -56,6 +58,7 @@ public: bool setChosenId(const RsGxsId &gxsId); ChosenId_Ret getChosenId(RsGxsId &gxsId); + void setEntryEnabled(int index, bool enabled); signals: // emitted after first load of own ids void idsLoaded(); @@ -71,13 +74,13 @@ private slots: private: void loadPrivateIds(); - void setDefaultItem(); + void setDefaultItem(); uint32_t mFlags; RsGxsId mDefaultId; bool mFirstLoad; - RsGxsUpdateBroadcastBase *mBase; + RsGxsUpdateBroadcastBase *mBase; }; #endif diff --git a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp index d9e83111a..bacf1349f 100644 --- a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp @@ -121,7 +121,12 @@ void CreateGxsForumMsg::newMsg() mForumMetaLoaded = false; /* fill in the available OwnIds for signing */ - ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, RsGxsId()); + std::cerr << "Initing ID chooser. Sign flags = " << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; + + if(mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) + ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NON_ANONYMOUS, RsGxsId()); + else + ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, RsGxsId()); if (mForumId.isNull()) { mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); @@ -203,6 +208,13 @@ void CreateGxsForumMsg::loadFormInformation() std::cerr << "CreateGxsForumMsg::loadMsgInformation() Data Available!"; std::cerr << std::endl; + std::cerr << "CreateGxsForumMsg::loadMsgInformation() using signFlags=" << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; + + if(mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) + ui.idChooser->setFlags(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NON_ANONYMOUS) ; + else + ui.idChooser->setFlags(IDCHOOSER_ID_REQUIRED) ; + QString name = QString::fromUtf8(mForumMeta.mGroupName.c_str()); QString subj; if (!mParentId.isNull()) diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp index 41f138e20..433f354c9 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp @@ -33,6 +33,7 @@ const uint32_t ForumCreateEnabledFlags = ( GXS_GROUP_FLAGS_DISTRIBUTION | // GXS_GROUP_FLAGS_PUBLISHSIGN | GXS_GROUP_FLAGS_SHAREKEYS | + GXS_GROUP_FLAGS_ANTI_SPAM | // GXS_GROUP_FLAGS_PERSONALSIGN | // GXS_GROUP_FLAGS_COMMENTS | 0); @@ -46,7 +47,7 @@ const uint32_t ForumCreateDefaultsFlags = ( GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC //GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED | //GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED | - //GXS_GROUP_DEFAULTS_PERSONAL_GPG | + //GXS_GROUP_DEFAULTS_PERSONAL_PGP | GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED | //GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB | diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 16d7d5c6b..2fe308cb3 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -41,6 +41,7 @@ #include "util/QtVersion.h" #include +#include #include #include // These should be in retroshare/ folder. @@ -547,6 +548,17 @@ void GxsForumThreadWidget::changedThread() mThreadId = RsGxsMessageId(item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString()); } + // Show info about who passed on this message. + if(mForumGroup.mMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) + { + RsPeerId providerId ; + std::string msgId = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); + RsGxsMessageId mid(msgId) ; + + if(rsGRouter->getTrackingInfo(mid,providerId) && !providerId.isNull() ) + item->setToolTip(COLUMN_THREAD_TITLE,tr("This message was obtained from %1").arg(QString::fromUtf8(rsPeers->getPeerName(providerId).c_str()))); + } + if (mFillThread) { return; } @@ -744,12 +756,26 @@ void GxsForumThreadWidget::insertGroupData() const RsGxsForumGroup& group = tw->mForumGroup; tw->mSubscribeFlags = group.mMeta.mSubscribeFlags; + tw->mSignFlags = group.mMeta.mSignFlags; tw->ui->forumName->setText(QString::fromUtf8(group.mMeta.mGroupName.c_str())); + QString anti_spam_features1 ; + if(IS_GROUP_PGP_AUTHED(tw->mSignFlags)) anti_spam_features1 = tr("Anonymous IDs reputation threshold set to 0.4"); + + QString anti_spam_features2 ; + if(IS_GROUP_MESSAGE_TRACKING(tw->mSignFlags)) anti_spam_features2 = tr("Message routing info kept for 10 days"); + tw->mForumDescription = QString("%1: \t%2
").arg(tr("Forum name"), QString::fromUtf8( group.mMeta.mGroupName.c_str())); tw->mForumDescription += QString("%1: \t%2
").arg(tr("Subscribers")).arg(group.mMeta.mPop); tw->mForumDescription += QString("%1: \t%2
").arg(tr("Posts (at neighbor nodes)")).arg(group.mMeta.mVisibleMsgCount); tw->mForumDescription += QString("%1: \t%2
").arg(tr("Author"), author); + + if(!anti_spam_features1.isNull()) + tw->mForumDescription += QString("%1: \t%2
").arg(tr("Anti-spam")).arg(anti_spam_features1); + + if(!anti_spam_features2.isNull()) + tw->mForumDescription += QString("%1: \t%2
").arg(tr("Anti-spam")).arg(anti_spam_features2); + tw->mForumDescription += QString("%1:

%2").arg(tr("Description"), QString::fromUtf8(group.mDescription.c_str())); tw->ui->subscribeToolButton->setSubscribed(IS_GROUP_SUBSCRIBED(tw->mSubscribeFlags)); @@ -936,6 +962,7 @@ QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForum // Set later with GxsIdRSTreeWidgetItem::setId item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_AUTHOR, QString::fromStdString(msg.mMeta.mAuthorId.toStdString())); + //#TODO #if 0 text = QString::fromUtf8(authorName.c_str()); @@ -1863,6 +1890,7 @@ bool GxsForumThreadWidget::filterItem(QTreeWidgetItem *item, const QString &text void GxsForumThreadWidget::requestGroupData() { mSubscribeFlags = 0; + mSignFlags = 0; mForumDescription.clear(); mTokenQueue->cancelActiveRequestTokens(mTokenTypeGroupData); diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h index 7048e7925..f80956166 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -149,6 +149,7 @@ private: RsGxsForumGroup mForumGroup; QString mForumDescription; int mSubscribeFlags; + int mSignFlags; bool mInProcessSettings; bool mInMsgAsReadUnread; int mLastViewType; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp index 6fefb0c34..880ed6ba7 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp @@ -178,8 +178,9 @@ void GxsForumsDialog::groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, groupItemInfo.description = descriptionIt.value(); } - if (IS_GROUP_ADMIN(groupInfo.mSubscribeFlags)) { - groupItemInfo.icon = QIcon(":images/konv_message2.png"); - } + if (IS_GROUP_ADMIN(groupInfo.mSubscribeFlags)) + groupItemInfo.icon = QIcon(":images/konv_message2.png"); + else if ((IS_GROUP_PGP_AUTHED(groupInfo.mSignFlags)) || (IS_GROUP_MESSAGE_TRACKING(groupInfo.mSignFlags)) ) + groupItemInfo.icon = QIcon(":images/konv_message3.png"); } diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index de22823e7..2d26956be 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -316,6 +316,7 @@ images/konversation16.png images/konversation128.png images/konv_message2.png + images/konv_message3.png images/konv_message64.png images/konversation64.png images/forums_new.png diff --git a/retroshare-gui/src/gui/images/konv_message3.png b/retroshare-gui/src/gui/images/konv_message3.png new file mode 100644 index 000000000..40280bb50 Binary files /dev/null and b/retroshare-gui/src/gui/images/konv_message3.png differ