Merge pull request #164 from csoler/v0.6-SignedForums2

V0.6 signed forums2
This commit is contained in:
Cyril Soler 2015-10-28 10:01:26 -04:00
commit 5beb85215c
36 changed files with 1345 additions and 793 deletions

View File

@ -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 ;

View File

@ -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<RoutingMatrixHitEntry> 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 ;
};

View File

@ -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<RsGxsMessageId,RoutingTrackEntry>::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<RsGxsMessageId,RoutingTrackEntry>::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<GRouterKeyId>& key_ids) const
key_ids.clear() ;
for(std::map<GRouterKeyId,std::vector<float> >::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<RsGxsMessageId,RoutingTrackEntry>::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<RsGxsMessageId, RoutingTrackEntry>::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<RsPeerId>& friends, std::vector<float>& probas) const
@ -241,55 +299,78 @@ bool GRouterMatrix::saveList(std::list<RsItem*>& 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<GRouterKeyId,std::list<RoutingMatrixHitEntry> >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it)
{
RsGRouterMatrixCluesItem *item = new RsGRouterMatrixCluesItem ;
for(std::map<GRouterKeyId,std::list<RoutingMatrixHitEntry> >::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<RsGxsMessageId,RoutingTrackEntry>::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<RsItem*>& 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<RsItem*>::const_iterator it(items.begin());it!=items.end();++it)
{
if(NULL != (itm2 = dynamic_cast<RsGRouterMatrixCluesItem*>(*it)))
{
for(std::list<RsItem*>::const_iterator it(items.begin());it!=items.end();++it)
{
if(NULL != (itm3 = dynamic_cast<RsGRouterMatrixTrackItem*>(*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<RsGRouterMatrixCluesItem*>(*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<RsGRouterMatrixFriendListItem*>(*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<RsGRouterMatrixFriendListItem*>(*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 ;
}

View File

@ -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<RsItem*>& items) ;
bool loadList(std::list<RsItem*>& items) ;
bool cleanUp() ;
// Dump info in terminal.
//
void debugDump() const ;
void getListOfKnownKeys(std::vector<GRouterKeyId>& 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<GRouterKeyId, std::list<RoutingMatrixHitEntry> > _routing_clues ; // received routing clues. Should be saved.
std::map<GRouterKeyId, std::vector<float> > _time_combined_hits ; // hit matrix after time-convolution filter
std::map<GRouterKeyId, std::list<RoutingMatrixHitEntry> > _routing_clues ; // received routing clues. Should be saved.
std::map<GRouterKeyId, std::vector<float> > _time_combined_hits ; // hit matrix after time-convolution filter
std::map<RsGxsMessageId,RoutingTrackEntry> _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<RsPeerId,uint32_t> _friend_indices ; // index for each friend to lookup in the routing matrix Not saved.
std::vector<RsPeerId> _reverse_friend_indices ;// SSLid corresponding to each friend index. Saved.
};

View File

@ -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.

View File

@ -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<GRouterRoutingCacheInfo>& 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() ;
}

View File

@ -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<GRouterRoutingCacheInfo>& 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

View File

@ -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;

View File

@ -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);

View File

@ -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<RsGxsId, RsTlvSecurityKey>& keys = grpKeySet.keys;
std::map<RsGxsId, RsTlvSecurityKey>::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<RsPeerId> 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<RsGxsId,std::set<RsPeerId> >::const_iterator it = mRoutingClues.begin();it!=mRoutingClues.end();++it)
for(std::set<RsPeerId>::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<std::pair<RsGxsMessageId,RsPeerId> >::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<RsNxsMsg*, RsGxsGrpMsgIdPair>& gpsi = *pend_it;
for(; pend_it != mMsgPendingValidate.end();)
{
GxsPendingItem<RsNxsMsg*, RsGxsGrpMsgIdPair>& 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<RsNxsMsg*>::iterator vit = mReceivedMsgs.begin();
GxsMsgReq msgIds;
std::map<RsNxsMsg*, RsGxsMsgMetaData*> msgs;
std::vector<RsNxsMsg*>::iterator vit = mReceivedMsgs.begin();
GxsMsgReq msgIds;
std::map<RsNxsMsg*, RsGxsMsgMetaData*> msgs;
std::map<RsGxsGroupId, RsGxsGrpMetaData*> grpMetas;
std::map<RsGxsGroupId, RsGxsGrpMetaData*> 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<RsGxsGroupId, RsGxsGrpMetaData*>::iterator mit = grpMetas.find(msg->grpId);
if(ok)
{
std::map<RsGxsGroupId, RsGxsGrpMetaData*>::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<RsGxsMessageId> &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!" <<std::endl;
#endif
validateReturn = VALIDATE_FAIL;
}
if(validateReturn == VALIDATE_FAIL)
{
// validate msg
if(mit != grpMetas.end())
{
grpMeta = mit->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<RsGxsMessageId> &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!" <<std::endl;
#endif
validateReturn = VALIDATE_FAIL;
}
if(validateReturn == VALIDATE_FAIL)
{
#ifdef GEN_EXCH_DEBUG
std::cerr << "Validation failed for message id "
<< "msg->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<RsNxsMsg*, RsGxsGrpMsgIdPair> item(msg, id);
mMsgPendingValidate.push_back(item);
}else
{
if(vit == mMsgPendingValidate.end())
{
GxsPendingItem<RsNxsMsg*, RsGxsGrpMsgIdPair> item(msg, id);
mMsgPendingValidate.push_back(item);
}else
{
vit->mAttempts++;
}
}
}
}
}
}
// clean up resources from group meta retrieval
freeAndClearContainerResource<std::map<RsGxsGroupId, RsGxsGrpMetaData*>,
RsGxsGrpMetaData*>(grpMetas);
// clean up resources from group meta retrieval
freeAndClearContainerResource<std::map<RsGxsGroupId, RsGxsGrpMetaData*>,
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<SignType, RsTlvKeySignature>& signSet = newGrp.metaData->signSet.keySignSet;
std::map<SignType, RsTlvKeySignature>::iterator mit = signSet.find(GXS_SERV::FLAG_AUTHEN_ADMIN);
std::map<SignType, RsTlvKeySignature>::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)
//

View File

@ -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<GroupDeletePublish> mGroupDeletePublish;
std::map<RsGxsId,std::set<RsPeerId> > mRoutingClues ;
std::list<std::pair<RsGxsMessageId,RsPeerId> > mTrackingClues ;
};
#endif // RSGENEXCHANGE_H

View File

@ -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

View File

@ -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;

View File

@ -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;
};

View File

@ -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

View File

@ -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)

