mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-28 17:09:34 -05:00
put some notes and comments in the code for what is to be done
This commit is contained in:
parent
f44ccbe756
commit
89472d6502
@ -187,6 +187,7 @@ void RsGenExchange::tick()
|
||||
processGroupUpdatePublish();
|
||||
|
||||
processGroupDelete();
|
||||
processMessageDelete();
|
||||
|
||||
processRecvdData();
|
||||
|
||||
@ -1620,6 +1621,11 @@ void RsGenExchange::deleteGroup(uint32_t& token, RsGxsGrpItem* grpItem)
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
}
|
||||
void RsGenExchange::deleteMsgs(uint32_t& token, const GxsMsgReq& msgs)
|
||||
{
|
||||
token = mDataAccess->generatePublicToken();
|
||||
mMsgDeletePublish.push_back(MsgDeletePublish(msgs, token));
|
||||
}
|
||||
|
||||
void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem)
|
||||
{
|
||||
@ -2188,6 +2194,7 @@ void RsGenExchange::processRoutingClues()
|
||||
|
||||
mTrackingClues.clear() ;
|
||||
}
|
||||
|
||||
void RsGenExchange::processGroupDelete()
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
@ -2234,6 +2241,52 @@ void RsGenExchange::processGroupDelete()
|
||||
|
||||
mGroupDeletePublish.clear();
|
||||
}
|
||||
void RsGenExchange::processMessageDelete()
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
#ifdef TODO
|
||||
typedef std::pair<bool, RsGxsGroupId> GrpNote;
|
||||
std::map<uint32_t, GrpNote> toNotify;
|
||||
#endif
|
||||
|
||||
for( std::vector<MsgDeletePublish>::iterator vit = mMsgDeletePublish.begin(); vit != mMsgDeletePublish.end(); ++vit)
|
||||
{
|
||||
#ifdef TODO
|
||||
uint32_t token = (*vit).mToken;
|
||||
const RsGxsGroupId& groupId = gdp.grpItem->meta.mGroupId;
|
||||
toNotify.insert(std::make_pair( token, GrpNote(true, groupId)));
|
||||
#endif
|
||||
mDataStore->removeMsgs( (*vit).mMsgs );
|
||||
}
|
||||
|
||||
|
||||
#warning TODO: notify for deleted messages
|
||||
#ifdef SUSPENDED
|
||||
std::list<RsGxsGroupId> grpDeleted;
|
||||
std::map<uint32_t, GrpNote>::iterator mit = toNotify.begin();
|
||||
for(; mit != toNotify.end(); ++mit)
|
||||
{
|
||||
GrpNote& note = mit->second;
|
||||
uint8_t status = note.first ? RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE
|
||||
: RsTokenService::GXS_REQUEST_V2_STATUS_FAILED;
|
||||
|
||||
mGrpNotify.insert(std::make_pair(mit->first, note.second));
|
||||
mDataAccess->updatePublicRequestStatus(mit->first, status);
|
||||
|
||||
if(note.first)
|
||||
grpDeleted.push_back(note.second);
|
||||
}
|
||||
|
||||
if(!grpDeleted.empty())
|
||||
{
|
||||
RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PUBLISH, false);
|
||||
gc->mGrpIdList = grpDeleted;
|
||||
mNotifications.push_back(gc);
|
||||
}
|
||||
#endif
|
||||
|
||||
mMsgDeletePublish.clear();
|
||||
}
|
||||
|
||||
bool RsGenExchange::checkKeys(const RsTlvSecurityKeySet& keySet)
|
||||
{
|
||||
|
@ -535,6 +535,14 @@ public:
|
||||
*/
|
||||
void publishMsg(uint32_t& token, RsGxsMsgItem* msgItem);
|
||||
|
||||
/*!
|
||||
* Deletes the messages \n
|
||||
* This will induce a related change message \n
|
||||
* @param token
|
||||
* @param msgs
|
||||
*/
|
||||
void deleteMsgs(uint32_t& token, const GxsMsgReq& msgs);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* This represents the group before its signature is calculated
|
||||
@ -657,6 +665,7 @@ private:
|
||||
void processGroupUpdatePublish();
|
||||
|
||||
void processGroupDelete();
|
||||
void processMessageDelete();
|
||||
void processRoutingClues();
|
||||
|
||||
void publishMsgs();
|
||||
@ -869,6 +878,7 @@ private:
|
||||
|
||||
std::vector<GroupUpdatePublish> mGroupUpdatePublish;
|
||||
std::vector<GroupDeletePublish> mGroupDeletePublish;
|
||||
std::vector<MsgDeletePublish> mMsgDeletePublish;
|
||||
|
||||
std::map<RsGxsId,std::set<RsPeerId> > mRoutingClues ;
|
||||
std::list<std::pair<RsGxsMessageId,RsPeerId> > mTrackingClues ;
|
||||
|
@ -761,6 +761,7 @@ void RsGxsNetService::syncWithPeers()
|
||||
RsNxsItem *encrypted_item = NULL ;
|
||||
uint32_t status ;
|
||||
|
||||
#warning pass on the group id here so as to know which list to encrypt to (admin/members)
|
||||
if(encryptSingleNxsItem(msg, encrypt_to_this_circle_id, encrypted_item, status))
|
||||
sendItem(encrypted_item) ;
|
||||
else
|
||||
@ -1270,6 +1271,7 @@ bool RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVett
|
||||
RsNxsItem *encrypted_item = NULL ;
|
||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||
|
||||
#warning pass on the group id here so as to know which list to encrypt to (admin/members)
|
||||
if(encryptSingleNxsItem(gItem, entry.mCircleId, encrypted_item,status))
|
||||
{
|
||||
itemL.push_back(encrypted_item) ;
|
||||
@ -1321,6 +1323,7 @@ bool RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVet
|
||||
RsNxsItem *encrypted_item = NULL ;
|
||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||
|
||||
#warning pass on the group id here so as to know which list to encrypt to (admin/members)
|
||||
if(encryptSingleNxsItem(mItem,msgPend->mCircleId,encrypted_item,status))
|
||||
{
|
||||
itemL.push_back(encrypted_item) ;
|
||||
@ -3678,6 +3681,7 @@ bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId&
|
||||
|
||||
std::list<RsGxsId> recipients ;
|
||||
|
||||
#warning recipients should take the destination group ID as parameter and use it to know if is will use the admin list or the members list.
|
||||
if(!mCircles->recipients(destination_circle,recipients))
|
||||
{
|
||||
std::cerr << " (EE) Cannot encrypt transaction: recipients list not available. Should re-try later." << std::endl;
|
||||
@ -4047,7 +4051,7 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item)
|
||||
#endif
|
||||
RsNxsItem *encrypted_item = NULL ;
|
||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||
|
||||
#warning pass on the group id here so as to know which list to encrypt to (admin/members)
|
||||
if(encryptSingleNxsItem(gItem, grpMeta->mCircleId, encrypted_item,status))
|
||||
{
|
||||
itemL.push_back(encrypted_item) ;
|
||||
@ -4471,6 +4475,7 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_
|
||||
RsNxsItem *encrypted_item = NULL ;
|
||||
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
|
||||
|
||||
#warning pass on the group id here so as to know which list to encrypt to (admin/members)
|
||||
if(encryptSingleNxsItem(mItem, grpMeta->mCircleId, encrypted_item,status))
|
||||
{
|
||||
itemL.push_back(encrypted_item) ;
|
||||
|
@ -162,4 +162,15 @@ public:
|
||||
uint32_t mToken;
|
||||
};
|
||||
|
||||
|
||||
class MsgDeletePublish
|
||||
{
|
||||
public:
|
||||
MsgDeletePublish(const GxsMsgReq& msgs, uint32_t token)
|
||||
: mMsgs(msgs), mToken(token) {}
|
||||
|
||||
GxsMsgReq mMsgs ;
|
||||
uint32_t mToken;
|
||||
};
|
||||
|
||||
#endif /* GXSUTIL_H_ */
|
||||
|
@ -73,8 +73,9 @@ RsGxsCircles *rsGxsCircles = NULL;
|
||||
*/
|
||||
|
||||
|
||||
#define CIRCLEREQ_CACHELOAD 0x0001
|
||||
#define CIRCLEREQ_CIRCLE_LIST 0x0002
|
||||
#define CIRCLEREQ_CACHELOAD 0x0001
|
||||
#define CIRCLEREQ_CIRCLE_LIST 0x0002
|
||||
#define CIRCLEREQ_MESSAGE_DATA 0x0003
|
||||
|
||||
//#define CIRCLEREQ_PGPHASH 0x0010
|
||||
//#define CIRCLEREQ_REPUTATION 0x0020
|
||||
@ -406,6 +407,11 @@ bool p3GxsCircles::isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id)
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function (will) use the destination group for the transaction in order to decide which list of
|
||||
// keys to ecnrypt to. When sending to a self-restricted group, the list of recipients is extended to
|
||||
// the admin list rather than just the members list.
|
||||
#warning TODO
|
||||
|
||||
bool p3GxsCircles::recipients(const RsGxsCircleId& circleId, std::list<RsGxsId>& gxs_ids)
|
||||
{
|
||||
RsGxsCircleDetails details ;
|
||||
@ -586,13 +592,14 @@ bool RsGxsCircleCache::getAllowedPeersList(std::list<RsPgpId>& friendlist) const
|
||||
|
||||
bool RsGxsCircleCache::isAllowedPeer(const RsGxsId& id) const
|
||||
{
|
||||
if(mUnprocessedPeers.find(id) != mUnprocessedPeers.end())
|
||||
return true ;
|
||||
std::map<RsGxsId,RsGxsCircleMembershipStatus>::const_iterator it = mMembershipStatusMap.find(id) ;
|
||||
|
||||
if(mAllowedGxsIds.find(id) != mAllowedGxsIds.end())
|
||||
return true ;
|
||||
if(it == mMembershipStatusMap.end())
|
||||
return false ;
|
||||
|
||||
return false ;
|
||||
// Peers are admitted if in admin list. This is the condition for messages to propagate.
|
||||
|
||||
return !!(it->second & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ;
|
||||
}
|
||||
|
||||
bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) const
|
||||
@ -856,8 +863,7 @@ bool p3GxsCircles::cache_request_load(const RsGxsCircleId &id)
|
||||
{
|
||||
if (age < MIN_CIRCLE_LOAD_GAP)
|
||||
{
|
||||
RsTickEvent::schedule_in(CIRCLE_EVENT_CACHELOAD,
|
||||
MIN_CIRCLE_LOAD_GAP - age);
|
||||
RsTickEvent::schedule_in(CIRCLE_EVENT_CACHELOAD, MIN_CIRCLE_LOAD_GAP - age);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1090,8 +1096,8 @@ bool p3GxsCircles::cache_load_for_token(uint32_t token)
|
||||
isUnprocessedPeers = false;
|
||||
}
|
||||
|
||||
// we can check for self inclusion in the circle right away, since own ids are always loaded.
|
||||
// that allows to subscribe/unsubscribe uncomplete circles
|
||||
// we can check for self inclusion in the circle right away, since own ids are always loaded.
|
||||
// that allows to subscribe/unsubscribe uncomplete circles
|
||||
checkCircleCacheForAutoSubscribe(cache);
|
||||
|
||||
if (isComplete)
|
||||
@ -1241,7 +1247,24 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsCircles::checkCircleCacheForMembershipUpdate(RsGxsCircleCache& cache)
|
||||
{
|
||||
if(cache.mLastUpdatedMembership_TS + < now)
|
||||
{
|
||||
// this should be called regularly
|
||||
uint32_t token ;
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||
std::list<RsGxsGroupId> grpIds ;
|
||||
|
||||
grpIds.push_back(grp) ;
|
||||
|
||||
RsGenExchange::getTokenService()->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds);
|
||||
GxsTokenQueue::queueRequest(token, CIRCLEREQ_MESSAGE_DATA);
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
/* We need to AutoSubscribe if the Circle is relevent to us */
|
||||
|
||||
@ -1752,6 +1775,10 @@ void p3GxsCircles::handleResponse(uint32_t token, uint32_t req_type)
|
||||
load_CircleIdList(token);
|
||||
break;
|
||||
|
||||
case CIRCLEREQ_MESSAGE_DATA:
|
||||
processMembershipRequests(token);
|
||||
break;
|
||||
|
||||
case CIRCLEREQ_CACHELOAD:
|
||||
cache_load_for_token(token);
|
||||
break;
|
||||
@ -1838,8 +1865,22 @@ void p3GxsCircles::handle_event(uint32_t event_type, const std::string &elabel)
|
||||
// - compatibility with self-restricted circles:
|
||||
// * subscription should be based on admin list, so that non subscribed peers still receive the invitation
|
||||
//
|
||||
// - two possible subscription models for circle member list (Restricted forums only propagate to members):
|
||||
// 1 - list of admin who have not opposed subscription
|
||||
// - solves propagation issue. Only admin see data. They can however unsubscribe using a negative req. Admin needs to remove them.
|
||||
// - bad for security. Admin can refuse to remove them => back to square one
|
||||
// 2 - list of admin who have also requested membership
|
||||
// - propagation is ok. On restricted circle, the circle msgs/group should be sent to admin list, instead of member list.
|
||||
// - solves membership issue since people need to actively be in the group.
|
||||
// => choose 2
|
||||
// - forum group : encrypted for Member list
|
||||
// - circle group : clear / encrypted for admin list (for self-restricted)
|
||||
// We decide between the two by comparing the group we're sending and the circle id it is restricted to.
|
||||
//
|
||||
// - Use cases
|
||||
// * user sees group (not self restricted) and requests to subscribe => RS subscribes the group and the user can propagate the response
|
||||
// * user is invited to self-restricted circle. He will see it and can subscribe, so he will be in admin list and receive e.g. forum posts.
|
||||
// *
|
||||
//
|
||||
// - Threat model
|
||||
// * a malicious user forges a new subscription request: NP-hard as it needs to break the RSA key of the GXS id.
|
||||
@ -1848,6 +1889,23 @@ void p3GxsCircles::handle_event(uint32_t event_type, const std::string &elabel)
|
||||
// => not possible. Either this existing old susbscription already exists, or it has been replaced by a more recent one, which
|
||||
// will always replace the old one because of the date.
|
||||
// * a malicious user removes someone's subscription messages. This is possible, but the mesh nature of the network will allow the message to propagate anyway.
|
||||
// * a malicious user creates a circle with an incriminating name/content and adds everyone in it
|
||||
// => people can oppose their membership in the circle using a msg
|
||||
//
|
||||
//
|
||||
// - the table below summarizes the various choices: forum and circle propagation when restricted to a circle, and group subscribe to the circle
|
||||
//
|
||||
// +------------------------------+-----------------------------+
|
||||
// | User in admin list | User not in admin list |
|
||||
// +-------------+------------------------------+-----------------------------+
|
||||
// | User request| Forum Grp/Msg: YES | Forum Grp/Msg: NO |
|
||||
// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO |
|
||||
// | | Grp Subscribed: YES | Grp Subscribed: YES |
|
||||
// +-------------+------------------------------+-----------------------------+
|
||||
// | No request | Forum Grp/Msg: NO | Forum Grp/Msg: NO |
|
||||
// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO |
|
||||
// | | Grp Subscribed: NO | Grp Subscribed: NO |
|
||||
// +-------------+------------------------------+-----------------------------+
|
||||
|
||||
bool p3GxsCircles::pushCircleMembershipRequest(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id,uint32_t request_type)
|
||||
{
|
||||
@ -1909,7 +1967,79 @@ bool p3GxsCircles::cancelCircleMembership(const RsGxsId& own_gxsid,const RsGxsCi
|
||||
{
|
||||
return pushCircleMembershipRequest(own_gxsid,circle_id,RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE) ;
|
||||
}
|
||||
|
||||
|
||||
bool p3GxsCircles::processMembershipRequests(uint32_t token)
|
||||
{
|
||||
// Go through membership request messages and process them according to the following rule:
|
||||
// * for each ID only keep the latest membership request. Delete the older ones.
|
||||
// * for each circle, keep a list of IDs sorted into membership categories (e.g. keep updated flags for each IDs)
|
||||
// Because msg loading is async-ed, the job in split in two methods: one calls the loading, the other one handles the loaded data.
|
||||
|
||||
GxsMsgDataMap msgItems ;
|
||||
|
||||
if(!RsGenExchange::getMsgData(token, msgItems))
|
||||
{
|
||||
std::cerr << "(EE) Cannot get msg data for circle. Something's weird." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
GxsMsgReq messages_to_delete ;
|
||||
|
||||
for(GxsMsgDataMap::const_iterator it(msgItems.begin());it!=msgItems.end();++it)
|
||||
{
|
||||
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
||||
std::cerr << "Circle ID: " << it->first << std::endl;
|
||||
|
||||
RsGxsCircleId cid = it->first ;
|
||||
|
||||
if (!mCircleCache.is_cached(cid))
|
||||
{
|
||||
std::cerr << "(EE) Circle is not in cache!" << std::endl;
|
||||
continue ;
|
||||
}
|
||||
|
||||
// Find the circle ID in cache and process the list of messages to keep the latest order in time.
|
||||
|
||||
RsGxsCircleCache& data = mCircleCache.ref(cid);
|
||||
|
||||
for(uint32_t i=0;i<it->second.size();++i)
|
||||
{
|
||||
RsGxsCircleSubscriptionRequestItem *item = dynamic_cast<RsGxsCircleSubscriptionRequestItem*>(it->second[i]) ;
|
||||
|
||||
if(item == NULL)
|
||||
{
|
||||
std::cerr << "(EE) item is not a RsGxsCircleSubscriptionRequestItem. Weird." << std::endl;
|
||||
continue ;
|
||||
}
|
||||
|
||||
|
||||
RsGxsCircleSubscriptionStatusInfo& info(data.mSubscriptions[item->meta.mAuthorId]) ;
|
||||
|
||||
if(info.subscription_TS < item->time_stamp)
|
||||
{
|
||||
info.subscription_TS = item->time_stamp ;
|
||||
|
||||
if(item->subscription_type == RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE)
|
||||
info.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED;
|
||||
else if(item->subscription_type == RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE)
|
||||
info.subscription_flags &= ~GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED;
|
||||
else
|
||||
std::cerr << "(EE) unknown subscription order type " << item->subscription_type << " for circle " << cid << " by id " << item->meta.mAuthorId << std::endl;
|
||||
}
|
||||
else if(info.subscription_TS > item->time_stamp)
|
||||
{
|
||||
std::cerr << " scheduling for deletion" << std::endl;
|
||||
messages_to_delete[RsGxsGroupId(cid)].push_back(it->second[i]->meta.mMsgId) ;
|
||||
}
|
||||
}
|
||||
|
||||
data.mLastUpdatedMembershipTS = time(NULL) ;
|
||||
}
|
||||
|
||||
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
|
||||
mDataStore->removeMsgs(messages_to_delete);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -124,6 +124,15 @@
|
||||
/* Permissions is part of GroupMetaData
|
||||
*/
|
||||
|
||||
class RsGxsCircleMembershipStatus
|
||||
{
|
||||
public:
|
||||
RsGxsCircleMembershipStatus() : subscription_TS(0), subscription_flags(0) {}
|
||||
|
||||
time_t last_subscription_TS ;
|
||||
uint32_t subscription_flags ; // combination of GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST and GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED
|
||||
};
|
||||
|
||||
class RsGxsCircleCache
|
||||
{
|
||||
public:
|
||||
@ -153,9 +162,10 @@ class RsGxsCircleCache
|
||||
std::set<RsGxsCircleId> mUnprocessedCircles;
|
||||
std::set<RsGxsCircleId> mProcessedCircles;
|
||||
#endif
|
||||
std::set<RsGxsId> mUnprocessedPeers;
|
||||
std::map<RsGxsId,RsGxsCircleMembershipStatus> mMembershipStatusMap;
|
||||
time_t mLastUpdateMembershipTS ; // last time the subscribe messages have been requested. Should be reset when new messages arrive.
|
||||
|
||||
std::set<RsGxsId> mAllowedGxsIds;
|
||||
std::set<RsGxsId> mAllowedGxsIds; // IDs that are allowed in the circle and have requested membership. This is the official members list.
|
||||
std::set<RsPgpId> mAllowedNodes;
|
||||
|
||||
RsPeerId mOriginator ; // peer who sent the data, in case we need to ask for ids
|
||||
@ -224,6 +234,7 @@ virtual RsServiceInfo getServiceInfo();
|
||||
// Load data.
|
||||
bool request_CircleIdList();
|
||||
bool load_CircleIdList(uint32_t token);
|
||||
bool processMembershipRequests(uint32_t token);
|
||||
|
||||
// Need some crazy arsed cache to store the circle info.
|
||||
// so we don't have to keep loading groups.
|
||||
@ -237,6 +248,7 @@ virtual RsServiceInfo getServiceInfo();
|
||||
bool cache_reloadids(const RsGxsCircleId &circleId);
|
||||
|
||||
bool checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache);
|
||||
bool checkCircleCacheForMembershipUpdate(RsGxsCircleCache& cache);
|
||||
|
||||
|
||||
p3IdService *mIdentities; // Needed for constructing Circle Info,
|
||||
|
Loading…
Reference in New Issue
Block a user