2012-11-29 17:48:28 -05:00
/*
* libretroshare / src / services p3gxscircles . cc
*
* Circles Interface for RetroShare .
*
* Copyright 2012 - 2012 by Robert Fernie .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " retroshare@lunamutt.com " .
*
*/
# include "services/p3gxscircles.h"
# include "serialiser/rsgxscircleitems.h"
2013-02-28 16:58:38 -05:00
# include "retroshare/rsgxsflags.h"
2012-11-29 17:48:28 -05:00
# include "util/rsrandom.h"
2016-05-11 17:59:42 -04:00
# include "util/rsdir.h"
# include "util/radix64.h"
2012-11-29 17:48:28 -05:00
# include "util/rsstring.h"
2014-04-27 09:14:07 -04:00
# include "pgp/pgpauxutils.h"
2016-05-18 21:13:54 -04:00
# include "retroshare/rsgxscircles.h"
2016-05-21 15:51:49 -04:00
# include "retroshare/rspeers.h"
2012-11-29 17:48:28 -05:00
# include <sstream>
# include <stdio.h>
/****
2013-02-27 16:16:03 -05:00
* # define DEBUG_CIRCLES 1
2012-11-29 17:48:28 -05:00
* * * */
RsGxsCircles * rsGxsCircles = NULL ;
/******
*
* GxsCircles are used to limit the spread of Gxs Groups and Messages .
*
* This is done via GxsCircle parameters in GroupMetaData :
* mCircleType ( ALL , External , Internal ) .
* mCircleId .
*
* The Circle Group contains the definition of who is allowed access to the Group .
* and GXS asks this service before forwarding any data .
*
* The CircleGroup contains :
* list of GxsId ' s
* list of GxsCircleId ' s ( subcircles also allowed ) .
*
* This service runs a background task to transform the CircleGroups
* into a list of friends / peers who are allowed access .
* These results are cached to provide GXS with quick access to the information .
* This involves :
* - fetching the GroupData via GXS .
* - querying the list of GxsId to see if they are known .
* ( NB : this will cause caching of GxsId in p3IdService .
* - recursively loading subcircles to complete Circle definition .
* - saving the result into Cache .
*
* For Phase 1 , we will only use the list of GxsIds . No subcircles will be allowed .
* Recursively determining membership via sub - circles is complex and needs more thought .
* The data - types for the full system , however , will be in - place .
*/
2016-05-17 00:00:15 -04:00
# define CIRCLEREQ_CACHELOAD 0x0001
# define CIRCLEREQ_CIRCLE_LIST 0x0002
# define CIRCLEREQ_MESSAGE_DATA 0x0003
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
//#define CIRCLEREQ_PGPHASH 0x0010
//#define CIRCLEREQ_REPUTATION 0x0020
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
//#define CIRCLEREQ_CACHETEST 0x1000
2012-11-29 17:48:28 -05:00
// Events.
2012-12-15 18:07:12 -05:00
# define CIRCLE_EVENT_LOADIDS 0x0001
2012-11-29 17:48:28 -05:00
# define CIRCLE_EVENT_CACHELOAD 0x0002
# define CIRCLE_EVENT_RELOADIDS 0x0003
2012-12-15 18:07:12 -05:00
# define CIRCLE_EVENT_DUMMYSTART 0x0004
# define CIRCLE_EVENT_DUMMYLOAD 0x0005
# define CIRCLE_EVENT_DUMMYGEN 0x0006
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
# define CIRCLE_DUMMY_STARTPERIOD 300 // MUST BE LONG ENOUGH FOR IDS TO HAVE BEEN MADE.
# define CIRCLE_DUMMY_GENPERIOD 10
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
//#define CIRCLE_EVENT_CACHETEST 0x1000
//#define CACHETEST_PERIOD 60
//#define OWNID_RELOAD_DELAY 10
2012-11-29 17:48:28 -05:00
# define GXSID_LOAD_CYCLE 10 // GXSID completes a load in this period.
# define MIN_CIRCLE_LOAD_GAP 5
2016-05-22 20:35:51 -04:00
# define GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages.
# define GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages.
2012-11-29 17:48:28 -05:00
/********************************************************************************/
/******************* Startup / Tick ******************************************/
/********************************************************************************/
2014-04-27 09:14:07 -04:00
p3GxsCircles : : p3GxsCircles ( RsGeneralDataService * gds , RsNetworkExchangeService * nes ,
p3IdService * identities , PgpAuxUtils * pgpUtils )
2012-11-29 17:48:28 -05:00
: RsGxsCircleExchange ( gds , nes , new RsGxsCircleSerialiser ( ) ,
2014-03-29 11:34:37 -04:00
RS_SERVICE_GXS_TYPE_GXSCIRCLE , identities , circleAuthenPolicy ( ) ) ,
2014-04-27 09:14:07 -04:00
RsGxsCircles ( this ) , GxsTokenQueue ( this ) , RsTickEvent ( ) ,
mIdentities ( identities ) ,
mPgpUtils ( pgpUtils ) ,
2012-11-29 17:48:28 -05:00
mCircleMtx ( " p3GxsCircles " ) ,
mCircleCache ( DEFAULT_MEM_CACHE_SIZE , " GxsCircleCache " )
{
// Kick off Cache Testing, + Others.
2012-12-15 18:07:12 -05:00
//RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD);
2016-05-22 20:35:51 -04:00
mLastCacheMembershipUpdateTS = 0 ;
2012-12-15 18:07:12 -05:00
RsTickEvent : : schedule_now ( CIRCLE_EVENT_LOADIDS ) ;
// Dummy Circles.
2016-04-14 23:09:59 -04:00
// RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYSTART, CIRCLE_DUMMY_STARTPERIOD);
mDummyIdToken = 0 ;
2012-11-29 17:48:28 -05:00
}
2016-05-18 21:13:54 -04:00
static bool allowedGxsIdFlagTest ( uint32_t subscription_flags , bool group_is_self_restricted )
{
if ( group_is_self_restricted )
return ( subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ) & & ( subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE ) ;
else
return ( subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ) & & ( subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED ) & & ( subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE ) ;
}
2012-11-29 17:48:28 -05:00
2014-03-21 23:53:44 -04:00
const std : : string GXS_CIRCLES_APP_NAME = " gxscircle " ;
const uint16_t GXS_CIRCLES_APP_MAJOR_VERSION = 1 ;
const uint16_t GXS_CIRCLES_APP_MINOR_VERSION = 0 ;
const uint16_t GXS_CIRCLES_MIN_MAJOR_VERSION = 1 ;
const uint16_t GXS_CIRCLES_MIN_MINOR_VERSION = 0 ;
RsServiceInfo p3GxsCircles : : getServiceInfo ( )
{
2014-03-29 11:34:37 -04:00
return RsServiceInfo ( RS_SERVICE_GXS_TYPE_GXSCIRCLE ,
2014-03-21 23:53:44 -04:00
GXS_CIRCLES_APP_NAME ,
GXS_CIRCLES_APP_MAJOR_VERSION ,
GXS_CIRCLES_APP_MINOR_VERSION ,
GXS_CIRCLES_MIN_MAJOR_VERSION ,
GXS_CIRCLES_MIN_MINOR_VERSION ) ;
}
2012-11-29 17:48:28 -05:00
uint32_t p3GxsCircles : : circleAuthenPolicy ( )
{
2013-02-10 12:52:50 -05:00
uint32_t policy = 0 ;
uint8_t flag = 0 ;
2013-03-24 15:21:30 -04:00
//flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN;
//flag = GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN;
//flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN;
//flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN;
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : PUBLIC_GRP_BITS ) ;
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : RESTRICTED_GRP_BITS ) ;
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : PRIVATE_GRP_BITS ) ;
flag = 0 ;
//flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN;
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : GRP_OPTION_BITS ) ;
2013-02-10 12:52:50 -05:00
return policy ;
2012-11-29 17:48:28 -05:00
}
2013-02-10 12:52:50 -05:00
2012-11-29 17:48:28 -05:00
void p3GxsCircles : : service_tick ( )
{
RsTickEvent : : tick_events ( ) ;
GxsTokenQueue : : checkRequests ( ) ; // GxsTokenQueue handles all requests.
2016-05-22 20:35:51 -04:00
time_t now = time ( NULL ) ;
if ( now > mLastCacheMembershipUpdateTS + GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE )
{
p3GxsCircles : : checkCircleCacheForMembershipUpdate ( ) ;
mLastCacheMembershipUpdateTS = now ;
}
2012-11-29 17:48:28 -05:00
return ;
}
void p3GxsCircles : : notifyChanges ( std : : vector < RsGxsNotify * > & changes )
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-03-14 23:19:37 -04:00
std : : cerr < < " p3GxsCircles::notifyChanges() " ;
std : : cerr < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2012-11-29 17:48:28 -05:00
2016-03-14 23:19:37 -04:00
std : : vector < RsGxsNotify * > : : iterator it ;
for ( it = changes . begin ( ) ; it ! = changes . end ( ) ; + + it )
{
RsGxsGroupChange * groupChange = dynamic_cast < RsGxsGroupChange * > ( * it ) ;
RsGxsMsgChange * msgChange = dynamic_cast < RsGxsMsgChange * > ( * it ) ;
2016-05-24 21:07:50 -04:00
2016-03-14 23:19:37 -04:00
if ( msgChange & & ! msgChange - > metaChange ( ) )
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-05-24 21:07:50 -04:00
std : : cerr < < " Found circle Message Change Notification " < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2016-05-24 21:07:50 -04:00
for ( std : : map < RsGxsGroupId , std : : vector < RsGxsMessageId > > : : iterator mit = msgChange - > msgChangeMap . begin ( ) ; mit ! = msgChange - > msgChangeMap . end ( ) ; + + mit )
2016-03-14 23:19:37 -04:00
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-05-24 21:07:50 -04:00
std : : cerr < < " Msgs for Group: " < < mit - > first < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2016-05-24 21:07:50 -04:00
for ( std : : map < RsGxsGroupId , std : : vector < RsGxsMessageId > > : : const_iterator it2 ( msgChange - > msgChangeMap . begin ( ) ) ; it2 ! = msgChange - > msgChangeMap . end ( ) ; + + it2 )
force_cache_reload ( RsGxsCircleId ( it2 - > first ) ) ;
2016-03-14 23:19:37 -04:00
}
}
2012-11-30 19:16:24 -05:00
2016-03-14 23:19:37 -04:00
/* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */
if ( groupChange & & ! groupChange - > metaChange ( ) )
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-05-24 21:07:50 -04:00
std : : cerr < < " Found Group Change Notification " < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2016-05-24 21:07:50 -04:00
for ( std : : list < RsGxsGroupId > : : iterator git = groupChange - > mGrpIdList . begin ( ) ; git ! = groupChange - > mGrpIdList . end ( ) ; + + git )
2016-03-14 23:19:37 -04:00
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-03-14 23:19:37 -04:00
std : : cerr < < " Incoming Group: " < < * git < < " . Forcing cache load. " < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2012-11-30 19:16:24 -05:00
2016-03-14 23:19:37 -04:00
// for new circles we need to add them to the list.
// we don't know the type of this circle here
// original behavior was to add all ids to the external ids list
2016-05-24 21:07:50 -04:00
2016-03-14 23:19:37 -04:00
addCircleIdToList ( RsGxsCircleId ( * git ) , 0 ) ;
// reset the cached circle data for this id
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
mCircleCache . erase ( RsGxsCircleId ( * git ) ) ;
}
}
}
2016-05-24 21:07:50 -04:00
if ( groupChange )
for ( std : : list < RsGxsGroupId > : : const_iterator git ( groupChange - > mGrpIdList . begin ( ) ) ; git ! = groupChange - > mGrpIdList . end ( ) ; + + git )
{
2016-03-14 23:19:37 -04:00
# ifdef DEBUG_CIRCLES
2016-05-24 21:07:50 -04:00
std : : cerr < < " forcing cache loading for circle " < < * git < < " in order to trigger subscribe update. " < < std : : endl ;
2016-03-14 23:19:37 -04:00
# endif
2016-05-24 21:07:50 -04:00
force_cache_reload ( RsGxsCircleId ( * git ) ) ;
}
2016-03-14 23:19:37 -04:00
}
RsGxsIfaceHelper : : receiveChanges ( changes ) ; // this clear up the vector and delete its elements
2012-11-29 17:48:28 -05:00
}
2013-06-04 17:00:43 -04:00
/********************************************************************************/
/******************* RsCircles Interface ***************************************/
/********************************************************************************/
2012-12-15 18:07:12 -05:00
bool p3GxsCircles : : getCircleDetails ( const RsGxsCircleId & id , RsGxsCircleDetails & details )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2016-05-18 21:13:54 -04:00
std : : cerr < < " p3GxsCircles::getCircleDetails( " < < id < < " ) " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( mCircleCache . is_cached ( id ) )
{
RsGxsCircleCache & data = mCircleCache . ref ( id ) ;
2012-12-15 18:07:12 -05:00
2016-05-18 21:13:54 -04:00
// should also have meta data....
details . mCircleId = id ;
details . mCircleName = data . mCircleName ;
2013-06-04 17:00:43 -04:00
2016-05-18 21:13:54 -04:00
details . mCircleType = data . mCircleType ;
2013-06-04 17:00:43 -04:00
2016-05-18 21:13:54 -04:00
details . mAllowedNodes = data . mAllowedNodes ;
details . mSubscriptionFlags . clear ( ) ;
details . mAllowedGxsIds . clear ( ) ;
2016-05-23 21:09:06 -04:00
details . mAmIAllowed = false ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
for ( std : : map < RsGxsId , RsGxsCircleMembershipStatus > : : const_iterator it ( data . mMembershipStatus . begin ( ) ) ; it ! = data . mMembershipStatus . end ( ) ; + + it )
{
details . mSubscriptionFlags [ it - > first ] = it - > second . subscription_flags ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
if ( it - > second . subscription_flags = = GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED )
2016-05-23 21:09:06 -04:00
{
2016-05-18 21:13:54 -04:00
details . mAllowedGxsIds . insert ( it - > first ) ;
2016-05-23 21:09:06 -04:00
if ( rsIdentity - > isOwnId ( it - > first ) )
details . mAmIAllowed = true ;
}
2016-05-18 21:13:54 -04:00
}
return true ;
}
}
/* it isn't there - add to public requests */
cache_request_load ( id ) ;
return false ;
2012-11-29 17:48:28 -05:00
}
2013-06-04 17:00:43 -04:00
bool p3GxsCircles : : getCirclePersonalIdList ( std : : list < RsGxsCircleId > & circleIds )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::getCircleIdList() " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
2012-11-29 17:48:28 -05:00
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
2013-06-04 17:00:43 -04:00
if ( circleIds . empty ( ) )
{
circleIds = mCirclePersonalIdList ;
}
else
{
std : : list < RsGxsCircleId > : : const_iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = mCirclePersonalIdList . begin ( ) ; it ! = mCirclePersonalIdList . begin ( ) ; + + it )
2013-06-04 17:00:43 -04:00
{
circleIds . push_back ( * it ) ;
}
}
return true ;
}
bool p3GxsCircles : : getCircleExternalIdList ( std : : list < RsGxsCircleId > & circleIds )
{
# ifdef DEBUG_CIRCLES
std : : cerr < < " p3GxsCircles::getCircleIdList() " ;
std : : cerr < < std : : endl ;
# endif // DEBUG_CIRCLES
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( circleIds . empty ( ) )
{
circleIds = mCircleExternalIdList ;
}
else
{
std : : list < RsGxsCircleId > : : const_iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = mCircleExternalIdList . begin ( ) ; it ! = mCircleExternalIdList . begin ( ) ; + + it )
2013-06-04 17:00:43 -04:00
{
circleIds . push_back ( * it ) ;
}
}
2012-11-29 17:48:28 -05:00
return true ;
}
/********************************************************************************/
2013-06-04 17:00:43 -04:00
/******************* RsGcxs Interface ***************************************/
2012-11-29 17:48:28 -05:00
/********************************************************************************/
bool p3GxsCircles : : isLoaded ( const RsGxsCircleId & circleId )
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
return mCircleCache . is_cached ( circleId ) ;
}
bool p3GxsCircles : : loadCircle ( const RsGxsCircleId & circleId )
{
return cache_request_load ( circleId ) ;
}
2016-02-20 17:53:03 -05:00
int p3GxsCircles : : canSend ( const RsGxsCircleId & circleId , const RsPgpId & id , bool & should_encrypt )
2013-06-04 17:00:43 -04:00
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( mCircleCache . is_cached ( circleId ) )
{
RsGxsCircleCache & data = mCircleCache . ref ( circleId ) ;
2016-02-20 17:53:03 -05:00
should_encrypt = ( data . mCircleType = = GXS_CIRCLE_TYPE_EXTERNAL ) ;
2013-06-04 17:00:43 -04:00
if ( data . isAllowedPeer ( id ) )
return 1 ;
2016-02-20 17:53:03 -05:00
2013-06-04 17:00:43 -04:00
return 0 ;
}
return - 1 ;
}
int p3GxsCircles : : canReceive ( const RsGxsCircleId & circleId , const RsPgpId & id )
2012-11-29 17:48:28 -05:00
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( mCircleCache . is_cached ( circleId ) )
{
RsGxsCircleCache & data = mCircleCache . ref ( circleId ) ;
if ( data . isAllowedPeer ( id ) )
{
return 1 ;
}
return 0 ;
}
return - 1 ;
}
2015-09-27 23:53:55 -04:00
bool p3GxsCircles : : recipients ( const RsGxsCircleId & circleId , std : : list < RsPgpId > & friendlist )
2012-11-29 17:48:28 -05:00
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( mCircleCache . is_cached ( circleId ) )
{
RsGxsCircleCache & data = mCircleCache . ref ( circleId ) ;
data . getAllowedPeersList ( friendlist ) ;
return true ;
}
return false ;
}
2016-05-18 21:13:54 -04:00
bool p3GxsCircles : : isRecipient ( const RsGxsCircleId & circleId , const RsGxsGroupId & destination_group , const RsGxsId & id )
2016-03-23 20:54:45 -04:00
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( mCircleCache . is_cached ( circleId ) )
{
const RsGxsCircleCache & data = mCircleCache . ref ( circleId ) ;
2016-05-18 21:13:54 -04:00
return data . isAllowedPeer ( id , destination_group ) ;
2016-03-23 20:54:45 -04:00
}
return false ;
}
2016-05-18 21:13:54 -04:00
// This function uses the destination group for the transaction in order to decide which list of
2016-05-17 00:00:15 -04:00
// 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.
2016-05-18 21:13:54 -04:00
bool p3GxsCircles : : recipients ( const RsGxsCircleId & circleId , const RsGxsGroupId & dest_group , std : : list < RsGxsId > & gxs_ids )
2015-09-27 23:53:55 -04:00
{
2016-05-18 21:13:54 -04:00
gxs_ids . clear ( ) ;
2015-09-27 23:53:55 -04:00
2016-05-18 21:13:54 -04:00
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( ! mCircleCache . is_cached ( circleId ) )
return false ;
const RsGxsCircleCache & cache = mCircleCache . ref ( circleId ) ;
for ( std : : map < RsGxsId , RsGxsCircleMembershipStatus > : : const_iterator it ( cache . mMembershipStatus . begin ( ) ) ; it ! = cache . mMembershipStatus . end ( ) ; + + it )
if ( allowedGxsIdFlagTest ( it - > second . subscription_flags , RsGxsCircleId ( dest_group ) = = circleId ) )
gxs_ids . push_back ( it - > first ) ;
return true ;
2015-09-27 23:53:55 -04:00
}
2012-11-29 17:48:28 -05:00
/********************************************************************************/
/******************* Get/Set Data ******************************************/
/********************************************************************************/
bool p3GxsCircles : : getGroupData ( const uint32_t & token , std : : vector < RsGxsCircleGroup > & groups )
{
std : : vector < RsGxsGrpItem * > grpData ;
bool ok = RsGenExchange : : getGroupData ( token , grpData ) ;
if ( ok )
{
std : : vector < RsGxsGrpItem * > : : iterator vit = grpData . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = grpData . end ( ) ; + + vit )
2012-11-29 17:48:28 -05:00
{
RsGxsCircleGroupItem * item = dynamic_cast < RsGxsCircleGroupItem * > ( * vit ) ;
2013-07-20 21:50:13 -04:00
if ( item )
{
RsGxsCircleGroup group ;
item - > convertTo ( group ) ;
2012-11-29 17:48:28 -05:00
2013-07-20 21:50:13 -04:00
// If its cached - add that info (TODO).
groups . push_back ( group ) ;
delete ( item ) ;
}
else
{
2014-04-30 07:50:45 -04:00
std : : cerr < < " p3GxsCircles::getGroupData() " ;
std : : cerr < < " Not a RsGxsCircleGroupItem, deleting! " ;
std : : cerr < < std : : endl ;
2013-07-20 21:50:13 -04:00
delete * vit ;
}
2012-11-29 17:48:28 -05:00
}
}
return ok ;
}
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
2014-08-25 17:07:07 -04:00
void p3GxsCircles : : createGroup ( uint32_t & token , RsGxsCircleGroup & group )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::createGroup() " ;
2014-04-30 07:50:45 -04:00
std : : cerr < < " CircleType: " < < ( uint32_t ) group . mMeta . mCircleType ;
std : : cerr < < " CircleId: " < < group . mMeta . mCircleId . toStdString ( ) ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
RsGxsCircleGroupItem * item = new RsGxsCircleGroupItem ( ) ;
item - > convertFrom ( group ) ;
2014-04-30 07:50:45 -04:00
2012-12-15 18:07:12 -05:00
RsGenExchange : : publishGroup ( token , item ) ;
2014-08-25 17:07:07 -04:00
}
void p3GxsCircles : : updateGroup ( uint32_t & token , RsGxsCircleGroup & group )
{
// note: refresh of circle cache gets triggered in the RsGenExchange::notifyChanges() callback
RsGxsCircleGroupItem * item = new RsGxsCircleGroupItem ( ) ;
item - > convertFrom ( group ) ;
RsGenExchange : : updateGroup ( token , item ) ;
2012-11-29 17:48:28 -05:00
}
2013-03-08 14:55:59 -05:00
RsGenExchange : : ServiceCreate_Return p3GxsCircles : : service_CreateGroup ( RsGxsGrpItem * grpItem , RsTlvSecurityKeySet & /*keySet*/ )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::service_CreateGroup() " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
2012-11-29 17:48:28 -05:00
RsGxsCircleGroupItem * item = dynamic_cast < RsGxsCircleGroupItem * > ( grpItem ) ;
if ( ! item )
{
std : : cerr < < " p3GxsCircles::service_CreateGroup() ERROR invalid cast " ;
std : : cerr < < std : : endl ;
2013-03-08 14:55:59 -05:00
return SERVICE_CREATE_FAIL ;
2012-11-29 17:48:28 -05:00
}
// Now copy the GroupId into the mCircleId, and set the mode.
2013-06-04 17:00:43 -04:00
if ( item - > meta . mCircleType = = GXS_CIRCLE_TYPE_EXT_SELF )
{
item - > meta . mCircleType = GXS_CIRCLE_TYPE_EXTERNAL ;
2014-04-20 12:34:26 -04:00
item - > meta . mCircleId = RsGxsCircleId ( item - > meta . mGroupId ) ;
2013-06-04 17:00:43 -04:00
}
2012-11-29 17:48:28 -05:00
2014-08-25 17:07:07 -04:00
// the advantage of adding the id to the list now is, that we know the cirlce type at this point
// this is not the case in NotifyChanges()
addCircleIdToList ( RsGxsCircleId ( item - > meta . mGroupId ) , item - > meta . mCircleType ) ;
2013-03-08 14:55:59 -05:00
return SERVICE_CREATE_SUCCESS ;
2012-11-29 17:48:28 -05:00
}
/************************************************************************************/
/************************************************************************************/
/************************************************************************************/
/*
* Cache of recently used circles .
*/
RsGxsCircleCache : : RsGxsCircleCache ( )
{
2013-06-04 17:00:43 -04:00
mCircleType = GXS_CIRCLE_TYPE_EXTERNAL ;
mIsExternal = true ;
mUpdateTime = 0 ;
mGroupStatus = 0 ;
2016-03-15 22:11:36 -04:00
mGroupSubscribeFlags = 0 ;
2016-05-22 20:35:51 -04:00
mLastUpdatedMembershipTS = 0 ;
2013-06-04 17:00:43 -04:00
2012-11-29 17:48:28 -05:00
return ;
}
bool RsGxsCircleCache : : loadBaseCircle ( const RsGxsCircleGroup & circle )
{
2014-04-20 12:34:26 -04:00
mCircleId = RsGxsCircleId ( circle . mMeta . mGroupId ) ;
2012-12-15 18:07:12 -05:00
mCircleName = circle . mMeta . mGroupName ;
2012-11-29 17:48:28 -05:00
mUpdateTime = time ( NULL ) ;
2016-03-14 23:19:37 -04:00
// mProcessedCircles.insert(mCircleId);
2012-11-29 17:48:28 -05:00
2013-06-04 17:00:43 -04:00
mCircleType = circle . mMeta . mCircleType ;
mIsExternal = ( mCircleType ! = GXS_CIRCLE_TYPE_LOCAL ) ;
mGroupStatus = circle . mMeta . mGroupStatus ;
2016-03-15 22:11:36 -04:00
mGroupSubscribeFlags = circle . mMeta . mSubscribeFlags ;
2016-05-18 21:13:54 -04:00
mOriginator = circle . mMeta . mOriginator ;
mAllowedNodes = circle . mLocalFriends ;
mMembershipStatus . clear ( ) ;
for ( std : : set < RsGxsId > : : const_iterator it ( circle . mInvitedMembers . begin ( ) ) ; it ! = circle . mInvitedMembers . end ( ) ; + + it )
{
RsGxsCircleMembershipStatus & s ( mMembershipStatus [ * it ] ) ;
s . last_subscription_TS = 0 ;
s . subscription_flags = GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ;
}
2013-06-04 17:00:43 -04:00
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
std : : cerr < < " RsGxsCircleCache::loadBaseCircle( " < < mCircleId < < " ) " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
return true ;
}
bool RsGxsCircleCache : : loadSubCircle ( const RsGxsCircleCache & subcircle )
{
/* copy across all the lists */
/* should not be any unprocessed circles or peers */
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2013-06-04 17:00:43 -04:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
std : : cerr < < " RsGxsCircleCache::loadSubCircle( " < < subcircle . mCircleId < < " ) TODO " ;
std : : cerr < < std : : endl ;
return true ;
}
2016-04-17 17:13:42 -04:00
bool RsGxsCircleCache : : getAllowedPeersList ( std : : list < RsPgpId > & friendlist ) const
2012-11-29 17:48:28 -05:00
{
2016-04-17 17:13:42 -04:00
friendlist . clear ( ) ;
for ( std : : set < RsPgpId > : : const_iterator it = mAllowedNodes . begin ( ) ; it ! = mAllowedNodes . end ( ) ; + + it )
friendlist . push_back ( * it ) ;
2012-11-29 17:48:28 -05:00
return true ;
}
2016-05-18 21:13:54 -04:00
bool RsGxsCircleCache : : isAllowedPeer ( const RsGxsId & id , const RsGxsGroupId & destination_group ) const
2016-03-23 20:54:45 -04:00
{
2016-05-18 21:13:54 -04:00
std : : map < RsGxsId , RsGxsCircleMembershipStatus > : : const_iterator it = mMembershipStatus . find ( id ) ;
2016-03-23 20:54:45 -04:00
2016-05-18 21:13:54 -04:00
if ( it = = mMembershipStatus . end ( ) )
return false ;
return allowedGxsIdFlagTest ( it - > second . subscription_flags , RsGxsGroupId ( mCircleId ) = = destination_group ) ;
2016-03-23 20:54:45 -04:00
}
bool RsGxsCircleCache : : isAllowedPeer ( const RsPgpId & id ) const
2012-11-29 17:48:28 -05:00
{
2016-04-17 17:13:42 -04:00
return mAllowedNodes . find ( id ) ! = mAllowedNodes . end ( ) ;
2012-11-29 17:48:28 -05:00
}
2013-06-04 17:00:43 -04:00
bool RsGxsCircleCache : : addLocalFriend ( const RsPgpId & pgpId )
{
/* empty list as no GxsID associated */
2016-04-17 17:13:42 -04:00
mAllowedNodes . insert ( pgpId ) ;
2013-06-04 17:00:43 -04:00
return true ;
}
2012-11-29 17:48:28 -05:00
/************************************************************************************/
/************************************************************************************/
2012-12-15 18:07:12 -05:00
bool p3GxsCircles : : request_CircleIdList ( )
2012-11-29 17:48:28 -05:00
{
/* trigger request to load missing ids into cache */
std : : list < RsGxsGroupId > groupIds ;
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::request_CircleIdList() " ;
2012-11-29 17:48:28 -05:00
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2013-06-04 17:00:43 -04:00
uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY ;
2012-11-29 17:48:28 -05:00
RsTokReqOptions opts ;
2013-06-04 17:00:43 -04:00
opts . mReqType = GXS_REQUEST_TYPE_GROUP_META ;
2012-11-29 17:48:28 -05:00
uint32_t token = 0 ;
RsGenExchange : : getTokenService ( ) - > requestGroupInfo ( token , ansType , opts ) ;
2012-12-15 18:07:12 -05:00
GxsTokenQueue : : queueRequest ( token , CIRCLEREQ_CIRCLE_LIST ) ;
2012-11-29 17:48:28 -05:00
return 1 ;
}
2012-12-15 18:07:12 -05:00
bool p3GxsCircles : : load_CircleIdList ( uint32_t token )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::load_CircleIdList() : " < < token ;
2012-11-29 17:48:28 -05:00
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2014-08-25 17:07:07 -04:00
std : : list < RsGroupMetaData > groups ;
bool ok = RsGenExchange : : getGroupMeta ( token , groups ) ;
2012-11-29 17:48:28 -05:00
if ( ok )
{
// Save List
2014-08-25 17:07:07 -04:00
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
mCirclePersonalIdList . clear ( ) ;
mCircleExternalIdList . clear ( ) ;
}
2012-11-29 17:48:28 -05:00
2014-10-24 18:07:26 -04:00
for ( std : : list < RsGroupMetaData > : : iterator it = groups . begin ( ) ; it ! = groups . end ( ) ; + + it )
2012-11-29 17:48:28 -05:00
{
2014-08-25 17:07:07 -04:00
addCircleIdToList ( RsGxsCircleId ( it - > mGroupId ) , it - > mCircleType ) ;
2012-11-29 17:48:28 -05:00
}
}
else
{
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::load_CircleIdList() ERROR no data " ;
2012-11-29 17:48:28 -05:00
std : : cerr < < std : : endl ;
return false ;
}
return true ;
}
2012-12-15 18:07:12 -05:00
/****************************************************************************/
// ID STUFF. \/ \/ \/ \/ \/ \/ \/ :)
/****************************************************************************/
#if 0
2012-11-29 17:48:28 -05:00
/************************************************************************************/
/************************************************************************************/
bool p3GxsCircles : : cachetest_getlist ( )
{
std : : cerr < < " p3GxsCircles::cachetest_getlist() making request " ;
std : : cerr < < std : : endl ;
uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_GROUP_IDS ;
uint32_t token = 0 ;
RsGenExchange : : getTokenService ( ) - > requestGroupInfo ( token , ansType , opts ) ;
GxsTokenQueue : : queueRequest ( token , CIRCLEREQ_CACHETEST ) ;
// Schedule Next Event.
RsTickEvent : : schedule_in ( CIRCLE_EVENT_CACHETEST , CACHETEST_PERIOD ) ;
return true ;
}
bool p3GxsCircles : : cachetest_handlerequest ( uint32_t token )
{
std : : cerr < < " p3GxsCircles::cachetest_handlerequest() token: " < < token ;
std : : cerr < < std : : endl ;
std : : list < RsGxsId > grpIds ;
bool ok = RsGenExchange : : getGroupList ( token , grpIds ) ;
if ( ok )
{
std : : list < RsGxsId > : : iterator vit = grpIds . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = grpIds . end ( ) ; + + vit )
2012-11-29 17:48:28 -05:00
{
/* 5% chance of checking it! */
if ( RSRandom : : random_f32 ( ) < 0.25 )
{
std : : cerr < < " p3GxsCircles::cachetest_request() Testing Id: " < < * vit ;
std : : cerr < < std : : endl ;
/* try the cache! */
if ( ! haveKey ( * vit ) )
{
std : : list < PeerId > nullpeers ;
requestKey ( * vit , nullpeers ) ;
std : : cerr < < " p3GxsCircles::cachetest_request() Requested Key Id: " < < * vit ;
std : : cerr < < std : : endl ;
}
else
{
RsTlvSecurityKey seckey ;
if ( getKey ( * vit , seckey ) )
{
std : : cerr < < " p3GxsCircles::cachetest_request() Got Key OK Id: " < < * vit ;
std : : cerr < < std : : endl ;
// success!
seckey . print ( std : : cerr , 10 ) ;
std : : cerr < < std : : endl ;
}
else
{
std : : cerr < < " p3GxsCircles::cachetest_request() ERROR no Key for Id: " < < * vit ;
std : : cerr < < std : : endl ;
}
}
/* try private key too! */
if ( ! havePrivateKey ( * vit ) )
{
requestPrivateKey ( * vit ) ;
std : : cerr < < " p3GxsCircles::cachetest_request() Requested PrivateKey Id: " < < * vit ;
std : : cerr < < std : : endl ;
}
else
{
RsTlvSecurityKey seckey ;
if ( getPrivateKey ( * vit , seckey ) )
{
// success!
std : : cerr < < " p3GxsCircles::cachetest_request() Got PrivateKey OK Id: " < < * vit ;
std : : cerr < < std : : endl ;
}
else
{
std : : cerr < < " p3GxsCircles::cachetest_request() ERROR no PrivateKey for Id: " < < * vit ;
std : : cerr < < std : : endl ;
}
}
}
}
}
else
{
std : : cerr < < " p3GxsCircles::cache_load_for_token() ERROR no data " ;
std : : cerr < < std : : endl ;
return false ;
}
return true ;
}
/****************************************************************************/
// ID STUFF. /\ /\ /\ /\ /\ /\ /\ /\ :)
/****************************************************************************/
# endif
/************************************************************************************/
/************************************************************************************/
/************************************************************************************/
// Complicated deal of loading Circles.
2016-03-15 22:41:59 -04:00
bool p3GxsCircles : : force_cache_reload ( const RsGxsCircleId & id )
{
# ifdef DEBUG_CIRCLES
std : : cerr < < " p3GxsCircles::force_cache_reload(): Forcing cache reload of Circle ID " < < id < < std : : endl ;
# endif
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
# ifdef DEBUG_CIRCLES
std : : cerr < < " clearing from existing cache entries... " < < std : : endl ;
# endif
std : : map < RsGxsCircleId , RsGxsCircleCache > : : iterator it = mLoadingCache . find ( id ) ;
if ( it ! = mLoadingCache . end ( ) )
{
mLoadingCache . erase ( it ) ;
# ifdef DEBUG_CIRCLES
std : : cerr < < " removed item from currently loading cache entries... " < < std : : endl ;
# endif
}
mCircleCache . erase ( id ) ;
}
cache_request_load ( id ) ;
return true ;
}
2012-11-29 17:48:28 -05:00
bool p3GxsCircles : : cache_request_load ( const RsGxsCircleId & id )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
std : : cerr < < " p3GxsCircles::cache_request_load( " < < id < < " ) " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
/* check its not loaded */
if ( mCircleCache . is_cached ( id ) )
return true ;
/* check it is not already being loaded */
std : : map < RsGxsCircleId , RsGxsCircleCache > : : iterator it ;
it = mLoadingCache . find ( id ) ;
if ( it ! = mLoadingCache . end ( ) )
{
// Already loading.
return true ;
}
// Put it into the Loading Cache - so we will detect it later.
mLoadingCache [ id ] = RsGxsCircleCache ( ) ;
mCacheLoad_ToCache . push_back ( id ) ;
}
if ( RsTickEvent : : event_count ( CIRCLE_EVENT_CACHELOAD ) > 0 )
{
/* its already scheduled */
return true ;
}
int32_t age = 0 ;
if ( RsTickEvent : : prev_event_ago ( CIRCLE_EVENT_CACHELOAD , age ) )
{
if ( age < MIN_CIRCLE_LOAD_GAP )
{
2016-05-17 00:00:15 -04:00
RsTickEvent : : schedule_in ( CIRCLE_EVENT_CACHELOAD , MIN_CIRCLE_LOAD_GAP - age ) ;
2012-11-29 17:48:28 -05:00
return true ;
}
}
RsTickEvent : : schedule_now ( CIRCLE_EVENT_CACHELOAD ) ;
return true ;
}
bool p3GxsCircles : : cache_start_load ( )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::cache_start_load() " ;
std : : cerr < < std : : endl ;
2014-03-17 16:56:06 -04:00
# endif // DEBUG_CIRCLESmatch
2012-12-15 18:07:12 -05:00
2012-11-29 17:48:28 -05:00
/* trigger request to load missing ids into cache */
std : : list < RsGxsGroupId > groupIds ;
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
/* now we process the modGroupList -> a map so we can use it easily later, and create id list too */
2014-03-17 16:56:06 -04:00
std : : list < RsGxsCircleId > : : iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = mCacheLoad_ToCache . begin ( ) ; it ! = mCacheLoad_ToCache . end ( ) ; + + it )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
std : : cerr < < " p3GxsCircles::cache_start_load() GroupId: " < < * it ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2014-03-17 16:56:06 -04:00
groupIds . push_back ( RsGxsGroupId ( it - > toStdString ( ) ) ) ; // might need conversion?
2012-11-29 17:48:28 -05:00
}
mCacheLoad_ToCache . clear ( ) ;
}
if ( groupIds . size ( ) > 0 )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
std : : cerr < < " p3GxsCircles::cache_start_load() #Groups: " < < groupIds . size ( ) ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_GROUP_DATA ;
uint32_t token = 0 ;
RsGenExchange : : getTokenService ( ) - > requestGroupInfo ( token , ansType , opts , groupIds ) ;
GxsTokenQueue : : queueRequest ( token , CIRCLEREQ_CACHELOAD ) ;
}
return 1 ;
}
bool p3GxsCircles : : cache_load_for_token ( uint32_t token )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2016-05-18 21:13:54 -04:00
std : : cerr < < " p3GxsCircles::cache_load_for_token() : " < < token < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
std : : vector < RsGxsGrpItem * > grpData ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
if ( ! RsGenExchange : : getGroupData ( token , grpData ) )
{
std : : cerr < < " p3GxsCircles::cache_load_for_token() ERROR no data " ;
std : : cerr < < std : : endl ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
return false ;
}
std : : vector < RsGxsGrpItem * > : : iterator vit = grpData . begin ( ) ;
for ( ; vit ! = grpData . end ( ) ; + + vit )
{
RsGxsCircleGroupItem * item = dynamic_cast < RsGxsCircleGroupItem * > ( * vit ) ;
if ( ! item )
{
std : : cerr < < " Not a RsGxsCircleGroupItem Item, deleting! " < < std : : endl ;
delete ( * vit ) ;
continue ;
}
RsGxsCircleGroup group ;
item - > convertTo ( group ) ;
2012-11-29 17:48:28 -05:00
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2016-05-18 21:13:54 -04:00
std : : cerr < < " Loaded Id with Meta: " < < item - > meta < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
/* should already have a LoadingCache entry */
RsGxsCircleId id = RsGxsCircleId ( item - > meta . mGroupId ) ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
// (cyril) I'm not sure this logic is needed. The token system would avoid duplicates normally.
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
std : : map < RsGxsCircleId , RsGxsCircleCache > : : iterator it = mLoadingCache . find ( id ) ;
2013-06-04 17:00:43 -04:00
2016-05-18 21:13:54 -04:00
if ( it = = mLoadingCache . end ( ) )
{
std : : cerr < < " p3GxsCircles::cache_load_for_token() Load ERROR: " ;
std : : cerr < < item - > meta ;
std : : cerr < < std : : endl ;
delete ( item ) ;
// ERROR.
continue ;
}
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
RsGxsCircleCache & cache = it - > second ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
cache . loadBaseCircle ( group ) ;
delete item ;
if ( locked_processLoadingCacheEntry ( it - > second ) )
{
std : : cerr < < " All peers available. Moving to cache... " < < std : : endl ;
mLoadingCache . erase ( it ) ;
}
else
{
std : : cerr < < " Unprocessed peers. Requesting reload... " < < std : : endl ;
/* schedule event to try reload gxsIds */
RsTickEvent : : schedule_in ( CIRCLE_EVENT_RELOADIDS , GXSID_LOAD_CYCLE , id . toStdString ( ) ) ;
}
}
return true ;
}
// This method parses the cache entry and makes sure that all ids are known. If not, requests the missing ids
// when done, the entry is removed from mLoadingCache
bool p3GxsCircles : : locked_processLoadingCacheEntry ( RsGxsCircleCache & cache )
{
bool isUnprocessedPeers = false ;
if ( cache . mIsExternal )
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-05-21 15:51:49 -04:00
std : : cerr < < " Processing External Circle " < < cache . mCircleId < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2013-06-04 17:00:43 -04:00
2016-05-18 21:13:54 -04:00
// need to trigger the searches.
for ( std : : map < RsGxsId , RsGxsCircleMembershipStatus > : : iterator pit = cache . mMembershipStatus . begin ( ) ; pit ! = cache . mMembershipStatus . end ( ) ; + + pit )
{
2016-04-16 22:44:06 -04:00
# ifdef DEBUG_CIRCLES
2016-05-18 21:13:54 -04:00
std : : cerr < < " Member status: " < < pit - > first < < " : " < < pit - > second . subscription_flags ;
2016-04-16 22:44:06 -04:00
# endif
2016-05-18 21:13:54 -04:00
/* check cache */
if ( ! ( pit - > second . subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE ) )
if ( mIdentities - > haveKey ( pit - > first ) )
2012-11-29 17:48:28 -05:00
{
2016-05-18 21:13:54 -04:00
pit - > second . subscription_flags | = GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE ;
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-05-18 21:13:54 -04:00
std : : cerr < < " Key is now available! " < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2016-05-18 21:13:54 -04:00
}
else
2016-05-21 15:51:49 -04:00
{
std : : list < PeerId > peers ;
2012-11-29 17:48:28 -05:00
2016-05-21 15:51:49 -04:00
if ( ! cache . mOriginator . isNull ( ) )
2016-05-21 16:50:50 -04:00
{
2016-05-21 15:51:49 -04:00
peers . push_back ( cache . mOriginator ) ;
2016-05-21 16:50:50 -04:00
# ifdef DEBUG_CIRCLES
std : : cerr < < " Requesting unknown/unloaded identity: " < < pit - > first < < " to originator " < < cache . mOriginator < < std : : endl ;
# endif
}
2016-05-21 15:51:49 -04:00
else
{
2016-05-21 16:50:50 -04:00
std : : cerr < < " (WW) cache entry for circle " < < cache . mCircleId < < " has empty originator. Asking info for GXS id " < < pit - > first < < " to all connected friends. " < < std : : endl ;
rsPeers - > getOnlineList ( peers ) ;
2016-05-21 15:51:49 -04:00
}
2013-06-04 17:00:43 -04:00
2016-05-21 15:51:49 -04:00
mIdentities - > requestKey ( pit - > first , peers ) ;
isUnprocessedPeers = true ;
}
# ifdef DEBUG_CIRCLES
else
std : : cerr < < " Key is available. Nothing to process. " < < std : : endl ;
# endif
2016-05-18 21:13:54 -04:00
}
2012-11-29 17:48:28 -05:00
# ifdef HANDLE_SUBCIRCLES
#if 0
2016-05-18 21:13:54 -04:00
std : : list < RsGxsCircleId > & circles = group . mSubCircles ;
std : : list < RsGxsCircleId > : : const_iterator cit ;
for ( cit = circles . begin ( ) ; cit ! = circles . end ( ) ; + + cit )
{
/* if its cached already -> then its complete. */
if ( mCircleCache . is_loaded ( * cit ) )
{
RsGxsCircleCache cachedCircle ;
if ( mCircleCache . fetch ( & cit , cachedCircle ) )
2012-11-29 17:48:28 -05:00
{
2016-05-18 21:13:54 -04:00
/* copy cached circle into circle */
cache . loadSubCircle ( cachedCircle ) ;
2012-11-29 17:48:28 -05:00
}
2016-05-18 21:13:54 -04:00
else
2013-06-04 17:00:43 -04:00
{
2016-05-18 21:13:54 -04:00
/* error */
continue ;
2012-11-29 17:48:28 -05:00
}
}
2016-05-18 21:13:54 -04:00
else
2012-11-29 17:48:28 -05:00
{
2016-05-18 21:13:54 -04:00
/* push into secondary processing queues */
std : : list < RsGxsCircleId > & proc_circles = mCacheLoad_SubCircle [ * cit ] ;
proc_circles . push_back ( id ) ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
subCirclesToLoad . push_back ( * cit ) ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
isComplete = false ;
isUnprocessedCircles = true ;
2012-11-29 17:48:28 -05:00
}
}
2016-05-18 21:13:54 -04:00
# endif
# endif
2012-11-29 17:48:28 -05:00
}
2016-05-18 21:13:54 -04:00
# ifdef DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
else
2016-05-18 21:13:54 -04:00
std : : cerr < < " Loading Personal Circle " < < std : : endl ;
# endif
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
// We can check for self inclusion in the circle right away, since own ids are always loaded.
// that allows to subscribe/unsubscribe uncomplete circles
2016-05-22 20:35:51 -04:00
locked_checkCircleCacheForAutoSubscribe ( cache ) ;
locked_checkCircleCacheForMembershipUpdate ( cache ) ;
2012-11-29 17:48:28 -05:00
2016-05-22 18:21:00 -04:00
// always store in cache even if uncomplete. But do not remove the loading items so that they can be kept in loading state.
// if(isUnprocessedPeers)
// return false ;
2016-05-18 21:13:54 -04:00
/* move straight into the cache */
mCircleCache . store ( cache . mCircleId , cache ) ;
mCircleCache . resize ( ) ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
std : : cerr < < " Loading complete. " < < std : : endl ;
return true ;
2012-11-29 17:48:28 -05:00
}
2014-03-17 16:56:06 -04:00
bool p3GxsCircles : : cache_reloadids ( const RsGxsCircleId & circleId )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2016-05-18 21:13:54 -04:00
std : : cerr < < " p3GxsCircles::cache_reloadids() " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
2016-05-18 21:13:54 -04:00
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
/* fetch from loadMap */
std : : map < RsGxsCircleId , RsGxsCircleCache > : : iterator it ;
it = mLoadingCache . find ( circleId ) ;
if ( it = = mLoadingCache . end ( ) )
2016-04-17 00:51:45 -04:00
{
2016-05-18 21:13:54 -04:00
std : : cerr < < " p3GxsCircles::cache_reloadids() ERROR Id: " < < circleId ;
std : : cerr < < " Not in mLoadingCache Map " ;
std : : cerr < < std : : endl ;
2016-04-17 00:51:45 -04:00
2016-05-18 21:13:54 -04:00
// ERROR
return false ;
2016-04-17 00:51:45 -04:00
}
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
if ( locked_processLoadingCacheEntry ( it - > second ) )
{
/* remove from loading queue */
mLoadingCache . erase ( it ) ;
}
else
{
std : : cerr < < " Unprocessed peers. Requesting reload for circle " < < circleId < < std : : endl ;
2012-11-29 17:48:28 -05:00
2016-05-18 21:13:54 -04:00
/* schedule event to try reload gxsIds */
RsTickEvent : : schedule_in ( CIRCLE_EVENT_RELOADIDS , GXSID_LOAD_CYCLE , circleId . toStdString ( ) ) ;
}
2012-12-15 18:07:12 -05:00
2016-05-18 21:13:54 -04:00
return true ;
2012-11-29 17:48:28 -05:00
}
2016-05-17 00:00:15 -04:00
2016-05-22 20:35:51 -04:00
bool p3GxsCircles : : checkCircleCacheForMembershipUpdate ( )
2016-05-17 00:00:15 -04:00
{
2016-05-22 20:35:51 -04:00
# warning TODO. Should go over existing cache entries and update / process the membership requests
std : : cerr < < __PRETTY_FUNCTION__ < < " : not implemented! " < < std : : endl ;
return false ;
}
2012-11-29 17:48:28 -05:00
2016-05-22 20:35:51 -04:00
bool p3GxsCircles : : locked_checkCircleCacheForMembershipUpdate ( RsGxsCircleCache & cache )
{
time_t now = time ( NULL ) ;
2016-05-17 00:00:15 -04:00
2016-05-22 20:35:51 -04:00
if ( cache . mLastUpdatedMembershipTS + GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE < now )
{
std : : cerr < < " Cache entry for circle " < < cache . mCircleId < < " needs a swab over membership requests. Re-scheduling it. " < < std : : endl ;
2016-05-18 21:13:54 -04:00
2016-05-22 20:35:51 -04:00
// this should be called regularly
uint32_t token ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_MSG_DATA ;
std : : list < RsGxsGroupId > grpIds ;
grpIds . push_back ( RsGxsGroupId ( cache . mCircleId ) ) ;
RsGenExchange : : getTokenService ( ) - > requestMsgInfo ( token , RS_TOKREQ_ANSTYPE_SUMMARY , opts , grpIds ) ;
GxsTokenQueue : : queueRequest ( token , CIRCLEREQ_MESSAGE_DATA ) ;
}
return true ;
2016-05-17 00:00:15 -04:00
}
2012-11-29 17:48:28 -05:00
2013-06-04 17:00:43 -04:00
/* We need to AutoSubscribe if the Circle is relevent to us */
2016-04-14 23:09:59 -04:00
2016-05-22 20:35:51 -04:00
bool p3GxsCircles : : locked_checkCircleCacheForAutoSubscribe ( RsGxsCircleCache & cache )
2013-06-04 17:00:43 -04:00
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-05-22 20:35:51 -04:00
std : : cerr < < " p3GxsCircles::locked_checkCircleCacheForAutoSubscribe() : " < < cache . mCircleId < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2013-06-04 17:00:43 -04:00
/* if processed already - ignore */
if ( ! ( cache . mGroupStatus & GXS_SERV : : GXS_GRP_STATUS_UNPROCESSED ) )
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-03-14 23:19:37 -04:00
std : : cerr < < " Already Processed " < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2013-06-04 17:00:43 -04:00
return false ;
}
/* if personal - we created ... is subscribed already */
if ( ! cache . mIsExternal )
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-03-14 23:19:37 -04:00
std : : cerr < < " Personal Circle. Nothing to do. " < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2013-06-04 17:00:43 -04:00
return false ;
}
2016-05-28 20:25:15 -04:00
/* if we appear in the group - then autosubscribe, and mark as processed. This also applies if we're the group admin */
2016-03-11 22:36:47 -05:00
2016-05-18 21:13:54 -04:00
std : : list < RsGxsId > myOwnIds ;
if ( ! rsIdentity - > getOwnIds ( myOwnIds ) )
{
std : : cerr < < " own ids not loaded yet. " < < std : : endl ;
/* schedule event to try reload gxsIds */
RsTickEvent : : schedule_in ( CIRCLE_EVENT_RELOADIDS , GXSID_LOAD_CYCLE , cache . mCircleId . toStdString ( ) ) ;
return false ;
}
bool in_admin_list = false ;
2016-05-28 20:17:19 -04:00
bool member_request = false ;
2016-05-18 21:13:54 -04:00
2016-05-28 20:17:19 -04:00
for ( std : : list < RsGxsId > : : const_iterator it ( myOwnIds . begin ( ) ) ; it ! = myOwnIds . end ( ) & & ( ! in_admin_list ) & & ( ! member_request ) ; + + it )
2016-05-18 21:13:54 -04:00
{
std : : map < RsGxsId , RsGxsCircleMembershipStatus > : : const_iterator it2 = cache . mMembershipStatus . find ( * it ) ;
if ( it2 ! = cache . mMembershipStatus . end ( ) )
2016-05-28 20:17:19 -04:00
{
in_admin_list = in_admin_list | | bool ( it2 - > second . subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ) ;
member_request = member_request | | bool ( it2 - > second . subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED ) ;
}
2016-05-18 21:13:54 -04:00
}
2016-05-28 20:25:15 -04:00
bool am_I_admin ( cache . mGroupSubscribeFlags & GXS_SERV : : GROUP_SUBSCRIBE_ADMIN ) ;
2016-05-18 21:13:54 -04:00
# ifdef DEBUG_CIRCLES
2016-05-28 20:25:15 -04:00
std : : cerr < < " own ID in circle: " < < in_admin_list < < " , own subscribe request: " < < member_request < < " , am I admin?: " < < am_I_admin < < std : : endl ;
2016-05-18 21:13:54 -04:00
# endif
2016-05-28 20:25:15 -04:00
if ( in_admin_list | | member_request | | am_I_admin )
2013-06-04 17:00:43 -04:00
{
2016-03-15 22:11:36 -04:00
uint32_t token , token2 ;
if ( ! ( cache . mGroupSubscribeFlags & GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED ) )
{
2014-04-30 07:50:45 -04:00
# ifdef DEBUG_CIRCLES
2016-03-15 22:11:36 -04:00
/* we are part of this group - subscribe, clear unprocessed flag */
std : : cerr < < " I'm allowed in this circle => AutoSubscribing! " < < std : : endl ;
2014-04-30 07:50:45 -04:00
# endif
2016-03-15 22:11:36 -04:00
RsGenExchange : : subscribeToGroup ( token , RsGxsGroupId ( cache . mCircleId ) , true ) ;
}
# ifdef DEBUG_CIRCLES
else
std : : cerr < < " I'm allowed in this circle, and already subscribed. " < < std : : endl ;
# endif
2016-03-13 11:29:21 -04:00
RsGenExchange : : setGroupStatusFlags ( token2 , RsGxsGroupId ( cache . mCircleId ) , 0 , GXS_SERV : : GXS_GRP_STATUS_UNPROCESSED ) ;
2016-04-16 22:44:06 -04:00
cache . mGroupStatus & = ~ GXS_SERV : : GXS_GRP_STATUS_UNPROCESSED ;
2016-03-14 23:19:37 -04:00
2013-06-04 17:00:43 -04:00
return true ;
}
2016-05-18 21:13:54 -04:00
else
2013-06-04 17:00:43 -04:00
{
/* we know all the peers - we are not part - we can flag as PROCESSED. */
2016-03-14 23:19:37 -04:00
uint32_t token , token2 ;
2014-03-17 16:56:06 -04:00
RsGenExchange : : setGroupStatusFlags ( token , RsGxsGroupId ( cache . mCircleId . toStdString ( ) ) , 0 , GXS_SERV : : GXS_GRP_STATUS_UNPROCESSED ) ;
2016-03-15 22:11:36 -04:00
if ( cache . mGroupSubscribeFlags & GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED )
{
RsGenExchange : : subscribeToGroup ( token2 , RsGxsGroupId ( cache . mCircleId ) , false ) ;
# ifdef DEBUG_CIRCLES
std : : cerr < < " Not part of the group! Let's unsubscribe this circle of unfriendly Napoleons! " < < std : : endl ;
# endif
}
# ifdef DEBUG_CIRCLES
else
std : : cerr < < " Not part of the group, and not subscribed either. " < < std : : endl ;
# endif
2016-03-14 23:19:37 -04:00
2016-04-16 22:44:06 -04:00
cache . mGroupStatus & = ~ GXS_SERV : : GXS_GRP_STATUS_UNPROCESSED ;
2016-03-14 23:19:37 -04:00
return true ;
2013-06-04 17:00:43 -04:00
}
}
2014-08-25 17:07:07 -04:00
void p3GxsCircles : : addCircleIdToList ( const RsGxsCircleId & circleId , uint32_t circleType )
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
if ( circleType = = GXS_CIRCLE_TYPE_LOCAL )
{
if ( mCirclePersonalIdList . end ( ) = = std : : find ( mCirclePersonalIdList . begin ( ) , mCirclePersonalIdList . end ( ) , circleId ) ) {
mCirclePersonalIdList . push_back ( circleId ) ;
}
}
else
{
if ( mCircleExternalIdList . end ( ) = = std : : find ( mCircleExternalIdList . begin ( ) , mCircleExternalIdList . end ( ) , circleId ) ) {
mCircleExternalIdList . push_back ( circleId ) ;
}
}
}
2013-06-04 17:00:43 -04:00
2012-11-29 17:48:28 -05:00
# ifdef HANDLE_SUBCIRCLES
#if 0
/**** TODO BELOW ****/
bool p3GxsCircles : : cache_load_subcircles ( uint32_t token )
{
std : : cerr < < " p3GxsCircles::cache_load_subcircles() : " < < token ;
std : : cerr < < std : : endl ;
std : : vector < RsGxsGrpItem * > grpData ;
bool ok = RsGenExchange : : getGroupData ( token , grpData ) ;
if ( ok )
{
std : : vector < RsGxsGrpItem * > : : iterator vit = grpData . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = grpData . end ( ) ; + + vit )
2012-11-29 17:48:28 -05:00
{
RsGxsIdGroupItem * item = dynamic_cast < RsGxsIdGroupItem * > ( * vit ) ;
RsGxsCircleId id = item - > meta . mGroupId ;
RsGxsCircleGroup group = item - > group ;
group . mMeta = item - > meta ;
delete item ;
std : : cerr < < " p3GxsCircles::cache_load_subcircles() Loaded Id with Meta: " ;
std : : cerr < < item - > meta ;
std : : cerr < < std : : endl ;
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
/* stage 2 of loading, load subcircles */
std : : map < RsGxsCircleId , std : : list < RsGxsCircleId > > : : iterator sit ;
sit = mCacheLoad_SubCircle . find ( id )
if ( sit = = mCacheLoad_SubCircle . end ( ) )
{
/* ERROR */
continue ;
}
std : : list < RsGxsCircleId > updateCaches = sit - > second ;
// cleanup while we're here.
mCacheLoad_SubCircle . erase ( sit ) ;
/* Now iterate through peers / subcircles, and apply
* - similarly to base load function
*/
RsGxsCircleCache & cache = it - > second ;
cache . loadBaseCircle ( group ) ;
bool isComplete = true ;
std : : list < RsGxsId > & peers = group . peers ;
std : : list < RsGxsId > : : const_iterator pit ;
// need to trigger the searches.
2014-10-24 18:07:26 -04:00
for ( pit = peers . begin ( ) ; pit ! = peers . end ( ) ; + + pit )
2012-11-29 17:48:28 -05:00
{
/* check cache */
if ( mIdentities - > is_cached ( * pit ) )
{
/* we can process now! */
RsIdentityDetails details ;
if ( mIdentities - > getDetails ( * pit , details ) )
{
if ( details . isPgpKnown )
{
// Problem - could have multiple GxsIds here!
// TODO.
//cache.mAllowedPeers[details.mPgpId] = *pit;
2014-10-24 18:07:26 -04:00
for ( uit = updateCaches . begin ( ) ; uit ! = updateCaches . end ( ) ; + + uit )
2012-11-29 17:48:28 -05:00
{
/* fetch the cache - and update */
mLoadingCache [ id ] = RsGxsCircleCache ( ) ;
std : : map < RsGxsCircleId , RsGxsCircleCache > : : iterator it ;
it = mLoadingCache . find ( id ) ;
}
}
else
{
//cache.mUnknownPeers.push_back(*pit);
}
}
else
{
// ERROR.
}
}
else
{
/* store in to_process queue. */
cache . mUnprocessedPeers . push_back ( * pit ) ;
if ( isComplete )
{
/* store reference to update */
isComplete = false ;
mCacheLoad_KeyWait . push_back ( id ) ;
}
}
}
std : : list < RsGxsCircleId > & circles = group . circles ;
std : : list < RsGxsCircleId > : : const_iterator cit ;
2014-10-24 18:07:26 -04:00
for ( cit = circles . begin ( ) ; cit ! = circles . end ( ) ; + + cit )
2012-11-29 17:48:28 -05:00
{
/* if its cached already -> then its complete. */
if ( mCircleCache . is_loaded ( * cit ) )
{
RsGxsCircleCache cachedCircle ;
if ( mCircleCache . fetch ( & cit , cachedCircle ) )
{
/* copy cached circle into circle */
cache . loadSubCircle ( cachedCircle ) ;
}
else
{
/* error */
continue ;
}
}
else
{
/* push into secondary processing queues */
std : : list < RsGxsCircleId > & proc_circles = mCacheLoad_SubCircle [ id ] ;
proc_circles . push_back ( id ) ;
subCirclesToLoad . push_back ( id ) ;
isComplete = false ;
}
}
if ( isComplete )
{
/* move straight into the cache */
mCircleCache . store ( id , cache ) ;
/* remove from loading queue */
mLoadingCache . erase ( it ) ;
}
}
}
else
{
std : : cerr < < " p3GxsCircles::cache_load_for_token() ERROR no data " ;
std : : cerr < < std : : endl ;
return false ;
}
if ( ! keysToLoad . empty ( ) )
{
/* schedule event to try reload gxsIds */
}
if ( ! subCirclesToLoad . empty ( ) )
{
/* request load of subcircles */
}
return true ;
}
# endif
# endif
/************************************************************************************/
/************************************************************************************/
/************************************************************************************/
std : : string p3GxsCircles : : genRandomId ( )
{
std : : string randomId ;
for ( int i = 0 ; i < 20 ; i + + )
{
randomId + = ( char ) ( ' a ' + ( RSRandom : : random_u32 ( ) % 26 ) ) ;
}
return randomId ;
}
void p3GxsCircles : : generateDummyData ( )
{
2012-12-15 18:07:12 -05:00
// request Id Data...
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::generateDummyData() getting Id List " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_GROUP_DATA ;
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
uint32_t token ;
rsIdentity - > getTokenService ( ) - > requestGroupInfo ( token , ansType , opts ) ;
2012-11-29 17:48:28 -05:00
{
2012-12-15 18:07:12 -05:00
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
mDummyIdToken = token ;
}
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
RsTickEvent : : schedule_in ( CIRCLE_EVENT_DUMMYLOAD , CIRCLE_DUMMY_GENPERIOD ) ;
}
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
void p3GxsCircles : : checkDummyIdData ( )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::checkDummyIdData() " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
// check the token.
uint32_t status = rsIdentity - > getTokenService ( ) - > requestStatus ( mDummyIdToken ) ;
if ( ( RsTokenService : : GXS_REQUEST_V2_STATUS_FAILED = = status ) | |
( RsTokenService : : GXS_REQUEST_V2_STATUS_COMPLETE = = status ) )
{
std : : vector < RsGxsIdGroup > ids ;
if ( ! rsIdentity - > getGroupData ( mDummyIdToken , ids ) )
{
std : : cerr < < " p3GxsCircles::checkDummyIdData() ERROR getting data " ;
std : : cerr < < std : : endl ;
/* error */
return ;
}
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
std : : vector < RsGxsIdGroup > : : iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = ids . begin ( ) ; it ! = ids . end ( ) ; + + it )
2012-12-15 18:07:12 -05:00
{
if ( it - > mMeta . mGroupFlags & RSGXSID_GROUPFLAG_REALID )
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::checkDummyIdData() PgpLinkedId: " < < it - > mMeta . mGroupId ;
2012-11-29 17:48:28 -05:00
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2014-03-17 16:56:06 -04:00
mDummyPgpLinkedIds . push_back ( RsGxsId ( it - > mMeta . mGroupId . toStdString ( ) ) ) ;
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
if ( it - > mMeta . mSubscribeFlags & GXS_SERV : : GROUP_SUBSCRIBE_ADMIN )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::checkDummyIdData() OwnId: " < < it - > mMeta . mGroupId ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2014-03-17 16:56:06 -04:00
mDummyOwnIds . push_back ( RsGxsId ( it - > mMeta . mGroupId . toStdString ( ) ) ) ;
2012-12-15 18:07:12 -05:00
}
2012-11-29 17:48:28 -05:00
}
2012-12-15 18:07:12 -05:00
else
2012-11-29 17:48:28 -05:00
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::checkDummyIdData() Other Id: " < < it - > mMeta . mGroupId ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
}
}
2012-12-15 18:07:12 -05:00
/* schedule the generate events */
# define MAX_CIRCLES 10
for ( int i = 0 ; i < MAX_CIRCLES ; i + + )
{
RsTickEvent : : schedule_in ( CIRCLE_EVENT_DUMMYGEN , i * CIRCLE_DUMMY_GENPERIOD ) ;
}
return ;
2012-11-29 17:48:28 -05:00
}
2012-12-15 18:07:12 -05:00
// Otherwise - reschedule to come back here.
RsTickEvent : : schedule_in ( CIRCLE_EVENT_DUMMYLOAD , CIRCLE_DUMMY_GENPERIOD ) ;
return ;
}
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
void p3GxsCircles : : generateDummyCircle ( )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::generateDummyCircle() " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
int npgps = mDummyPgpLinkedIds . size ( ) ;
2013-03-16 09:37:39 -04:00
if ( npgps = = 0 )
return ;
2012-12-15 18:07:12 -05:00
RsGxsCircleGroup group ;
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
std : : set < RsGxsId > idset ;
// select a random number of them.
# define MAX_PEERS_PER_CIRCLE_GROUP 20
int nIds = 1 + ( RSRandom : : random_u32 ( ) % MAX_PEERS_PER_CIRCLE_GROUP ) ;
for ( int i = 0 ; i < nIds ; i + + )
{
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
int selection = ( RSRandom : : random_u32 ( ) % npgps ) ;
std : : list < RsGxsId > : : iterator it = mDummyPgpLinkedIds . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( int j = 0 ; ( it ! = mDummyPgpLinkedIds . end ( ) ) & & ( j < selection ) ; j + + , + + it ) ;
2012-12-15 18:07:12 -05:00
if ( it ! = mDummyPgpLinkedIds . end ( ) )
{
idset . insert ( * it ) ;
}
2012-11-29 17:48:28 -05:00
}
2012-12-15 18:07:12 -05:00
/* be sure to add one of our IDs too (otherwise we wouldn't get the group)
*/
2012-11-29 17:48:28 -05:00
{
2012-12-15 18:07:12 -05:00
int selection = ( RSRandom : : random_u32 ( ) % mDummyOwnIds . size ( ) ) ;
std : : list < RsGxsId > : : iterator it = mDummyOwnIds . begin ( ) ;
mDummyOwnIds . push_back ( * it ) ;
2014-10-24 18:07:26 -04:00
for ( int j = 0 ; ( it ! = mDummyOwnIds . end ( ) ) & & ( j < selection ) ; j + + , + + it ) ;
2012-12-15 18:07:12 -05:00
if ( it ! = mDummyOwnIds . end ( ) )
{
idset . insert ( * it ) ;
}
}
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
group . mMeta . mGroupName = genRandomId ( ) ;
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::generateDummyCircle() Name: " < < group . mMeta . mGroupName ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
2012-12-15 18:07:12 -05:00
std : : set < RsGxsId > : : iterator it ;
2014-10-24 18:07:26 -04:00
for ( it = idset . begin ( ) ; it ! = idset . end ( ) ; + + it )
2012-12-15 18:07:12 -05:00
{
2015-04-17 17:36:22 -04:00
group . mInvitedMembers . insert ( * it ) ;
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-12-15 18:07:12 -05:00
std : : cerr < < " p3GxsCircles::generateDummyCircle() Adding: " < < * it ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
}
2012-12-15 18:07:12 -05:00
uint32_t dummyToken ;
createGroup ( dummyToken , group ) ;
2012-11-29 17:48:28 -05:00
}
/************************************************************************************/
/************************************************************************************/
/************************************************************************************/
/************************************************************************************/
2012-11-30 19:16:24 -05:00
std : : ostream & operator < < ( std : : ostream & out , const RsGxsCircleGroup & grp )
2012-11-29 17:48:28 -05:00
{
2012-11-30 19:16:24 -05:00
out < < " RsGxsCircleGroup: Meta: " < < grp . mMeta ;
out < < " InvitedMembers: " ;
2012-11-29 17:48:28 -05:00
out < < std : : endl ;
2012-11-30 19:16:24 -05:00
2015-04-17 17:36:22 -04:00
std : : set < RsGxsId > : : const_iterator it ;
std : : set < RsGxsCircleId > : : const_iterator sit ;
2012-11-30 19:16:24 -05:00
for ( it = grp . mInvitedMembers . begin ( ) ;
2014-10-24 18:07:26 -04:00
it ! = grp . mInvitedMembers . begin ( ) ; + + it )
2012-11-30 19:16:24 -05:00
{
out < < " \t " < < * it ;
out < < std : : endl ;
}
for ( sit = grp . mSubCircles . begin ( ) ;
2014-10-24 18:07:26 -04:00
sit ! = grp . mSubCircles . begin ( ) ; + + sit )
2012-11-30 19:16:24 -05:00
{
out < < " \t " < < * it ;
out < < std : : endl ;
}
2012-11-29 17:48:28 -05:00
return out ;
}
2012-11-30 19:16:24 -05:00
std : : ostream & operator < < ( std : : ostream & out , const RsGxsCircleMsg & msg )
2012-11-29 17:48:28 -05:00
{
2012-11-30 19:16:24 -05:00
out < < " RsGxsCircleMsg: Meta: " < < msg . mMeta ;
2012-11-29 17:48:28 -05:00
out < < std : : endl ;
return out ;
}
// Overloaded from GxsTokenQueue for Request callbacks.
void p3GxsCircles : : handleResponse ( uint32_t token , uint32_t req_type )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
std : : cerr < < " p3GxsCircles::handleResponse( " < < token < < " , " < < req_type < < " ) " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
// stuff.
switch ( req_type )
{
2012-12-15 18:07:12 -05:00
case CIRCLEREQ_CIRCLE_LIST :
load_CircleIdList ( token ) ;
2012-11-29 17:48:28 -05:00
break ;
2012-12-15 18:07:12 -05:00
2016-05-17 00:00:15 -04:00
case CIRCLEREQ_MESSAGE_DATA :
processMembershipRequests ( token ) ;
break ;
2012-11-29 17:48:28 -05:00
case CIRCLEREQ_CACHELOAD :
cache_load_for_token ( token ) ;
break ;
#if 0
case CIRCLEREQ_CACHETEST :
cachetest_handlerequest ( token ) ;
break ;
# endif
default :
/* error */
std : : cerr < < " p3GxsCircles::handleResponse() Unknown Request Type: " < < req_type ;
std : : cerr < < std : : endl ;
break ;
}
}
// Overloaded from RsTickEvent for Event callbacks.
void p3GxsCircles : : handle_event ( uint32_t event_type , const std : : string & elabel )
{
2013-02-27 16:16:03 -05:00
# ifdef DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
std : : cerr < < " p3GxsCircles::handle_event( " < < event_type < < " ) " ;
std : : cerr < < std : : endl ;
2013-02-27 16:16:03 -05:00
# endif // DEBUG_CIRCLES
2012-11-29 17:48:28 -05:00
// stuff.
switch ( event_type )
{
2012-12-15 18:07:12 -05:00
case CIRCLE_EVENT_LOADIDS :
request_CircleIdList ( ) ;
2012-11-29 17:48:28 -05:00
break ;
case CIRCLE_EVENT_CACHELOAD :
cache_start_load ( ) ;
break ;
case CIRCLE_EVENT_RELOADIDS :
2014-03-17 16:56:06 -04:00
cache_reloadids ( RsGxsCircleId ( elabel ) ) ;
2012-11-29 17:48:28 -05:00
break ;
#if 0
case CIRCLE_EVENT_CACHETEST :
cachetest_getlist ( ) ;
break ;
# endif
2012-12-15 18:07:12 -05:00
case CIRCLE_EVENT_DUMMYSTART :
generateDummyData ( ) ;
break ;
case CIRCLE_EVENT_DUMMYLOAD :
checkDummyIdData ( ) ;
break ;
case CIRCLE_EVENT_DUMMYGEN :
generateDummyCircle ( ) ;
break ;
2012-11-29 17:48:28 -05:00
default :
/* error */
std : : cerr < < " p3GxsCircles::handle_event() Unknown Event Type: " < < event_type ;
std : : cerr < < std : : endl ;
break ;
}
}
2016-05-10 21:24:31 -04:00
// Circle membership is requested/denied by posting a message into the cicle group, according to the following rules:
//
// - a subscription request is a RsItem (which serialises into a radix64 message, that is further signed by the group message publishing system)
// The item contains:
// * subscribe order (yes/no), boolean
// * circle ID (this is important, otherwise people can copy subscribe messages from one circle to another)
// * subscribe date
// * subscribe timeout (how long is the message kept. When timed out, the message is removed and subscription cancelled)
//
// - subscribe messages follow the following rules, which are enforced by a timer-based method:
// * subscription requests from a given user are always replaced by the last subscription request
// * a complete list of who's subscribed to a given group is kept, saved, and regularly updated when new subscribe messages are received, or when admin list is changed.
// * getGroupDetails reads this list in order to respond who's subscribed to a group. The list of
//
// - compatibility with self-restricted circles:
// * subscription should be based on admin list, so that non subscribed peers still receive the invitation
//
2016-05-17 00:00:15 -04:00
// - 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.
//
2016-05-10 21:24:31 -04:00
// - Use cases
// * user sees group (not self restricted) and requests to subscribe => RS subscribes the group and the user can propagate the response
2016-05-17 00:00:15 -04:00
// * 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.
// *
2016-05-10 21:24:31 -04:00
//
// - Threat model
// * a malicious user forges a new subscription request: NP-hard as it needs to break the RSA key of the GXS id.
// * a malicious corrupts a subscription request: NP-hard. Messages are signed.
// * a malicious user copies an old subscription of someone else and inserts it in the system.
// => 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.
2016-05-17 00:00:15 -04:00
// * 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 |
// +-------------+------------------------------+-----------------------------+
2016-05-10 21:24:31 -04:00
bool p3GxsCircles : : pushCircleMembershipRequest ( const RsGxsId & own_gxsid , const RsGxsCircleId & circle_id , uint32_t request_type )
2016-05-06 22:12:44 -04:00
{
2016-05-12 22:30:12 -04:00
std : : cerr < < " Circle membership request: own_gxsid = " < < own_gxsid < < " , circle= " < < circle_id < < " , req type= " < < request_type < < std : : endl ;
2016-05-10 21:24:31 -04:00
// check for some consistency
if ( request_type ! = RsGxsCircleSubscriptionRequestItem : : SUBSCRIPTION_REQUEST_SUBSCRIBE & & request_type ! = RsGxsCircleSubscriptionRequestItem : : SUBSCRIPTION_REQUEST_UNSUBSCRIBE )
return false ;
std : : list < RsGxsId > own_ids ;
if ( ! rsIdentity - > getOwnIds ( own_ids ) )
return false ;
bool found = false ;
for ( std : : list < RsGxsId > : : const_iterator it ( own_ids . begin ( ) ) ; it ! = own_ids . end ( ) & & ! found ; + + it )
found = ( ( * it ) = = own_gxsid ) ;
if ( ! found )
return false ;
// Create a subscribe item
2016-05-11 17:59:42 -04:00
RsGxsCircleSubscriptionRequestItem * s = new RsGxsCircleSubscriptionRequestItem ;
2016-05-10 21:24:31 -04:00
2016-05-11 17:59:42 -04:00
s - > time_stamp = time ( NULL ) ;
s - > time_out = 0 ; // means never
2016-05-23 21:09:06 -04:00
s - > subscription_type = request_type ;
2016-05-10 21:24:31 -04:00
2016-05-11 17:59:42 -04:00
RsTemporaryMemory tmpmem ( circle_id . serial_size ( ) + own_gxsid . serial_size ( ) ) ;
2016-05-10 21:24:31 -04:00
2016-05-11 17:59:42 -04:00
uint32_t off = 0 ;
circle_id . serialise ( tmpmem , tmpmem . size ( ) , off ) ;
2016-05-14 11:56:14 -04:00
own_gxsid . serialise ( tmpmem , tmpmem . size ( ) , off ) ;
2016-05-10 21:24:31 -04:00
2016-05-11 17:59:42 -04:00
s - > meta . mGroupId = RsGxsGroupId ( circle_id ) ;
s - > meta . mMsgId . clear ( ) ;
s - > meta . mThreadId = RsDirUtil : : sha1sum ( tmpmem , tmpmem . size ( ) ) ; // make the ID from the hash of the cirle ID and the author ID
s - > meta . mAuthorId = own_gxsid ;
2016-05-10 21:24:31 -04:00
// msgItem->meta.mParentId = ; // leave these blank
// msgItem->meta.mOrigMsgId= ;
std : : cerr < < " p3GxsCircles::publishSubscribeRequest() " < < std : : endl ;
std : : cerr < < " GroupId : " < < circle_id < < std : : endl ;
2016-05-11 17:59:42 -04:00
std : : cerr < < " AuthorId : " < < s - > meta . mAuthorId < < std : : endl ;
std : : cerr < < " ThreadId : " < < s - > meta . mThreadId < < std : : endl ;
2016-05-10 21:24:31 -04:00
2016-05-22 18:50:18 -04:00
uint32_t token ;
RsGenExchange : : publishMsg ( token , s ) ;
2016-05-23 21:09:06 -04:00
// update the cache.
force_cache_reload ( circle_id ) ;
2016-05-10 21:24:31 -04:00
return true ;
2016-05-06 22:12:44 -04:00
}
2016-05-10 21:24:31 -04:00
bool p3GxsCircles : : requestCircleMembership ( const RsGxsId & own_gxsid , const RsGxsCircleId & circle_id )
{
2016-05-11 17:59:42 -04:00
return pushCircleMembershipRequest ( own_gxsid , circle_id , RsGxsCircleSubscriptionRequestItem : : SUBSCRIPTION_REQUEST_SUBSCRIBE ) ;
2016-05-10 21:24:31 -04:00
}
2016-05-11 17:59:42 -04:00
bool p3GxsCircles : : cancelCircleMembership ( const RsGxsId & own_gxsid , const RsGxsCircleId & circle_id )
2016-05-06 22:12:44 -04:00
{
2016-05-11 17:59:42 -04:00
return pushCircleMembershipRequest ( own_gxsid , circle_id , RsGxsCircleSubscriptionRequestItem : : SUBSCRIPTION_REQUEST_UNSUBSCRIBE ) ;
2016-05-06 22:12:44 -04:00
}
2016-05-17 00:00:15 -04:00
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.
2016-05-18 21:47:34 -04:00
# ifdef DEBUG_CIRCLES
std : : cerr < < " Processing circle membership requests. " < < std : : endl ;
# endif
2016-05-17 00:00:15 -04:00
GxsMsgDataMap msgItems ;
if ( ! RsGenExchange : : getMsgData ( token , msgItems ) )
{
std : : cerr < < " (EE) Cannot get msg data for circle. Something's weird. " < < std : : endl ;
2016-05-18 21:13:54 -04:00
return false ;
2016-05-17 00:00:15 -04:00
}
GxsMsgReq messages_to_delete ;
for ( GxsMsgDataMap : : const_iterator it ( msgItems . begin ( ) ) ; it ! = msgItems . end ( ) ; + + it )
{
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
2016-05-18 21:47:34 -04:00
std : : cerr < < " Circle ID: " < < it - > first < < std : : endl ;
2016-05-17 00:00:15 -04:00
2016-05-18 21:13:54 -04:00
RsGxsCircleId cid ( it - > first ) ;
2016-05-17 00:00:15 -04:00
if ( ! mCircleCache . is_cached ( cid ) )
{
2016-05-18 21:47:34 -04:00
std : : cerr < < " (EE) Circle is not in cache! " < < std : : endl ;
2016-05-17 00:00:15 -04:00
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 ) ;
2016-05-18 21:47:34 -04:00
std : : cerr < < " Circle found in cache! " < < std : : endl ;
std : : cerr < < " Retrieving messages... " < < std : : endl ;
2016-05-17 00:00:15 -04:00
for ( uint32_t i = 0 ; i < it - > second . size ( ) ; + + i )
{
2016-05-18 21:47:34 -04:00
std : : cerr < < " Group ID: " < < it - > second [ i ] - > meta . mGroupId < < " , Message ID: " < < it - > second [ i ] - > meta . mMsgId < < " : " ;
2016-05-17 00:00:15 -04:00
RsGxsCircleSubscriptionRequestItem * item = dynamic_cast < RsGxsCircleSubscriptionRequestItem * > ( it - > second [ i ] ) ;
if ( item = = NULL )
2016-05-18 21:47:34 -04:00
{
std : : cerr < < " (EE) item is not a RsGxsCircleSubscriptionRequestItem. Weird. " < < std : : endl ;
2016-05-17 00:00:15 -04:00
continue ;
}
2016-05-18 21:13:54 -04:00
RsGxsCircleMembershipStatus & info ( data . mMembershipStatus [ item - > meta . mAuthorId ] ) ;
2016-05-17 00:00:15 -04:00
2016-05-18 21:47:34 -04:00
std : : cerr < < " is from id " < < item - > meta . mAuthorId < < " " < < time ( NULL ) - item - > time_stamp < < " seconds ago, " ;
2016-05-18 21:13:54 -04:00
if ( info . last_subscription_TS < item - > time_stamp )
2016-05-17 00:00:15 -04:00
{
2016-05-18 21:13:54 -04:00
info . last_subscription_TS = item - > time_stamp ;
2016-05-17 00:00:15 -04:00
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
2016-05-18 21:47:34 -04:00
std : : cerr < < " (EE) unknown subscription order type: " < < item - > subscription_type ;
std : : cerr < < " UPDATING " < < std : : endl ;
2016-05-17 00:00:15 -04:00
}
2016-05-18 21:13:54 -04:00
else if ( info . last_subscription_TS > item - > time_stamp )
2016-05-17 00:00:15 -04:00
{
2016-05-18 21:47:34 -04:00
std : : cerr < < " Older than last known ( " < < time ( NULL ) - info . last_subscription_TS < < " seconds ago): deleting. " < < std : : endl ;
2016-05-17 00:00:15 -04:00
messages_to_delete [ RsGxsGroupId ( cid ) ] . push_back ( it - > second [ i ] - > meta . mMsgId ) ;
}
}
data . mLastUpdatedMembershipTS = time ( NULL ) ;
}
2016-05-06 22:12:44 -04:00
2016-05-17 00:00:15 -04:00
RsStackMutex stack ( mCircleMtx ) ; /********** STACK LOCKED MTX ******/
2016-05-18 21:13:54 -04:00
uint32_t token2 ;
RsGenExchange : : deleteMsgs ( token2 , messages_to_delete ) ;
return true ;
2016-05-17 00:00:15 -04:00
}
2016-05-10 21:24:31 -04:00