View File

@ -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 } ;

View File

@ -24,7 +24,6 @@
this->mPublishTs = rGxsMeta.mPublishTs;
this->mThreadId = rGxsMeta.mThreadId;
this->mServiceString = rGxsMeta.mServiceString;
}

View File

@ -34,6 +34,9 @@
#include <iostream>
// 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<RsPeerId,uint32_t>::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 && i<S;++i)
{
RsPeerId pid ;
uint32_t op ;
ok &= pid.deserialise(data, tlvsize, offset) ;
ok &= getRawUInt32(data, tlvsize, &offset, &op);
if(ok)
item->mOpinions[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;

View File

@ -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<RsPeerId, uint32_t> 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);
};
/**************************************************************************/

View File

@ -23,6 +23,7 @@
*
*/
#include <math.h>
#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<RsGxsId> 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<RsGxsId, Reputation>::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<RsGxsId>::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<RsGxsId,Reputation>::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<RsGxsId,Reputation>::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<RsItem*> &savelist)
item->mGxsId = rit->first;
item->mOwnOpinion = rit->second.mOwnOpinion;
item->mOwnOpinionTS = rit->second.mOwnOpinionTs;
item->mIdentityFlags = rit->second.mIdentityFlags;
std::map<RsPeerId, RsReputations::Opinion>::iterator oit;
for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit)
@ -719,6 +772,7 @@ bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
for(it = loadList.begin(); it != loadList.end(); ++it)
{
RsGxsReputationConfigItem *item = dynamic_cast<RsGxsReputationConfigItem *>(*it);
// Configurations are loaded first. (to establish peerSet).
if (item)
{
@ -728,13 +782,14 @@ bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
config.mPeerId = peerId;
config.mLatestUpdate = item->mLatestUpdate;
config.mLastQuery = 0;
peerSet.insert(peerId);
}
RsGxsReputationSetItem *set = dynamic_cast<RsGxsReputationSetItem *>(*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

View File

@ -32,6 +32,10 @@
#include <map>
#include <set>
#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<RsPeerId, RsReputations::Opinion> 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;

View File

@ -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());

View File

@ -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() ;

View File

@ -37,18 +37,24 @@
#include <iostream>
// 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);

View File

@ -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

View File

@ -6,32 +6,23 @@
<rect>
<x>0</x>
<y>0</y>
<width>685</width>
<height>517</height>
<width>928</width>
<height>914</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Create New</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="HeaderFrame" name="headerFrame"/>
</item>
@ -44,20 +35,98 @@
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="createmode">
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="horizontalSpacing">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QDockWidget" name="contactsdockWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>524287</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>220</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>check peers you would like to share private publish key with</string>
</property>
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::NoDockWidgetFeatures</set>
</property>
<property name="windowTitle">
<string>Share Key With</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="_2">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="FriendSelectionWidget" name="keyShareList" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>4</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>220</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxLogo">
<property name="title">
<string/>
@ -66,16 +135,7 @@
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>4</number>
</property>
<item>
@ -139,16 +199,7 @@
<property name="spacing">
<number>9</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>3</number>
</property>
<item>
@ -205,191 +256,19 @@
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="publishGroupBox">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Publish Signatures</string>
<string>Description</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QRadioButton" name="publish_open">
<property name="text">
<string>Open</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="publish_threads">
<property name="text">
<string>New Thread</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="publish_required">
<property name="text">
<string>Required</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="publish_encrypt">
<property name="text">
<string>Encrypted Msgs</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="MimeTextEdit" name="groupDesc"/>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="personalGroupBox">
<property name="title">
<string>Personal Signatures</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QRadioButton" name="personal_pgp">
<property name="text">
<string>PGP Required</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="personal_required">
<property name="text">
<string>Signature Required</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="personal_ifnopub">
<property name="text">
<string>If No Publish Signature</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QGroupBox" name="commentGroupBox">
<property name="title">
<string>Comments</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QRadioButton" name="comments_allowed">
<property name="text">
<string>Allow Comments</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="comments_no">
<property name="text">
<string>No Comments</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QFrame" name="extraFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<item>
<widget class="QGroupBox" name="distribGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -490,112 +369,230 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<item>
<widget class="QGroupBox" name="publishGroupBox">
<property name="title">
<string>Description</string>
<string>Publish Signatures</string>
</property>
<layout class="QVBoxLayout">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="MimeTextEdit" name="groupDesc"/>
<widget class="QRadioButton" name="publish_open">
<property name="text">
<string>Open</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="publish_threads">
<property name="text">
<string>New Thread</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="publish_required">
<property name="text">
<string>Required</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="publish_encrypt">
<property name="text">
<string>Encrypted Msgs</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" rowspan="6">
<widget class="QDockWidget" name="contactsdockWidget">
<property name="enabled">
<bool>true</bool>
<item>
<widget class="QGroupBox" name="personalGroupBox">
<property name="title">
<string>Personal Signatures</string>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QRadioButton" name="personal_pgp">
<property name="text">
<string>PGP Required</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="personal_required">
<property name="text">
<string>Signature Required</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="personal_ifnopub">
<property name="text">
<string>If No Publish Signature</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="commentGroupBox">
<property name="title">
<string>Comments</string>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>524287</height>
</size>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QRadioButton" name="comments_allowed">
<property name="text">
<string>Allow Comments</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="comments_no">
<property name="text">
<string>No Comments</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="spamProtection_GB">
<property name="title">
<string>Spam-protection</string>
</property>
<property name="sizeIncrement">
<size>
<width>220</width>
<height>0</height>
</size>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QCheckBox" name="antispam_favorSignedIds">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Favor PGP-signed ids</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="antispam_keepTrackOfPosts">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Keep track of posts</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="extraFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="toolTip">
<string>check peers you would like to share private publish key with</string>
</property>
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::NoDockWidgetFeatures</set>
</property>
<property name="windowTitle">
<string>Share Key With</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="FriendSelectionWidget" name="keyShareList" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>4</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>220</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -620,16 +617,7 @@
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>6</number>
</property>
<item row="0" column="1">
@ -726,16 +714,7 @@
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>6</number>
</property>
<item>

View File

@ -27,6 +27,7 @@
#include "gui/Identity/IdEditDialog.h"
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <algorithm>
#include <retroshare/rspeers.h>
@ -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<QSortFilterProxyModel*>(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()));
}

View File

@ -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

View File

@ -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())

View File

@ -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 |

View File

@ -41,6 +41,7 @@
#include "util/QtVersion.h"
#include <retroshare/rsgxsforums.h>
#include <retroshare/rsgrouter.h>
#include <retroshare/rsreputations.h>
#include <retroshare/rspeers.h>
// 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("<b>%1: \t</b>%2<br/>").arg(tr("Forum name"), QString::fromUtf8( group.mMeta.mGroupName.c_str()));
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Subscribers")).arg(group.mMeta.mPop);
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Posts (at neighbor nodes)")).arg(group.mMeta.mVisibleMsgCount);
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Author"), author);
if(!anti_spam_features1.isNull())
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Anti-spam")).arg(anti_spam_features1);
if(!anti_spam_features2.isNull())
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Anti-spam")).arg(anti_spam_features2);
tw->mForumDescription += QString("<b>%1: </b><br/><br/>%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);

View File

@ -149,6 +149,7 @@ private:
RsGxsForumGroup mForumGroup;
QString mForumDescription;
int mSubscribeFlags;
int mSignFlags;
bool mInProcessSettings;
bool mInMsgAsReadUnread;
int mLastViewType;

View File

@ -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");
}

View File

@ -316,6 +316,7 @@
<file>images/konversation16.png</file>
<file>images/konversation128.png</file>
<file>images/konv_message2.png</file>
<file>images/konv_message3.png</file>
<file>images/konv_message64.png</file>
<file>images/konversation64.png</file>
<file>images/forums_new.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB