2014-05-17 09:50:40 -04:00
/*
* libretroshare / src / gxs : rsgenexchange . cc
*
* RetroShare Gxs exchange interface .
*
* Copyright 2012 - 2012 by Christopher Evi - Parker , 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 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 <unistd.h>
# include "pqi/pqihash.h"
# include "rsgenexchange.h"
# include "gxssecurity.h"
# include "util/contentvalue.h"
# include "retroshare/rsgxsflags.h"
# include "retroshare/rsgxscircles.h"
2014-10-22 17:00:20 -04:00
# include "retroshare/rsgrouter.h"
2015-10-25 17:16:16 -04:00
# include "retroshare/rspeers.h"
2014-05-17 09:50:40 -04:00
# include "rsgixs.h"
# include "rsgxsutil.h"
2015-03-20 06:39:17 -04:00
# include "rsserver/p3face.h"
2014-05-17 09:50:40 -04:00
2015-02-06 20:04:51 -05:00
# include <algorithm>
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# define PUB_GRP_MASK 0x000f
# define RESTR_GRP_MASK 0x00f0
# define PRIV_GRP_MASK 0x0f00
2014-05-17 09:50:40 -04:00
# define GRP_OPTIONS_MASK 0xf000
2014-09-20 15:58:07 -04:00
# define PUB_GRP_OFFSET 0
# define RESTR_GRP_OFFSET 8
# define PRIV_GRP_OFFSET 16
# define GRP_OPTIONS_OFFSET 24
2014-05-17 09:50:40 -04:00
2015-10-24 00:22:55 -04:00
// Authentication key indices. Used to store them in a map
// these where originally flags, but used as indexes. Still, we need
// to keep their old values to ensure backward compatibility.
2015-10-23 22:53:00 -04:00
static const uint32_t INDEX_AUTHEN_IDENTITY = 0x00000010 ; // identity
static const uint32_t INDEX_AUTHEN_PUBLISH = 0x00000020 ; // publish key
static const uint32_t INDEX_AUTHEN_ADMIN = 0x00000040 ; // admin key
2014-05-17 09:50:40 -04:00
# define GXS_MASK "GXS_MASK_HACK"
2015-10-24 12:55:49 -04:00
//#define GEN_EXCH_DEBUG 1
2014-05-17 09:50:40 -04:00
# define MSG_CLEANUP_PERIOD 60*5 // 5 minutes
# define INTEGRITY_CHECK_PERIOD 60*30 // 30 minutes
2014-05-06 13:15:20 -04:00
RsGenExchange : : RsGenExchange ( RsGeneralDataService * gds , RsNetworkExchangeService * ns ,
RsSerialType * serviceSerialiser , uint16_t servType , RsGixs * gixs ,
uint32_t authenPolicy , uint32_t messageStorePeriod )
: mGenMtx ( " GenExchange " ) ,
mDataStore ( gds ) ,
mNetService ( ns ) ,
mSerialiser ( serviceSerialiser ) ,
2014-05-17 09:50:40 -04:00
mServType ( servType ) ,
mGixs ( gixs ) ,
mAuthenPolicy ( authenPolicy ) ,
MESSAGE_STORE_PERIOD ( messageStorePeriod ) ,
mCleaning ( false ) ,
mLastClean ( time ( NULL ) ) ,
mMsgCleanUp ( NULL ) ,
mChecking ( false ) ,
mLastCheck ( time ( NULL ) ) ,
mIntegrityCheck ( NULL ) ,
CREATE_FAIL ( 0 ) ,
CREATE_SUCCESS ( 1 ) ,
CREATE_FAIL_TRY_LATER ( 2 ) ,
SIGN_MAX_ATTEMPTS ( 5 ) ,
SIGN_FAIL ( 0 ) ,
SIGN_SUCCESS ( 1 ) ,
SIGN_FAIL_TRY_LATER ( 2 ) ,
VALIDATE_FAIL ( 0 ) ,
VALIDATE_SUCCESS ( 1 ) ,
VALIDATE_FAIL_TRY_LATER ( 2 ) ,
VALIDATE_MAX_ATTEMPTS ( 5 )
{
mDataAccess = new RsGxsDataAccess ( gds ) ;
}
2014-10-05 15:14:05 -04:00
void RsGenExchange : : setNetworkExchangeService ( RsNetworkExchangeService * ns )
{
if ( mNetService ! = NULL )
std : : cerr < < " (EE) Cannot override existing network exchange service. Make sure it has been deleted otherwise. " < < std : : endl ;
else
mNetService = ns ;
}
2014-09-22 14:50:45 -04:00
# ifdef TO_BE_DELETED_IF_NOT_USEFUL
// This class has been tested so as to see where the database gets modified.
class RsDataBaseTester
{
public :
RsDataBaseTester ( RsGeneralDataService * store , const RsGxsGroupId & grpId , const std : : string & info )
: _grpId ( grpId ) , _store ( store ) , _info ( info )
{
//std::cerr << "RsDataBaseTester: (" << _info << ") retrieving messages for group " << grpId << std::endl;
_store - > retrieveMsgIds ( _grpId , _msgIds1 ) ;
}
~ RsDataBaseTester ( )
{
//std::cerr << "RsDataBaseTester: (" << _info << ") testing messages for group " << _grpId << std::endl;
_store - > retrieveMsgIds ( _grpId , _msgIds2 ) ;
bool all_idendical = true ;
std : : cerr < < std : : dec ;
if ( _msgIds1 . size ( ) ! = _msgIds2 . size ( ) )
std : : cerr < < " " < < _info < < " (EE) The two arrays are different (size1= " < < _msgIds1 . size ( ) < < " , size2= " < < _msgIds2 . size ( ) < < " ) !! " < < std : : endl ;
else
for ( uint32_t i = 0 ; i < _msgIds1 . size ( ) ; + + i )
if ( _msgIds1 [ i ] ! = _msgIds2 [ i ] )
std : : cerr < < " " < < _info < < " (EE) The two arrays are different for i= " < < i < < " !! " < < std : : endl ;
}
RsGxsGroupId _grpId ;
RsGeneralDataService * _store ;
std : : vector < RsGxsMessageId > _msgIds1 ;
std : : vector < RsGxsMessageId > _msgIds2 ;
std : : string _info ;
} ;
# endif
2014-05-17 09:50:40 -04:00
RsGenExchange : : ~ RsGenExchange ( )
{
// need to destruct in a certain order (bad thing, TODO: put down instance ownership rules!)
delete mNetService ;
delete mDataAccess ;
mDataAccess = NULL ;
delete mDataStore ;
mDataStore = NULL ;
}
2015-05-22 16:54:38 -04:00
void RsGenExchange : : data_tick ( )
2014-05-17 09:50:40 -04:00
{
2015-05-22 16:54:38 -04:00
static const double timeDelta = 0.1 ; // slow tick in sec
2014-05-17 09:50:40 -04:00
tick ( ) ;
2015-05-22 16:54:38 -04:00
usleep ( ( int ) ( timeDelta * 1000 * 1000 ) ) ; // timeDelta sec
2014-05-17 09:50:40 -04:00
}
void RsGenExchange : : tick ( )
{
// Meta Changes should happen first.
// This is important, as services want to change Meta, then get results.
// Services shouldn't rely on this ordering - but some do.
2014-10-22 17:00:20 -04:00
processGrpMetaChanges ( ) ;
2014-05-17 09:50:40 -04:00
processMsgMetaChanges ( ) ;
mDataAccess - > processRequests ( ) ;
publishGrps ( ) ;
publishMsgs ( ) ;
processGroupUpdatePublish ( ) ;
processGroupDelete ( ) ;
2014-10-22 17:00:20 -04:00
processRecvdData ( ) ;
processRoutingClues ( ) ;
2014-05-17 09:50:40 -04:00
if ( ! mNotifications . empty ( ) )
{
notifyChanges ( mNotifications ) ;
mNotifications . clear ( ) ;
}
// implemented service tick function
service_tick ( ) ;
time_t now = time ( NULL ) ;
if ( ( mLastClean + MSG_CLEANUP_PERIOD < now ) | | mCleaning )
{
if ( mMsgCleanUp )
{
if ( mMsgCleanUp - > clean ( ) )
{
mCleaning = false ;
delete mMsgCleanUp ;
mMsgCleanUp = NULL ;
mLastClean = time ( NULL ) ;
}
} else
{
mMsgCleanUp = new RsGxsMessageCleanUp ( mDataStore , MESSAGE_STORE_PERIOD , 1 ) ;
mCleaning = true ;
}
}
now = time ( NULL ) ;
if ( mChecking | | ( mLastCheck + INTEGRITY_CHECK_PERIOD < now ) )
{
if ( mIntegrityCheck )
{
if ( mIntegrityCheck - > isDone ( ) )
{
2014-09-28 08:11:29 -04:00
std : : list < RsGxsGroupId > grpIds ;
std : : map < RsGxsGroupId , std : : vector < RsGxsMessageId > > msgIds ;
mIntegrityCheck - > getDeletedIds ( grpIds , msgIds ) ;
if ( ! grpIds . empty ( ) )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-09-28 08:11:29 -04:00
RsGxsGroupChange * gc = new RsGxsGroupChange ( RsGxsNotify : : TYPE_PROCESSED , false ) ;
gc - > mGrpIdList = grpIds ;
mNotifications . push_back ( gc ) ;
}
if ( ! msgIds . empty ( ) ) {
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-09-28 08:11:29 -04:00
RsGxsMsgChange * c = new RsGxsMsgChange ( RsGxsNotify : : TYPE_PROCESSED , false ) ;
c - > msgChangeMap = msgIds ;
mNotifications . push_back ( c ) ;
}
2014-05-17 09:50:40 -04:00
delete mIntegrityCheck ;
mIntegrityCheck = NULL ;
mLastCheck = time ( NULL ) ;
mChecking = false ;
}
}
else
{
mIntegrityCheck = new RsGxsIntegrityCheck ( mDataStore ) ;
mIntegrityCheck - > start ( ) ;
mChecking = true ;
}
}
}
2014-09-22 14:50:45 -04:00
bool RsGenExchange : : messagePublicationTest ( const RsGxsMsgMetaData & meta )
{
time_t now = time ( NULL ) ;
return meta . mMsgStatus & GXS_SERV : : GXS_MSG_STATUS_KEEP | | meta . mPublishTs + MESSAGE_STORE_PERIOD > = now ;
}
2014-05-17 09:50:40 -04:00
bool RsGenExchange : : acknowledgeTokenMsg ( const uint32_t & token ,
RsGxsGrpMsgIdPair & msgId )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::acknowledgeTokenMsg(). token= " < < token < < std : : endl ;
# endif
std : : map < uint32_t , RsGxsGrpMsgIdPair > : : iterator mit = mMsgNotify . find ( token ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
if ( mit = = mMsgNotify . end ( ) )
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " no notification found for this token. " < < std : : endl ;
# endif
return false ;
}
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
msgId = mit - > second ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
// no dump token as client has ackowledged its completion
mDataAccess - > disposeOfPublicToken ( token ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " found grpId= " < < msgId . first < < " , msgId= " < < msgId . second < < std : : endl ;
std : : cerr < < " disposing token from mDataAccess " < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
return true ;
}
2014-09-20 15:58:07 -04:00
bool RsGenExchange : : acknowledgeTokenGrp ( const uint32_t & token , RsGxsGroupId & grpId )
2014-05-17 09:50:40 -04:00
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::acknowledgeTokenGrp(). token= " < < token < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
std : : map < uint32_t , RsGxsGroupId > : : iterator mit =
mGrpNotify . find ( token ) ;
2014-09-20 15:58:07 -04:00
if ( mit = = mGrpNotify . end ( ) )
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " no notification found for this token. " < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
return false ;
2014-09-20 15:58:07 -04:00
}
2014-05-17 09:50:40 -04:00
grpId = mit - > second ;
// no dump token as client has ackowledged its completion
mDataAccess - > disposeOfPublicToken ( token ) ;
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " found grpId= " < < grpId < < std : : endl ;
std : : cerr < < " disposing token from mDataAccess " < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
return true ;
}
void RsGenExchange : : generateGroupKeys ( RsTlvSecurityKeySet & privatekeySet , RsTlvSecurityKeySet & publickeySet , bool genPublishKeys )
{
/* create Keys */
RsTlvSecurityKey adminKey , privAdminKey ;
GxsSecurity : : generateKeyPair ( adminKey , privAdminKey ) ;
// for now all public
adminKey . keyFlags = RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_PUBLIC_ONLY ;
privAdminKey . keyFlags = RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL ;
publickeySet . keys [ adminKey . keyId ] = adminKey ;
privatekeySet . keys [ privAdminKey . keyId ] = privAdminKey ;
if ( genPublishKeys )
{
/* set publish keys */
2015-05-19 17:28:46 -04:00
RsTlvSecurityKey publishKey , privPublishKey ;
GxsSecurity : : generateKeyPair ( publishKey , privPublishKey ) ;
2014-05-17 09:50:40 -04:00
// for now all public
2015-05-19 17:28:46 -04:00
publishKey . keyFlags = RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_PUBLIC_ONLY ;
privPublishKey . keyFlags = RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL ;
2014-05-17 09:50:40 -04:00
2015-05-19 17:28:46 -04:00
publickeySet . keys [ publishKey . keyId ] = publishKey ;
privatekeySet . keys [ privPublishKey . keyId ] = privPublishKey ;
2014-05-17 09:50:40 -04:00
}
}
void RsGenExchange : : generatePublicFromPrivateKeys ( const RsTlvSecurityKeySet & privatekeySet , RsTlvSecurityKeySet & publickeySet )
{
// actually just copy settings of one key except mark its key flags public
publickeySet = RsTlvSecurityKeySet ( ) ;
RsTlvSecurityKey pubkey ;
2014-06-12 06:28:23 -04:00
for ( std : : map < RsGxsId , RsTlvSecurityKey > : : const_iterator cit = privatekeySet . keys . begin ( ) ; cit ! = privatekeySet . keys . end ( ) ; + + cit )
2014-05-17 09:50:40 -04:00
if ( GxsSecurity : : extractPublicKey ( cit - > second , pubkey ) )
publickeySet . keys . insert ( std : : make_pair ( pubkey . keyId , pubkey ) ) ;
}
uint8_t RsGenExchange : : createGroup ( RsNxsGrp * grp , RsTlvSecurityKeySet & privateKeySet , RsTlvSecurityKeySet & publicKeySet )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::createGroup() " ;
std : : cerr < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2014-05-17 09:50:40 -04:00
RsGxsGrpMetaData * meta = grp - > metaData ;
/* add public admin and publish keys to grp */
// find private admin key
RsTlvSecurityKey privAdminKey ;
2014-06-12 06:28:23 -04:00
std : : map < RsGxsId , RsTlvSecurityKey > : : iterator mit = privateKeySet . keys . begin ( ) ;
2014-05-17 09:50:40 -04:00
bool privKeyFound = false ; // private admin key
2014-10-24 18:07:26 -04:00
for ( ; mit ! = privateKeySet . keys . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
RsTlvSecurityKey & key = mit - > second ;
if ( ( key . keyFlags & RSTLV_KEY_DISTRIB_ADMIN ) & & ( key . keyFlags & RSTLV_KEY_TYPE_FULL ) )
{
privAdminKey = key ;
privKeyFound = true ;
2015-05-19 17:28:46 -04:00
break ;
2014-05-17 09:50:40 -04:00
}
}
if ( ! privKeyFound )
{
std : : cerr < < " RsGenExchange::createGroup() Missing private ADMIN Key " ;
std : : cerr < < std : : endl ;
return false ;
}
meta - > keys = publicKeySet ; // only public keys are included to be transported
// group is self signing
// for the creation of group signature
// only public admin and publish keys are present in meta
uint32_t metaDataLen = meta - > serial_size ( ) ;
uint32_t allGrpDataLen = metaDataLen + grp - > grp . bin_len ;
char * metaData = new char [ metaDataLen ] ;
char * allGrpData = new char [ allGrpDataLen ] ; // msgData + metaData
meta - > serialise ( metaData , metaDataLen ) ;
// copy msg data and meta in allMsgData buffer
memcpy ( allGrpData , grp - > grp . bin_data , grp - > grp . bin_len ) ;
memcpy ( allGrpData + ( grp - > grp . bin_len ) , metaData , metaDataLen ) ;
RsTlvKeySignature adminSign ;
bool ok = GxsSecurity : : getSignature ( allGrpData , allGrpDataLen , privAdminKey , adminSign ) ;
// add admin sign to grpMeta
2015-10-23 22:53:00 -04:00
meta - > signSet . keySignSet [ INDEX_AUTHEN_ADMIN ] = adminSign ;
2014-05-17 09:50:40 -04:00
RsTlvBinaryData grpData ( mServType ) ;
grpData . setBinData ( allGrpData , allGrpDataLen ) ;
uint8_t ret = createGroupSignatures ( meta - > signSet , grpData , * ( grp - > metaData ) ) ;
// clean up
delete [ ] allGrpData ;
delete [ ] metaData ;
if ( ! ok )
{
2015-01-31 13:06:37 -05:00
std : : cerr < < " RsGenExchange::createGroup() ERROR !okay (getSignature error) " ;
2014-05-17 09:50:40 -04:00
std : : cerr < < std : : endl ;
return CREATE_FAIL ;
}
if ( ret = = SIGN_FAIL )
{
return CREATE_FAIL ;
} else if ( ret = = SIGN_FAIL_TRY_LATER )
{
return CREATE_FAIL_TRY_LATER ;
} else if ( ret = = SIGN_SUCCESS )
{
return CREATE_SUCCESS ;
} else {
return CREATE_FAIL ;
}
}
int RsGenExchange : : createGroupSignatures ( RsTlvKeySignatureSet & signSet , RsTlvBinaryData & grpData ,
RsGxsGrpMetaData & grpMeta )
{
bool needIdentitySign = false ;
int id_ret ;
uint8_t author_flag = GXS_SERV : : GRP_OPTION_AUTHEN_AUTHOR_SIGN ;
PrivacyBitPos pos = GRP_OPTION_BITS ;
// Check required permissions, and allow them to sign it - if they want too - as well!
if ( ( ! grpMeta . mAuthorId . isNull ( ) ) | | checkAuthenFlag ( pos , author_flag ) )
{
needIdentitySign = true ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " Needs Identity sign! (Service Flags) " ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
}
if ( needIdentitySign )
{
2015-03-19 04:43:40 -04:00
if ( grpMeta . mAuthorId . isNull ( ) )
{
std : : cerr < < " RsGenExchange::createGroupSignatures() " ;
std : : cerr < < " Group signature is required by service, but the author id is null. " < < std : : endl ;
id_ret = SIGN_FAIL ;
}
else if ( mGixs )
2014-05-17 09:50:40 -04:00
{
bool haveKey = mGixs - > havePrivateKey ( grpMeta . mAuthorId ) ;
if ( haveKey )
{
RsTlvSecurityKey authorKey ;
mGixs - > getPrivateKey ( grpMeta . mAuthorId , authorKey ) ;
RsTlvKeySignature sign ;
if ( GxsSecurity : : getSignature ( ( char * ) grpData . bin_data , grpData . bin_len ,
authorKey , sign ) )
{
id_ret = SIGN_SUCCESS ;
}
else
{
id_ret = SIGN_FAIL ;
}
2015-10-23 22:53:00 -04:00
signSet . keySignSet [ INDEX_AUTHEN_IDENTITY ] = sign ;
2014-05-17 09:50:40 -04:00
}
else
{
mGixs - > requestPrivateKey ( grpMeta . mAuthorId ) ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::createGroupSignatures(): " ;
std : : cerr < < " ERROR AUTHOR KEY: " < < grpMeta . mAuthorId
< < " is not Cached / available for Message Signing \n " ;
std : : cerr < < " RsGenExchange::createGroupSignatures(): Requestiong AUTHOR KEY " ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
id_ret = SIGN_FAIL_TRY_LATER ;
}
}
else
{
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::createGroupSignatures() " ;
std : : cerr < < " Gixs not enabled while request identity signature validation! " < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
id_ret = SIGN_FAIL ;
}
}
else
{
id_ret = SIGN_SUCCESS ;
}
return id_ret ;
}
int RsGenExchange : : createMsgSignatures ( RsTlvKeySignatureSet & signSet , RsTlvBinaryData & msgData ,
const RsGxsMsgMetaData & msgMeta , RsGxsGrpMetaData & grpMeta )
{
bool needPublishSign = false , needIdentitySign = false ;
uint32_t grpFlag = grpMeta . mGroupFlags ;
bool publishSignSuccess = false ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::createMsgSignatures() for Msg.mMsgName: " < < msgMeta . mMsgName ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
// publish signature is determined by whether group is public or not
// for private group signature is not needed as it needs decrypting with
// the private publish key anyways
// restricted is a special case which heeds whether publish sign needs to be checked or not
// one may or may not want
uint8_t author_flag = GXS_SERV : : MSG_AUTHEN_ROOT_AUTHOR_SIGN ;
uint8_t publish_flag = GXS_SERV : : MSG_AUTHEN_ROOT_PUBLISH_SIGN ;
if ( ! msgMeta . mParentId . isNull ( ) )
{
// Child Message.
author_flag = GXS_SERV : : MSG_AUTHEN_CHILD_AUTHOR_SIGN ;
publish_flag = GXS_SERV : : MSG_AUTHEN_CHILD_PUBLISH_SIGN ;
}
PrivacyBitPos pos = PUBLIC_GRP_BITS ;
if ( grpFlag & GXS_SERV : : FLAG_PRIVACY_RESTRICTED )
{
pos = RESTRICTED_GRP_BITS ;
}
else if ( grpFlag & GXS_SERV : : FLAG_PRIVACY_PRIVATE )
{
pos = PRIVATE_GRP_BITS ;
}
needIdentitySign = false ;
needPublishSign = false ;
if ( checkAuthenFlag ( pos , publish_flag ) )
{
needPublishSign = true ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " Needs Publish sign! (Service Flags) " ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
}
// Check required permissions, and allow them to sign it - if they want too - as well!
if ( checkAuthenFlag ( pos , author_flag ) )
{
needIdentitySign = true ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " Needs Identity sign! (Service Flags) " ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
}
if ( ! msgMeta . mAuthorId . isNull ( ) )
{
needIdentitySign = true ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " Needs Identity sign! (AuthorId Exists) " ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
}
if ( needPublishSign )
{
// public and shared is publish key
RsTlvSecurityKeySet & keys = grpMeta . keys ;
2015-05-19 17:28:46 -04:00
RsTlvSecurityKey * publishKey ;
2014-05-17 09:50:40 -04:00
2014-06-12 06:28:23 -04:00
std : : map < RsGxsId , RsTlvSecurityKey > : : iterator mit =
2014-05-17 09:50:40 -04:00
keys . keys . begin ( ) , mit_end = keys . keys . end ( ) ;
2015-05-19 17:28:46 -04:00
bool publish_key_found = false ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = mit_end ; + + mit )
2014-05-17 09:50:40 -04:00
{
2015-05-19 17:28:46 -04:00
publish_key_found = mit - > second . keyFlags = = ( RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL ) ;
if ( publish_key_found )
2014-05-17 09:50:40 -04:00
break ;
}
2015-05-19 17:28:46 -04:00
if ( publish_key_found )
2014-05-17 09:50:40 -04:00
{
// private publish key
2015-05-19 17:28:46 -04:00
publishKey = & ( mit - > second ) ;
2014-05-17 09:50:40 -04:00
2015-10-23 22:53:00 -04:00
RsTlvKeySignature publishSign = signSet . keySignSet [ INDEX_AUTHEN_PUBLISH ] ;
2014-05-17 09:50:40 -04:00
2015-05-19 17:28:46 -04:00
publishSignSuccess = GxsSecurity : : getSignature ( ( char * ) msgData . bin_data , msgData . bin_len , * publishKey , publishSign ) ;
2014-05-17 09:50:40 -04:00
//place signature in msg meta
2015-10-23 22:53:00 -04:00
signSet . keySignSet [ INDEX_AUTHEN_PUBLISH ] = publishSign ;
2014-05-17 09:50:40 -04:00
} else
{
std : : cerr < < " RsGenExchange::createMsgSignatures() " ;
std : : cerr < < " ERROR Cannot find PUBLISH KEY for Message Signing! " ;
std : : cerr < < " ERROR Publish Sign failed! " ;
std : : cerr < < std : : endl ;
}
}
else // publish sign not needed so set as successful
{
publishSignSuccess = true ;
}
int id_ret ;
if ( needIdentitySign )
{
if ( mGixs )
{
bool haveKey = mGixs - > havePrivateKey ( msgMeta . mAuthorId ) ;
if ( haveKey )
{
RsTlvSecurityKey authorKey ;
mGixs - > getPrivateKey ( msgMeta . mAuthorId , authorKey ) ;
RsTlvKeySignature sign ;
if ( GxsSecurity : : getSignature ( ( char * ) msgData . bin_data , msgData . bin_len ,
authorKey , sign ) )
{
id_ret = SIGN_SUCCESS ;
}
else
{
id_ret = SIGN_FAIL ;
}
2015-10-23 22:53:00 -04:00
signSet . keySignSet [ INDEX_AUTHEN_IDENTITY ] = sign ;
2014-05-17 09:50:40 -04:00
}
else
{
mGixs - > requestPrivateKey ( msgMeta . mAuthorId ) ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::createMsgSignatures(): " ;
std : : cerr < < " ERROR AUTHOR KEY: " < < msgMeta . mAuthorId
< < " is not Cached / available for Message Signing \n " ;
std : : cerr < < " RsGenExchange::createMsgSignatures(): Requestiong AUTHOR KEY " ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
id_ret = SIGN_FAIL_TRY_LATER ;
}
}
else
{
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::createMsgSignatures() " ;
std : : cerr < < " Gixs not enabled while request identity signature validation! " < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
id_ret = SIGN_FAIL ;
}
}
else
{
id_ret = SIGN_SUCCESS ;
}
if ( publishSignSuccess )
{
return id_ret ;
}
else
{
return SIGN_FAIL ;
}
}
int RsGenExchange : : createMessage ( RsNxsMsg * msg )
{
const RsGxsGroupId & id = msg - > grpId ;
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::createMessage() " < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > metaMap ;
metaMap . insert ( std : : make_pair ( id , ( RsGxsGrpMetaData * ) ( NULL ) ) ) ;
mDataStore - > retrieveGxsGrpMetaData ( metaMap ) ;
RsGxsMsgMetaData & meta = * ( msg - > metaData ) ;
int ret_val ;
if ( ! metaMap [ id ] )
{
return CREATE_FAIL ;
}
else
{
// get publish key
RsGxsGrpMetaData * grpMeta = metaMap [ id ] ;
uint32_t metaDataLen = meta . serial_size ( ) ;
uint32_t allMsgDataLen = metaDataLen + msg - > msg . bin_len ;
char * metaData = new char [ metaDataLen ] ;
char * allMsgData = new char [ allMsgDataLen ] ; // msgData + metaData
meta . serialise ( metaData , & metaDataLen ) ;
// copy msg data and meta in allmsgData buffer
memcpy ( allMsgData , msg - > msg . bin_data , msg - > msg . bin_len ) ;
memcpy ( allMsgData + ( msg - > msg . bin_len ) , metaData , metaDataLen ) ;
RsTlvBinaryData msgData ( 0 ) ;
msgData . setBinData ( allMsgData , allMsgDataLen ) ;
// create signatures
ret_val = createMsgSignatures ( meta . signSet , msgData , meta , * grpMeta ) ;
// get hash of msg data to create msg id
pqihash hash ;
hash . addData ( allMsgData , allMsgDataLen ) ;
RsFileHash hashId ;
hash . Complete ( hashId ) ;
msg - > msgId = hashId ;
// assign msg id to msg meta
msg - > metaData - > mMsgId = msg - > msgId ;
delete [ ] metaData ;
delete [ ] allMsgData ;
delete grpMeta ;
}
if ( ret_val = = SIGN_FAIL )
return CREATE_FAIL ;
else if ( ret_val = = SIGN_FAIL_TRY_LATER )
return CREATE_FAIL_TRY_LATER ;
else if ( ret_val = = SIGN_SUCCESS )
return CREATE_SUCCESS ;
else
{
std : : cerr < < " Unknown return value from signature attempt! " ;
return CREATE_FAIL ;
}
}
2015-10-23 22:53:00 -04:00
int RsGenExchange : : validateMsg ( RsNxsMsg * msg , const uint32_t & grpFlag , const uint32_t & signFlag , RsTlvSecurityKeySet & grpKeySet )
2014-05-17 09:50:40 -04:00
{
bool needIdentitySign = false ;
bool needPublishSign = false ;
bool publishValidate = true , idValidate = true ;
uint8_t author_flag = GXS_SERV : : MSG_AUTHEN_ROOT_AUTHOR_SIGN ;
uint8_t publish_flag = GXS_SERV : : MSG_AUTHEN_ROOT_PUBLISH_SIGN ;
if ( ! msg - > metaData - > mParentId . isNull ( ) )
{
// Child Message.
author_flag = GXS_SERV : : MSG_AUTHEN_CHILD_AUTHOR_SIGN ;
publish_flag = GXS_SERV : : MSG_AUTHEN_CHILD_PUBLISH_SIGN ;
}
PrivacyBitPos pos = PUBLIC_GRP_BITS ;
if ( grpFlag & GXS_SERV : : FLAG_PRIVACY_RESTRICTED )
{
pos = RESTRICTED_GRP_BITS ;
}
else if ( grpFlag & GXS_SERV : : FLAG_PRIVACY_PRIVATE )
{
pos = PRIVATE_GRP_BITS ;
}
if ( checkAuthenFlag ( pos , publish_flag ) )
needPublishSign = true ;
// Check required permissions, if they have signed it anyway - we need to validate it.
if ( ( checkAuthenFlag ( pos , author_flag ) ) | | ( ! msg - > metaData - > mAuthorId . isNull ( ) ) )
needIdentitySign = true ;
2015-10-23 22:53:00 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " Validate message: msgId= " < < msg - > msgId < < " , grpId= " < < msg - > grpId < < " grpFlags= " < < std : : hex < < grpFlag < < std : : dec
< < " . Need publish= " < < needPublishSign < < " , needIdentitySign= " < < needIdentitySign ;
# endif
2014-05-17 09:50:40 -04:00
RsGxsMsgMetaData & metaData = * ( msg - > metaData ) ;
if ( needPublishSign )
{
2015-10-23 22:53:00 -04:00
RsTlvKeySignature sign = metaData . signSet . keySignSet [ INDEX_AUTHEN_PUBLISH ] ;
2014-05-17 09:50:40 -04:00
2014-06-12 06:28:23 -04:00
std : : map < RsGxsId , RsTlvSecurityKey > & keys = grpKeySet . keys ;
std : : map < RsGxsId , RsTlvSecurityKey > : : iterator mit = keys . begin ( ) ;
2014-05-17 09:50:40 -04:00
2014-06-12 06:28:23 -04:00
RsGxsId keyId ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = keys . end ( ) ; + + mit )
2015-05-19 17:28:46 -04:00
{
RsTlvSecurityKey & key = mit - > second ;
2014-05-17 09:50:40 -04:00
2015-05-19 17:28:46 -04:00
if ( key . keyFlags & RSTLV_KEY_DISTRIB_PUBLIC_deprecated )
{
keyId = key . keyId ;
std : : cerr < < " WARNING: old style publish key with flags " < < key . keyFlags < < std : : endl ;
std : : cerr < < " this cannot be fixed, but RS will deal with it. " < < std : : endl ;
break ;
2014-05-17 09:50:40 -04:00
}
2015-05-19 17:28:46 -04:00
if ( key . keyFlags & RSTLV_KEY_DISTRIB_PUBLISH ) // we might have the private key, but we still should be able to check the signature
{
keyId = key . keyId ;
break ;
}
}
2014-05-17 09:50:40 -04:00
2014-06-12 06:28:23 -04:00
if ( ! keyId . isNull ( ) )
2014-05-17 09:50:40 -04:00
{
RsTlvSecurityKey & key = keys [ keyId ] ;
publishValidate & = GxsSecurity : : validateNxsMsg ( * msg , sign , key ) ;
}
else
{
publishValidate = false ;
}
}
else
{
publishValidate = true ;
}
if ( needIdentitySign )
{
if ( mGixs )
{
bool haveKey = mGixs - > haveKey ( metaData . mAuthorId ) ;
if ( haveKey )
2015-10-23 22:53:00 -04:00
{
RsTlvSecurityKey authorKey ;
bool auth_key_fetched = mGixs - > getKey ( metaData . mAuthorId , authorKey ) ;
if ( auth_key_fetched )
{
RsTlvKeySignature sign = metaData . signSet . keySignSet [ INDEX_AUTHEN_IDENTITY ] ;
idValidate & = GxsSecurity : : validateNxsMsg ( * msg , sign , authorKey ) ;
mGixs - > timeStampKey ( metaData . mAuthorId ) ;
}
else
{
std : : cerr < < " RsGenExchange::validateMsg() " ;
std : : cerr < < " ERROR Cannot Retrieve AUTHOR KEY for Message Validation " ;
std : : cerr < < std : : endl ;
idValidate = false ;
}
2015-10-24 10:41:31 -04:00
if ( idValidate & & ( signFlag & GXS_SERV : : FLAG_AUTHOR_AUTHENTICATION_GPG ) )
{
// get key data and check that the key is actually PGP-linked. If not, reject the post.
RsIdentityDetails details ;
if ( ! mGixs - > getIdDetails ( metaData . mAuthorId , details ) )
{
// the key cannot ke reached, although it's in cache. Weird situation.
idValidate = false ;
std : : cerr < < " RsGenExchange::validateMsg(): cannot get key data for ID= " < < metaData . mAuthorId < < " , although it's supposed to be already in cache. Cannot validate. " < < std : : endl ;
idValidate = false ;
}
if ( ! details . mPgpLinked )
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::validateMsg(): message from " < < metaData . mAuthorId < < " , rejected because key is not PGP linked and the group requires it. " < < std : : endl ;
# endif
idValidate = false ;
}
}
2015-10-23 22:53:00 -04:00
}
else
2014-05-17 09:50:40 -04:00
{
std : : list < RsPeerId > peers ;
peers . push_back ( msg - > PeerId ( ) ) ;
mGixs - > requestKey ( metaData . mAuthorId , peers ) ;
2015-10-23 22:53:00 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " , Key missing. Retry later. " < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
return VALIDATE_FAIL_TRY_LATER ;
}
}
else
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " Gixs not enabled while request identity signature validation! " < < std : : endl ;
# endif
idValidate = false ;
}
}
else
{
idValidate = true ;
}
2015-10-23 22:53:00 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " , publish val= " < < publishValidate < < " , idValidate= " < < idValidate < < " . Result= " < < ( publishValidate & & idValidate ) < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
if ( publishValidate & & idValidate )
return VALIDATE_SUCCESS ;
else
return VALIDATE_FAIL ;
}
int RsGenExchange : : validateGrp ( RsNxsGrp * grp )
{
bool needIdentitySign = false , idValidate = false ;
RsGxsGrpMetaData & metaData = * ( grp - > metaData ) ;
uint8_t author_flag = GXS_SERV : : GRP_OPTION_AUTHEN_AUTHOR_SIGN ;
PrivacyBitPos pos = GRP_OPTION_BITS ;
// Check required permissions, and allow them to sign it - if they want too - as well!
2015-08-21 20:46:34 -04:00
if ( ( ! metaData . mAuthorId . isNull ( ) ) | | checkAuthenFlag ( pos , author_flag ) )
2014-05-17 09:50:40 -04:00
{
needIdentitySign = true ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " Needs Identity sign! (Service Flags) " ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2014-05-17 09:50:40 -04:00
}
if ( needIdentitySign )
{
if ( mGixs )
{
bool haveKey = mGixs - > haveKey ( metaData . mAuthorId ) ;
if ( haveKey )
{
RsTlvSecurityKey authorKey ;
2014-11-25 15:31:18 -05:00
bool auth_key_fetched = mGixs - > getKey ( metaData . mAuthorId , authorKey ) ;
2014-05-17 09:50:40 -04:00
if ( auth_key_fetched )
{
2015-10-23 22:53:00 -04:00
RsTlvKeySignature sign = metaData . signSet . keySignSet [ INDEX_AUTHEN_IDENTITY ] ;
2015-03-14 10:33:23 -04:00
idValidate = GxsSecurity : : validateNxsGrp ( * grp , sign , authorKey ) ;
mGixs - > timeStampKey ( metaData . mAuthorId ) ;
2014-05-17 09:50:40 -04:00
}
else
{
std : : cerr < < " RsGenExchange::validateGrp() " ;
std : : cerr < < " ERROR Cannot Retrieve AUTHOR KEY for Group Sign Validation " ;
std : : cerr < < std : : endl ;
idValidate = false ;
}
} else
{
std : : list < RsPeerId > peers ;
peers . push_back ( grp - > PeerId ( ) ) ;
mGixs - > requestKey ( metaData . mAuthorId , peers ) ;
return VALIDATE_FAIL_TRY_LATER ;
}
}
else
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " Gixs not enabled while request identity signature validation! " < < std : : endl ;
# endif
idValidate = false ;
}
}
else
{
idValidate = true ;
}
if ( idValidate )
return VALIDATE_SUCCESS ;
else
return VALIDATE_FAIL ;
}
bool RsGenExchange : : checkAuthenFlag ( const PrivacyBitPos & pos , const uint8_t & flag ) const
{
2015-06-16 15:11:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::checkMsgAuthenFlag(pos: " < < pos < < " flag: " ;
std : : cerr < < ( int ) flag < < " mAuthenPolicy: " < < mAuthenPolicy < < " ) " ;
std : : cerr < < std : : endl ;
2015-06-16 15:11:07 -04:00
# endif
2014-05-17 09:50:40 -04:00
switch ( pos )
{
case PUBLIC_GRP_BITS :
return mAuthenPolicy & flag ;
break ;
case RESTRICTED_GRP_BITS :
return flag & ( mAuthenPolicy > > RESTR_GRP_OFFSET ) ;
break ;
case PRIVATE_GRP_BITS :
return flag & ( mAuthenPolicy > > PRIV_GRP_OFFSET ) ;
break ;
case GRP_OPTION_BITS :
return flag & ( mAuthenPolicy > > GRP_OPTIONS_OFFSET ) ;
break ;
default :
std : : cerr < < " pos option not recognised " ;
return false ;
}
}
2015-03-11 09:39:58 -04:00
static void addMessageChanged ( std : : map < RsGxsGroupId , std : : vector < RsGxsMessageId > > & msgs , const std : : map < RsGxsGroupId , std : : vector < RsGxsMessageId > > & msgChanged )
{
2015-03-20 06:39:17 -04:00
if ( msgs . empty ( ) ) {
msgs = msgChanged ;
} else {
std : : map < RsGxsGroupId , std : : vector < RsGxsMessageId > > : : const_iterator mapIt ;
for ( mapIt = msgChanged . begin ( ) ; mapIt ! = msgChanged . end ( ) ; + + mapIt ) {
const RsGxsGroupId & grpId = mapIt - > first ;
const std : : vector < RsGxsMessageId > & srcMsgIds = mapIt - > second ;
std : : vector < RsGxsMessageId > & destMsgIds = msgs [ grpId ] ;
std : : vector < RsGxsMessageId > : : const_iterator msgIt ;
for ( msgIt = srcMsgIds . begin ( ) ; msgIt ! = srcMsgIds . end ( ) ; + + msgIt ) {
if ( std : : find ( destMsgIds . begin ( ) , destMsgIds . end ( ) , * msgIt ) = = destMsgIds . end ( ) ) {
destMsgIds . push_back ( * msgIt ) ;
}
}
}
}
2014-05-17 09:50:40 -04:00
}
2015-03-20 06:39:17 -04:00
void RsGenExchange : : receiveChanges ( std : : vector < RsGxsNotify * > & changes )
2014-05-17 09:50:40 -04:00
{
2015-03-20 06:39:17 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::receiveChanges() " < < std : : endl ;
# endif
RsGxsChanges out ;
out . mService = getTokenService ( ) ;
2014-05-17 09:50:40 -04:00
2015-03-20 06:39:17 -04:00
// collect all changes in one GxsChanges object
std : : vector < RsGxsNotify * > : : iterator vit = changes . begin ( ) ;
for ( ; vit ! = changes . end ( ) ; + + vit )
{
RsGxsNotify * n = * vit ;
RsGxsGroupChange * gc ;
RsGxsMsgChange * mc ;
if ( ( mc = dynamic_cast < RsGxsMsgChange * > ( n ) ) ! = NULL )
{
if ( mc - > metaChange ( ) )
{
addMessageChanged ( out . mMsgsMeta , mc - > msgChangeMap ) ;
}
else
{
addMessageChanged ( out . mMsgs , mc - > msgChangeMap ) ;
}
}
else if ( ( gc = dynamic_cast < RsGxsGroupChange * > ( n ) ) ! = NULL )
{
if ( gc - > metaChange ( ) )
{
out . mGrpsMeta . splice ( out . mGrpsMeta . end ( ) , gc - > mGrpIdList ) ;
}
else
{
out . mGrps . splice ( out . mGrps . end ( ) , gc - > mGrpIdList ) ;
}
}
delete n ;
}
RsServer : : notify ( ) - > notifyGxsChange ( out ) ;
2014-05-17 09:50:40 -04:00
}
bool RsGenExchange : : subscribeToGroup ( uint32_t & token , const RsGxsGroupId & grpId , bool subscribe )
{
if ( subscribe )
setGroupSubscribeFlags ( token , grpId , GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED ,
2015-01-28 17:48:59 -05:00
( GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED | GXS_SERV : : GROUP_SUBSCRIBE_NOT_SUBSCRIBED ) ) ;
2014-05-17 09:50:40 -04:00
else
setGroupSubscribeFlags ( token , grpId , GXS_SERV : : GROUP_SUBSCRIBE_NOT_SUBSCRIBED ,
2015-01-28 17:48:59 -05:00
( GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED | GXS_SERV : : GROUP_SUBSCRIBE_NOT_SUBSCRIBED ) ) ;
2014-05-17 09:50:40 -04:00
2015-01-29 09:21:18 -05:00
if ( mNetService ! = NULL )
mNetService - > subscribeStatusChanged ( grpId , subscribe ) ;
2015-01-28 17:48:59 -05:00
return true ;
2014-05-17 09:50:40 -04:00
}
2014-07-20 07:21:06 -04:00
bool RsGenExchange : : getGroupStatistic ( const uint32_t & token , GxsGroupStatistic & stats )
2014-05-17 09:50:40 -04:00
{
2014-07-20 07:21:06 -04:00
return mDataAccess - > getGroupStatistic ( token , stats ) ;
2014-05-17 09:50:40 -04:00
}
2014-07-20 07:21:06 -04:00
bool RsGenExchange : : getServiceStatistic ( const uint32_t & token , GxsServiceStatistic & stats )
2014-05-17 09:50:40 -04:00
{
2014-07-20 07:21:06 -04:00
return mDataAccess - > getServiceStatistic ( token , stats ) ;
2014-05-17 09:50:40 -04:00
}
bool RsGenExchange : : getGroupList ( const uint32_t & token , std : : list < RsGxsGroupId > & groupIds )
{
return mDataAccess - > getGroupList ( token , groupIds ) ;
}
bool RsGenExchange : : getMsgList ( const uint32_t & token ,
GxsMsgIdResult & msgIds )
{
return mDataAccess - > getMsgList ( token , msgIds ) ;
}
bool RsGenExchange : : getMsgRelatedList ( const uint32_t & token , MsgRelatedIdResult & msgIds )
{
return mDataAccess - > getMsgRelatedList ( token , msgIds ) ;
}
bool RsGenExchange : : getGroupMeta ( const uint32_t & token , std : : list < RsGroupMetaData > & groupInfo )
{
std : : list < RsGxsGrpMetaData * > metaL ;
bool ok = mDataAccess - > getGroupSummary ( token , metaL ) ;
std : : list < RsGxsGrpMetaData * > : : iterator lit = metaL . begin ( ) ;
RsGroupMetaData m ;
2014-10-24 18:07:26 -04:00
for ( ; lit ! = metaL . end ( ) ; + + lit )
2014-05-17 09:50:40 -04:00
{
RsGxsGrpMetaData & gMeta = * ( * lit ) ;
2014-10-07 17:42:44 -04:00
m = gMeta ;
2014-12-16 01:54:15 -05:00
RsGroupNetworkStats sts ;
2014-10-07 17:42:44 -04:00
2014-12-16 01:54:15 -05:00
if ( mNetService ! = NULL & & mNetService - > getGroupNetworkStats ( ( * lit ) - > mGroupId , sts ) )
{
m . mPop = sts . mSuppliers ;
m . mVisibleMsgCount = sts . mMaxVisibleCount ;
}
else
{
m . mPop = 0 ;
m . mVisibleMsgCount = 0 ;
}
2014-10-07 17:42:44 -04:00
groupInfo . push_back ( m ) ;
2014-05-17 09:50:40 -04:00
delete ( * lit ) ;
}
return ok ;
}
bool RsGenExchange : : getMsgMeta ( const uint32_t & token ,
GxsMsgMetaMap & msgInfo )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::getMsgMeta(): retrieving meta data for token " < < token < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
std : : list < RsGxsMsgMetaData * > metaL ;
GxsMsgMetaResult result ;
bool ok = mDataAccess - > getMsgSummary ( token , result ) ;
GxsMsgMetaResult : : iterator mit = result . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = result . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
std : : vector < RsGxsMsgMetaData * > & metaV = mit - > second ;
std : : vector < RsMsgMetaData > & msgInfoV = msgInfo [ mit - > first ] ;
std : : vector < RsGxsMsgMetaData * > : : iterator vit = metaV . begin ( ) ;
RsMsgMetaData meta ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = metaV . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
RsGxsMsgMetaData & m = * ( * vit ) ;
meta = m ;
msgInfoV . push_back ( meta ) ;
delete * vit ;
}
metaV . clear ( ) ;
}
return ok ;
}
bool RsGenExchange : : getMsgRelatedMeta ( const uint32_t & token , GxsMsgRelatedMetaMap & msgMeta )
{
MsgRelatedMetaResult result ;
bool ok = mDataAccess - > getMsgRelatedSummary ( token , result ) ;
MsgRelatedMetaResult : : iterator mit = result . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = result . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
std : : vector < RsGxsMsgMetaData * > & metaV = mit - > second ;
std : : vector < RsMsgMetaData > & msgInfoV = msgMeta [ mit - > first ] ;
std : : vector < RsGxsMsgMetaData * > : : iterator vit = metaV . begin ( ) ;
RsMsgMetaData meta ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = metaV . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
RsGxsMsgMetaData & m = * ( * vit ) ;
meta = m ;
msgInfoV . push_back ( meta ) ;
delete * vit ;
}
metaV . clear ( ) ;
}
return ok ;
}
bool RsGenExchange : : getGroupData ( const uint32_t & token , std : : vector < RsGxsGrpItem * > & grpItem )
{
std : : list < RsNxsGrp * > nxsGrps ;
bool ok = mDataAccess - > getGroupData ( token , nxsGrps ) ;
std : : list < RsNxsGrp * > : : iterator lit = nxsGrps . begin ( ) ;
2015-01-31 13:06:37 -05:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::getGroupData() RsNxsGrp::len: " < < nxsGrps . size ( ) ;
2015-01-31 13:06:37 -05:00
std : : cerr < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
if ( ok )
{
2014-10-24 18:07:26 -04:00
for ( ; lit ! = nxsGrps . end ( ) ; + + lit )
2014-05-17 09:50:40 -04:00
{
RsTlvBinaryData & data = ( * lit ) - > grp ;
RsItem * item = NULL ;
if ( data . bin_len ! = 0 )
item = mSerialiser - > deserialise ( data . bin_data , & data . bin_len ) ;
if ( item )
{
RsGxsGrpItem * gItem = dynamic_cast < RsGxsGrpItem * > ( item ) ;
if ( gItem )
{
2014-10-07 17:42:44 -04:00
gItem - > meta = * ( ( * lit ) - > metaData ) ;
2014-12-16 01:54:15 -05:00
RsGroupNetworkStats sts ;
if ( mNetService ! = NULL & & mNetService - > getGroupNetworkStats ( gItem - > meta . mGroupId , sts ) )
{
gItem - > meta . mPop = sts . mSuppliers ;
gItem - > meta . mVisibleMsgCount = sts . mMaxVisibleCount ;
}
2014-10-07 17:42:44 -04:00
else
2014-12-16 01:54:15 -05:00
{
gItem - > meta . mPop = 0 ;
gItem - > meta . mVisibleMsgCount = 0 ;
}
2014-05-17 09:50:40 -04:00
grpItem . push_back ( gItem ) ;
}
else
{
std : : cerr < < " RsGenExchange::getGroupData() deserialisation/dynamic_cast ERROR " ;
std : : cerr < < std : : endl ;
delete item ;
}
}
else
{
std : : cerr < < " RsGenExchange::getGroupData() ERROR deserialising item " ;
std : : cerr < < std : : endl ;
}
delete * lit ;
}
}
return ok ;
}
bool RsGenExchange : : getMsgData ( const uint32_t & token , GxsMsgDataMap & msgItems )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
NxsMsgDataResult msgResult ;
bool ok = mDataAccess - > getMsgData ( token , msgResult ) ;
if ( ok )
{
2015-09-08 10:34:22 -04:00
NxsMsgDataResult : : iterator mit = msgResult . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = msgResult . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
const RsGxsGroupId & grpId = mit - > first ;
2015-09-08 10:34:22 -04:00
std : : vector < RsGxsMsgItem * > & gxsMsgItems = msgItems [ grpId ] ;
2014-05-17 09:50:40 -04:00
std : : vector < RsNxsMsg * > & nxsMsgsV = mit - > second ;
std : : vector < RsNxsMsg * > : : iterator vit = nxsMsgsV . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = nxsMsgsV . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
RsNxsMsg * & msg = * vit ;
RsItem * item = NULL ;
if ( msg - > msg . bin_len ! = 0 )
item = mSerialiser - > deserialise ( msg - > msg . bin_data , & msg - > msg . bin_len ) ;
if ( item )
{
RsGxsMsgItem * mItem = dynamic_cast < RsGxsMsgItem * > ( item ) ;
if ( mItem )
{
mItem - > meta = * ( ( * vit ) - > metaData ) ; // get meta info from nxs msg
gxsMsgItems . push_back ( mItem ) ;
}
else
{
std : : cerr < < " RsGenExchange::getMsgData() deserialisation/dynamic_cast ERROR " ;
std : : cerr < < std : : endl ;
delete item ;
}
}
else
{
std : : cerr < < " RsGenExchange::getMsgData() deserialisation ERROR " ;
std : : cerr < < std : : endl ;
}
delete msg ;
}
}
}
return ok ;
}
bool RsGenExchange : : getMsgRelatedData ( const uint32_t & token , GxsMsgRelatedDataMap & msgItems )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
NxsMsgRelatedDataResult msgResult ;
bool ok = mDataAccess - > getMsgRelatedData ( token , msgResult ) ;
if ( ok )
{
NxsMsgRelatedDataResult : : iterator mit = msgResult . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = msgResult . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
const RsGxsGrpMsgIdPair & msgId = mit - > first ;
2015-09-08 10:34:22 -04:00
std : : vector < RsGxsMsgItem * > & gxsMsgItems = msgItems [ msgId ] ;
2014-05-17 09:50:40 -04:00
std : : vector < RsNxsMsg * > & nxsMsgsV = mit - > second ;
2015-09-08 10:34:22 -04:00
std : : vector < RsNxsMsg * > : : iterator vit = nxsMsgsV . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = nxsMsgsV . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
RsNxsMsg * & msg = * vit ;
RsItem * item = NULL ;
if ( msg - > msg . bin_len ! = 0 )
item = mSerialiser - > deserialise ( msg - > msg . bin_data ,
& msg - > msg . bin_len ) ;
if ( item )
{
RsGxsMsgItem * mItem = dynamic_cast < RsGxsMsgItem * > ( item ) ;
if ( mItem )
{
mItem - > meta = * ( ( * vit ) - > metaData ) ; // get meta info from nxs msg
gxsMsgItems . push_back ( mItem ) ;
}
else
{
std : : cerr < < " RsGenExchange::getMsgRelatedData() deserialisation/dynamic_cast ERROR " ;
std : : cerr < < std : : endl ;
delete item ;
}
}
else
{
std : : cerr < < " RsGenExchange::getMsgRelatedData() deserialisation ERROR " ;
std : : cerr < < std : : endl ;
}
delete msg ;
}
}
}
return ok ;
}
RsTokenService * RsGenExchange : : getTokenService ( )
{
return mDataAccess ;
}
bool RsGenExchange : : setAuthenPolicyFlag ( const uint8_t & msgFlag , uint32_t & authenFlag , const PrivacyBitPos & pos )
{
uint32_t temp = 0 ;
temp = msgFlag ;
switch ( pos )
{
case PUBLIC_GRP_BITS :
authenFlag & = ~ PUB_GRP_MASK ;
authenFlag | = temp ;
break ;
case RESTRICTED_GRP_BITS :
authenFlag & = ~ RESTR_GRP_MASK ;
authenFlag | = ( temp < < RESTR_GRP_OFFSET ) ;
break ;
case PRIVATE_GRP_BITS :
authenFlag & = ~ PRIV_GRP_MASK ;
authenFlag | = ( temp < < PRIV_GRP_OFFSET ) ;
break ;
case GRP_OPTION_BITS :
authenFlag & = ~ GRP_OPTIONS_MASK ;
authenFlag | = ( temp < < GRP_OPTIONS_OFFSET ) ;
break ;
default :
std : : cerr < < " pos option not recognised " ;
return false ;
}
return true ;
}
void RsGenExchange : : notifyNewGroups ( std : : vector < RsNxsGrp * > & groups )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
std : : vector < RsNxsGrp * > : : iterator vit = groups . begin ( ) ;
// store these for tick() to pick them up
2014-10-24 18:07:26 -04:00
for ( ; vit ! = groups . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
RsNxsGrp * grp = * vit ;
NxsGrpPendValidVect : : iterator received = std : : find ( mReceivedGrps . begin ( ) ,
mReceivedGrps . end ( ) , grp - > grpId ) ;
// drop group if you already have them
// TODO: move this to nxs layer to save bandwidth
if ( received = = mReceivedGrps . end ( ) )
{
2015-05-29 16:49:37 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::notifyNewGroups() Received GrpId: " < < grp - > grpId ;
std : : cerr < < std : : endl ;
2015-05-29 16:49:37 -04:00
# endif
2014-05-17 09:50:40 -04:00
GxsPendingItem < RsNxsGrp * , RsGxsGroupId > gpsi ( grp , grp - > grpId ) ;
mReceivedGrps . push_back ( gpsi ) ;
}
else
{
delete grp ;
}
}
}
2014-10-05 15:14:05 -04:00
2014-05-17 09:50:40 -04:00
void RsGenExchange : : notifyNewMessages ( std : : vector < RsNxsMsg * > & messages )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
std : : vector < RsNxsMsg * > : : iterator vit = messages . begin ( ) ;
// store these for tick() to pick them up
2014-10-24 18:07:26 -04:00
for ( ; vit ! = messages . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
RsNxsMsg * msg = * vit ;
NxsMsgPendingVect : : iterator it =
std : : find ( mMsgPendingValidate . begin ( ) , mMsgPendingValidate . end ( ) , getMsgIdPair ( * msg ) ) ;
// if we have msg already just delete it
if ( it = = mMsgPendingValidate . end ( ) )
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::notifyNewMessages() Received Msg: " ;
std : : cerr < < " GrpId: " < < msg - > grpId ;
std : : cerr < < " MsgId: " < < msg - > msgId ;
std : : cerr < < std : : endl ;
# endif
mReceivedMsgs . push_back ( msg ) ;
}
else
{
delete msg ;
}
}
}
2015-02-07 20:01:48 -05:00
void RsGenExchange : : notifyReceivePublishKey ( const RsGxsGroupId & grpId )
{
RS_STACK_MUTEX ( mGenMtx ) ;
RsGxsGroupChange * gc = new RsGxsGroupChange ( RsGxsNotify : : TYPE_PUBLISHKEY , false ) ;
gc - > mGrpIdList . push_back ( grpId ) ;
mNotifications . push_back ( gc ) ;
}
2014-05-17 09:50:40 -04:00
2015-05-19 17:40:19 -04:00
void RsGenExchange : : notifyChangedGroupStats ( const RsGxsGroupId & grpId )
{
RS_STACK_MUTEX ( mGenMtx ) ;
RsGxsGroupChange * gc = new RsGxsGroupChange ( RsGxsNotify : : TYPE_PROCESSED , false ) ;
gc - > mGrpIdList . push_back ( grpId ) ;
mNotifications . push_back ( gc ) ;
}
2014-05-17 09:50:40 -04:00
void RsGenExchange : : publishGroup ( uint32_t & token , RsGxsGrpItem * grpItem )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
GxsGrpPendingSign ggps ( grpItem , token ) ;
mGrpsToPublish . push_back ( ggps ) ;
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishGroup() token: " < < token ;
std : : cerr < < std : : endl ;
# endif
}
void RsGenExchange : : updateGroup ( uint32_t & token , RsGxsGrpItem * grpItem )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
mGroupUpdatePublish . push_back ( GroupUpdatePublish ( grpItem , token ) ) ;
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::updateGroup() token: " < < token ;
std : : cerr < < std : : endl ;
# endif
}
void RsGenExchange : : deleteGroup ( uint32_t & token , RsGxsGrpItem * grpItem )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
mGroupDeletePublish . push_back ( GroupDeletePublish ( grpItem , token ) ) ;
# ifdef GEN_EXCH_DEBUG
2015-01-31 13:06:37 -05:00
std : : cerr < < " RsGenExchange::deleteGroup() token: " < < token ;
2014-05-17 09:50:40 -04:00
std : : cerr < < std : : endl ;
# endif
}
void RsGenExchange : : publishMsg ( uint32_t & token , RsGxsMsgItem * msgItem )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
mMsgsToPublish . insert ( std : : make_pair ( token , msgItem ) ) ;
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishMsg() token: " < < token ;
std : : cerr < < std : : endl ;
# endif
}
void RsGenExchange : : setGroupSubscribeFlags ( uint32_t & token , const RsGxsGroupId & grpId , const uint32_t & flag , const uint32_t & mask )
{
/* TODO APPLY MASK TO FLAGS */
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
GrpLocMetaData g ;
g . grpId = grpId ;
g . val . put ( RsGeneralDataService : : GRP_META_SUBSCRIBE_FLAG , ( int32_t ) flag ) ;
g . val . put ( RsGeneralDataService : : GRP_META_SUBSCRIBE_FLAG + GXS_MASK , ( int32_t ) mask ) ; // HACK, need to perform mask operation in a non-blocking location
mGrpLocMetaMap . insert ( std : : make_pair ( token , g ) ) ;
}
void RsGenExchange : : setGroupStatusFlags ( uint32_t & token , const RsGxsGroupId & grpId , const uint32_t & status , const uint32_t & mask )
{
/* TODO APPLY MASK TO FLAGS */
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
GrpLocMetaData g ;
g . grpId = grpId ;
g . val . put ( RsGeneralDataService : : GRP_META_STATUS , ( int32_t ) status ) ;
g . val . put ( RsGeneralDataService : : GRP_META_STATUS + GXS_MASK , ( int32_t ) mask ) ; // HACK, need to perform mask operation in a non-blocking location
mGrpLocMetaMap . insert ( std : : make_pair ( token , g ) ) ;
}
void RsGenExchange : : setGroupServiceString ( uint32_t & token , const RsGxsGroupId & grpId , const std : : string & servString )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
GrpLocMetaData g ;
g . grpId = grpId ;
g . val . put ( RsGeneralDataService : : GRP_META_SERV_STRING , servString ) ;
mGrpLocMetaMap . insert ( std : : make_pair ( token , g ) ) ;
}
void RsGenExchange : : setMsgStatusFlags ( uint32_t & token , const RsGxsGrpMsgIdPair & msgId , const uint32_t & status , const uint32_t & mask )
{
/* TODO APPLY MASK TO FLAGS */
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
MsgLocMetaData m ;
m . val . put ( RsGeneralDataService : : MSG_META_STATUS , ( int32_t ) status ) ;
m . val . put ( RsGeneralDataService : : MSG_META_STATUS + GXS_MASK , ( int32_t ) mask ) ; // HACK, need to perform mask operation in a non-blocking location
m . msgId = msgId ;
mMsgLocMetaMap . insert ( std : : make_pair ( token , m ) ) ;
}
void RsGenExchange : : setMsgServiceString ( uint32_t & token , const RsGxsGrpMsgIdPair & msgId , const std : : string & servString )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
MsgLocMetaData m ;
m . val . put ( RsGeneralDataService : : MSG_META_SERV_STRING , servString ) ;
m . msgId = msgId ;
mMsgLocMetaMap . insert ( std : : make_pair ( token , m ) ) ;
}
void RsGenExchange : : processMsgMetaChanges ( )
{
2015-03-08 19:12:57 -04:00
std : : map < uint32_t , MsgLocMetaData > metaMap ;
2014-05-17 09:50:40 -04:00
2015-03-08 19:12:57 -04:00
{
RS_STACK_MUTEX ( mGenMtx ) ;
if ( mMsgLocMetaMap . empty ( ) )
{
return ;
}
metaMap = mMsgLocMetaMap ;
mMsgLocMetaMap . clear ( ) ;
}
2014-07-04 17:51:17 -04:00
2015-03-08 19:12:57 -04:00
GxsMsgReq msgIds ;
2014-05-17 09:50:40 -04:00
2015-03-08 19:12:57 -04:00
std : : map < uint32_t , MsgLocMetaData > : : iterator mit ;
for ( mit = metaMap . begin ( ) ; mit ! = metaMap . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
MsgLocMetaData & m = mit - > second ;
int32_t value , mask ;
bool ok = true ;
2014-07-04 17:51:17 -04:00
bool changed = false ;
2014-05-17 09:50:40 -04:00
// for meta flag changes get flag to apply mask
if ( m . val . getAsInt32 ( RsGeneralDataService : : MSG_META_STATUS , value ) )
{
ok = false ;
if ( m . val . getAsInt32 ( RsGeneralDataService : : MSG_META_STATUS + GXS_MASK , mask ) )
{
GxsMsgReq req ;
std : : vector < RsGxsMessageId > msgIdV ;
msgIdV . push_back ( m . msgId . second ) ;
req . insert ( std : : make_pair ( m . msgId . first , msgIdV ) ) ;
GxsMsgMetaResult result ;
mDataStore - > retrieveGxsMsgMetaData ( req , result ) ;
GxsMsgMetaResult : : iterator mit = result . find ( m . msgId . first ) ;
if ( mit ! = result . end ( ) )
{
std : : vector < RsGxsMsgMetaData * > & msgMetaV = mit - > second ;
if ( ! msgMetaV . empty ( ) )
{
RsGxsMsgMetaData * meta = * ( msgMetaV . begin ( ) ) ;
value = ( meta - > mMsgStatus & ~ mask ) | ( mask & value ) ;
2014-07-04 17:51:17 -04:00
changed = ( meta - > mMsgStatus ! = value ) ;
2014-05-17 09:50:40 -04:00
m . val . put ( RsGeneralDataService : : MSG_META_STATUS , value ) ;
delete meta ;
ok = true ;
}
}
m . val . removeKeyValue ( RsGeneralDataService : : MSG_META_STATUS + GXS_MASK ) ;
}
}
ok & = mDataStore - > updateMessageMetaData ( m ) = = 1 ;
uint32_t token = mit - > first ;
if ( ok )
{
mDataAccess - > updatePublicRequestStatus ( token , RsTokenService : : GXS_REQUEST_V2_STATUS_COMPLETE ) ;
2014-07-04 17:51:17 -04:00
if ( changed )
{
msgIds [ m . msgId . first ] . push_back ( m . msgId . second ) ;
}
}
else
2014-05-17 09:50:40 -04:00
{
mDataAccess - > updatePublicRequestStatus ( token , RsTokenService : : GXS_REQUEST_V2_STATUS_FAILED ) ;
}
2015-03-08 19:12:57 -04:00
{
RS_STACK_MUTEX ( mGenMtx ) ;
mMsgNotify . insert ( std : : make_pair ( token , m . msgId ) ) ;
}
2014-05-17 09:50:40 -04:00
}
2014-07-04 17:51:17 -04:00
if ( ! msgIds . empty ( ) ) {
2015-03-08 19:12:57 -04:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-07-04 17:51:17 -04:00
RsGxsMsgChange * c = new RsGxsMsgChange ( RsGxsNotify : : TYPE_PROCESSED , true ) ;
c - > msgChangeMap = msgIds ;
mNotifications . push_back ( c ) ;
}
2014-05-17 09:50:40 -04:00
}
void RsGenExchange : : processGrpMetaChanges ( )
{
2015-03-08 19:12:57 -04:00
std : : map < uint32_t , GrpLocMetaData > metaMap ;
2014-05-17 09:50:40 -04:00
2015-03-08 19:12:57 -04:00
{
RS_STACK_MUTEX ( mGenMtx ) ;
if ( mGrpLocMetaMap . empty ( ) )
{
return ;
}
metaMap = mGrpLocMetaMap ;
mGrpLocMetaMap . clear ( ) ;
}
2014-07-04 17:51:17 -04:00
2015-03-08 19:12:57 -04:00
std : : list < RsGxsGroupId > grpChanged ;
2014-05-17 09:50:40 -04:00
2015-03-08 19:12:57 -04:00
std : : map < uint32_t , GrpLocMetaData > : : iterator mit ;
for ( mit = metaMap . begin ( ) ; mit ! = metaMap . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
GrpLocMetaData & g = mit - > second ;
uint32_t token = mit - > first ;
// process mask
bool ok = processGrpMask ( g . grpId , g . val ) ;
2015-08-27 15:11:24 -04:00
ok = ok & & ( mDataStore - > updateGroupMetaData ( g ) = = 1 ) ;
2014-05-17 09:50:40 -04:00
if ( ok )
{
mDataAccess - > updatePublicRequestStatus ( token , RsTokenService : : GXS_REQUEST_V2_STATUS_COMPLETE ) ;
2014-07-04 17:51:17 -04:00
grpChanged . push_back ( g . grpId ) ;
2014-05-17 09:50:40 -04:00
} else
{
mDataAccess - > updatePublicRequestStatus ( token , RsTokenService : : GXS_REQUEST_V2_STATUS_FAILED ) ;
}
2015-03-08 19:12:57 -04:00
{
RS_STACK_MUTEX ( mGenMtx ) ;
mGrpNotify . insert ( std : : make_pair ( token , g . grpId ) ) ;
}
2014-05-17 09:50:40 -04:00
}
2014-07-04 17:51:17 -04:00
if ( ! grpChanged . empty ( ) )
{
2015-03-08 19:12:57 -04:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-07-04 17:51:17 -04:00
RsGxsGroupChange * gc = new RsGxsGroupChange ( RsGxsNotify : : TYPE_PROCESSED , true ) ;
gc - > mGrpIdList = grpChanged ;
mNotifications . push_back ( gc ) ;
}
2014-05-17 09:50:40 -04:00
}
bool RsGenExchange : : processGrpMask ( const RsGxsGroupId & grpId , ContentValue & grpCv )
{
// first find out which mask is involved
int32_t value , mask , currValue ;
std : : string key ;
RsGxsGrpMetaData * grpMeta = NULL ;
bool ok = false ;
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > grpMetaMap ;
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > : : iterator mit ;
grpMetaMap . insert ( std : : make_pair ( grpId , ( RsGxsGrpMetaData * ) ( NULL ) ) ) ;
mDataStore - > retrieveGxsGrpMetaData ( grpMetaMap ) ;
if ( ( mit = grpMetaMap . find ( grpId ) ) ! = grpMetaMap . end ( ) )
{
grpMeta = mit - > second ;
2015-08-27 15:11:24 -04:00
if ( ! grpMeta )
{
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2015-08-27 15:11:24 -04:00
std : : cerr < < " RsGenExchange::processGrpMask() Ignore update for not existing grp id " < < grpId . toStdString ( ) ;
std : : cerr < < std : : endl ;
2015-10-24 12:55:49 -04:00
# endif
2015-08-27 15:11:24 -04:00
return false ;
}
2014-05-17 09:50:40 -04:00
ok = true ;
}
if ( grpCv . getAsInt32 ( RsGeneralDataService : : GRP_META_STATUS , value ) & & grpMeta )
{
key = RsGeneralDataService : : GRP_META_STATUS ;
currValue = grpMeta - > mGroupStatus ;
}
else if ( grpCv . getAsInt32 ( RsGeneralDataService : : GRP_META_SUBSCRIBE_FLAG , value ) & & grpMeta )
{
key = RsGeneralDataService : : GRP_META_SUBSCRIBE_FLAG ;
currValue = grpMeta - > mSubscribeFlags ;
} else
{
if ( grpMeta )
delete grpMeta ;
2014-06-03 17:49:41 -04:00
return ! ( grpCv . empty ( ) ) ;
2014-05-17 09:50:40 -04:00
}
ok & = grpCv . getAsInt32 ( key + GXS_MASK , mask ) ;
// remove mask entry so it doesn't affect actual entry
grpCv . removeKeyValue ( key + GXS_MASK ) ;
// apply mask to current value
value = ( currValue & ~ mask ) | ( value & mask ) ;
grpCv . put ( key , value ) ;
if ( grpMeta )
delete grpMeta ;
return ok ;
}
void RsGenExchange : : publishMsgs ( )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
// stick back msgs pending signature
typedef std : : map < uint32_t , GxsPendingItem < RsGxsMsgItem * , uint32_t > > PendSignMap ;
PendSignMap : : iterator sign_it = mMsgPendingSign . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; sign_it ! = mMsgPendingSign . end ( ) ; + + sign_it )
2014-05-17 09:50:40 -04:00
{
GxsPendingItem < RsGxsMsgItem * , uint32_t > & item = sign_it - > second ;
mMsgsToPublish . insert ( std : : make_pair ( sign_it - > first , item . mItem ) ) ;
}
std : : map < RsGxsGroupId , std : : vector < RsGxsMessageId > > msgChangeMap ;
std : : map < uint32_t , RsGxsMsgItem * > : : iterator mit = mMsgsToPublish . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = mMsgsToPublish . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishMsgs() Publishing a Message " ;
std : : cerr < < std : : endl ;
# endif
RsGxsMsgItem * msgItem = mit - > second ;
const uint32_t & token = mit - > first ;
uint32_t size = mSerialiser - > size ( msgItem ) ;
char * mData = new char [ size ] ;
bool serialOk = false ;
// for fatal sign creation
bool createOk = false ;
// if sign requests to try later
bool tryLater = false ;
serialOk = mSerialiser - > serialise ( msgItem , mData , & size ) ;
if ( serialOk )
{
2015-06-14 19:04:54 -04:00
RsNxsMsg * msg = new RsNxsMsg ( mServType ) ;
msg - > grpId = msgItem - > meta . mGroupId ;
2014-05-17 09:50:40 -04:00
msg - > msg . setBinData ( mData , size ) ;
// now create meta
msg - > metaData = new RsGxsMsgMetaData ( ) ;
* ( msg - > metaData ) = msgItem - > meta ;
// assign time stamp
msg - > metaData - > mPublishTs = time ( NULL ) ;
// now intialise msg (sign it)
uint8_t createReturn = createMessage ( msg ) ;
if ( createReturn = = CREATE_FAIL )
{
createOk = false ;
}
else if ( createReturn = = CREATE_FAIL_TRY_LATER )
{
PendSignMap : : iterator pit = mMsgPendingSign . find ( token ) ;
tryLater = true ;
// add to queue of messages waiting for a successful
// sign attempt
if ( pit = = mMsgPendingSign . end ( ) )
{
GxsPendingItem < RsGxsMsgItem * , uint32_t > gsi ( msgItem , token ) ;
mMsgPendingSign . insert ( std : : make_pair ( token , gsi ) ) ;
}
else
{
// remove from attempts queue if over sign
// attempts limit
if ( pit - > second . mAttempts = = SIGN_MAX_ATTEMPTS )
{
mMsgPendingSign . erase ( token ) ;
tryLater = false ;
}
else
{
2014-10-24 18:07:26 -04:00
+ + pit - > second . mAttempts ;
2014-05-17 09:50:40 -04:00
}
}
createOk = false ;
}
else if ( createReturn = = CREATE_SUCCESS )
{
createOk = true ;
// erase from queue if it exists
mMsgPendingSign . erase ( token ) ;
}
else // unknown return, just fail
createOk = false ;
RsGxsMessageId msgId ;
RsGxsGroupId grpId = msgItem - > meta . mGroupId ;
bool validSize = false ;
// check message not over single msg storage limit
if ( createOk )
{
validSize = mDataStore - > validSize ( msg ) ;
}
if ( createOk & & validSize )
{
// empty orig msg id means this is the original
// msg
if ( msg - > metaData - > mOrigMsgId . isNull ( ) )
{
msg - > metaData - > mOrigMsgId = msg - > metaData - > mMsgId ;
}
// now serialise meta data
size = msg - > metaData - > serial_size ( ) ;
char * metaDataBuff = new char [ size ] ;
bool s = msg - > metaData - > serialise ( metaDataBuff , & size ) ;
s & = msg - > meta . setBinData ( metaDataBuff , size ) ;
2014-10-12 11:53:23 -04:00
msg - > metaData - > mMsgStatus = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
2014-05-17 09:50:40 -04:00
msgId = msg - > msgId ;
grpId = msg - > grpId ;
msg - > metaData - > recvTS = time ( NULL ) ;
2015-10-25 17:16:16 -04:00
mRoutingClues [ msg - > metaData - > mAuthorId ] . insert ( rsPeers - > getOwnId ( ) ) ;
mTrackingClues . push_back ( std : : make_pair ( msg - > msgId , rsPeers - > getOwnId ( ) ) ) ;
2014-05-17 09:50:40 -04:00
computeHash ( msg - > msg , msg - > metaData - > mHash ) ;
mDataAccess - > addMsgData ( msg ) ;
msgChangeMap [ grpId ] . push_back ( msgId ) ;
delete [ ] metaDataBuff ;
// add to published to allow acknowledgement
mMsgNotify . insert ( std : : make_pair ( mit - > first , std : : make_pair ( grpId , msgId ) ) ) ;
mDataAccess - > updatePublicRequestStatus ( mit - > first , RsTokenService : : GXS_REQUEST_V2_STATUS_COMPLETE ) ;
}
else
{
// delete msg if create msg not ok
delete msg ;
if ( ! tryLater )
mDataAccess - > updatePublicRequestStatus ( mit - > first ,
RsTokenService : : GXS_REQUEST_V2_STATUS_FAILED ) ;
std : : cerr < < " RsGenExchange::publishMsgs() failed to publish msg " < < std : : endl ;
}
}
else
{
std : : cerr < < " RsGenExchange::publishMsgs() failed to serialise msg " < < std : : endl ;
}
2014-05-06 13:15:20 -04:00
2014-05-17 09:50:40 -04:00
delete [ ] mData ;
2014-05-06 13:15:20 -04:00
2014-05-17 09:50:40 -04:00
if ( ! tryLater )
delete msgItem ;
}
2014-05-06 13:15:20 -04:00
2014-05-17 09:50:40 -04:00
// clear msg item map as we're done publishing them and all
// entries are invalid
mMsgsToPublish . clear ( ) ;
2014-05-06 13:15:20 -04:00
2014-05-17 09:50:40 -04:00
if ( ! msgChangeMap . empty ( ) )
{
2014-07-04 17:51:17 -04:00
RsGxsMsgChange * ch = new RsGxsMsgChange ( RsGxsNotify : : TYPE_PUBLISH , false ) ;
2014-05-17 09:50:40 -04:00
ch - > msgChangeMap = msgChangeMap ;
mNotifications . push_back ( ch ) ;
}
2014-05-06 13:15:20 -04:00
}
2014-05-17 09:50:40 -04:00
RsGenExchange : : ServiceCreate_Return RsGenExchange : : service_CreateGroup ( RsGxsGrpItem * /* grpItem */ ,
RsTlvSecurityKeySet & /* keySet */ )
2014-05-06 13:15:20 -04:00
{
2014-05-17 09:50:40 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::service_CreateGroup(): Does nothing "
< < std : : endl ;
2014-05-06 13:15:20 -04:00
# endif
2014-05-17 09:50:40 -04:00
return SERVICE_CREATE_SUCCESS ;
2014-05-06 13:15:20 -04:00
}
2014-05-17 09:50:40 -04:00
# define PENDING_SIGN_TIMEOUT 10 // 5 seconds
void RsGenExchange : : processGroupUpdatePublish ( )
2014-05-06 13:15:20 -04:00
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-06 13:15:20 -04:00
2014-05-17 09:50:40 -04:00
// get keys for group update publish
// first build meta request map for groups to be updated
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > grpMeta ;
std : : vector < GroupUpdatePublish > : : iterator vit = mGroupUpdatePublish . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = mGroupUpdatePublish . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
GroupUpdatePublish & gup = * vit ;
const RsGxsGroupId & groupId = gup . grpItem - > meta . mGroupId ;
grpMeta . insert ( std : : make_pair ( groupId , ( RsGxsGrpMetaData * ) ( NULL ) ) ) ;
}
if ( grpMeta . empty ( ) )
return ;
mDataStore - > retrieveGxsGrpMetaData ( grpMeta ) ;
// now
vit = mGroupUpdatePublish . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = mGroupUpdatePublish . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
GroupUpdatePublish & gup = * vit ;
const RsGxsGroupId & groupId = gup . grpItem - > meta . mGroupId ;
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > : : iterator mit = grpMeta . find ( groupId ) ;
RsGxsGrpMetaData * meta = NULL ;
if ( mit = = grpMeta . end ( ) | | mit - > second = = NULL )
{
std : : cerr < < " Error! could not find meta of old group to update! " < < std : : endl ;
mDataAccess - > updatePublicRequestStatus ( gup . mToken , RsTokenService : : GXS_REQUEST_V2_STATUS_FAILED ) ;
delete gup . grpItem ;
continue ;
} else
{
meta = mit - > second ;
}
//gup.grpItem->meta = *meta;
2015-06-14 11:08:04 -04:00
GxsGrpPendingSign ggps ( gup . grpItem , gup . mToken ) ;
2014-05-17 09:50:40 -04:00
bool publishAndAdminPrivatePresent = checkKeys ( meta - > keys ) ;
if ( publishAndAdminPrivatePresent )
{
ggps . mPrivateKeys = meta - > keys ;
generatePublicFromPrivateKeys ( ggps . mPrivateKeys , ggps . mPublicKeys ) ;
ggps . mHaveKeys = true ;
ggps . mStartTS = time ( NULL ) ;
ggps . mLastAttemptTS = 0 ;
ggps . mIsUpdate = true ;
ggps . mToken = gup . mToken ;
mGrpsToPublish . push_back ( ggps ) ;
} else
{
delete gup . grpItem ;
mDataAccess - > updatePublicRequestStatus ( gup . mToken , RsTokenService : : GXS_REQUEST_V2_STATUS_FAILED ) ;
}
delete meta ;
}
2014-05-06 13:15:20 -04:00
mGroupUpdatePublish . clear ( ) ;
}
2014-10-05 15:14:05 -04:00
2014-10-22 17:00:20 -04:00
void RsGenExchange : : processRoutingClues ( )
{
2015-10-25 17:16:16 -04:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-10-22 17:00:20 -04:00
for ( std : : map < RsGxsId , std : : set < RsPeerId > > : : const_iterator it = mRoutingClues . begin ( ) ; it ! = mRoutingClues . end ( ) ; + + it )
for ( std : : set < RsPeerId > : : const_iterator it2 ( it - > second . begin ( ) ) ; it2 ! = it - > second . end ( ) ; + + it2 )
2015-10-25 17:16:16 -04:00
rsGRouter - > addRoutingClue ( GRouterKeyId ( it - > first ) , ( * it2 ) ) ;
2014-10-22 17:00:20 -04:00
mRoutingClues . clear ( ) ;
2015-10-25 17:16:16 -04:00
for ( std : : list < std : : pair < RsGxsMessageId , RsPeerId > > : : const_iterator it = mTrackingClues . begin ( ) ; it ! = mTrackingClues . end ( ) ; + + it )
rsGRouter - > addTrackingInfo ( ( * it ) . first , ( * it ) . second ) ;
mTrackingClues . clear ( ) ;
2014-10-22 17:00:20 -04:00
}
2014-05-06 13:15:20 -04:00
void RsGenExchange : : processGroupDelete ( )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-06 13:15:20 -04:00
2014-10-05 15:14:05 -04:00
// get keys for group delete publish
2014-05-06 13:15:20 -04:00
typedef std : : pair < bool , RsGxsGroupId > GrpNote ;
std : : map < uint32_t , GrpNote > toNotify ;
std : : vector < GroupDeletePublish > : : iterator vit = mGroupDeletePublish . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = mGroupDeletePublish . end ( ) ; + + vit )
2014-05-06 13:15:20 -04:00
{
GroupDeletePublish & gdp = * vit ;
uint32_t token = gdp . mToken ;
const RsGxsGroupId & groupId = gdp . grpItem - > meta . mGroupId ;
std : : vector < RsGxsGroupId > gprIds ;
gprIds . push_back ( groupId ) ;
mDataStore - > removeGroups ( gprIds ) ;
toNotify . insert ( std : : make_pair (
2015-08-27 16:21:01 -04:00
token , GrpNote ( true , groupId ) ) ) ;
2014-05-06 13:15:20 -04:00
}
std : : list < RsGxsGroupId > grpDeleted ;
std : : map < uint32_t , GrpNote > : : iterator mit = toNotify . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = toNotify . end ( ) ; + + mit )
2014-05-06 13:15:20 -04:00
{
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 ( ) )
{
2014-07-04 17:51:17 -04:00
RsGxsGroupChange * gc = new RsGxsGroupChange ( RsGxsNotify : : TYPE_PUBLISH , false ) ;
2014-05-06 13:15:20 -04:00
gc - > mGrpIdList = grpDeleted ;
mNotifications . push_back ( gc ) ;
}
mGroupDeletePublish . clear ( ) ;
}
bool RsGenExchange : : checkKeys ( const RsTlvSecurityKeySet & keySet )
{
2014-06-12 06:28:23 -04:00
typedef std : : map < RsGxsId , RsTlvSecurityKey > keyMap ;
2014-05-17 09:50:40 -04:00
const keyMap & allKeys = keySet . keys ;
keyMap : : const_iterator cit = allKeys . begin ( ) ;
bool adminFound = false , publishFound = false ;
2014-10-24 18:07:26 -04:00
for ( ; cit ! = allKeys . end ( ) ; + + cit )
2014-05-17 09:50:40 -04:00
{
const RsTlvSecurityKey & key = cit - > second ;
if ( key . keyFlags & RSTLV_KEY_TYPE_FULL )
{
if ( key . keyFlags & RSTLV_KEY_DISTRIB_ADMIN )
adminFound = true ;
2015-05-19 17:28:46 -04:00
if ( key . keyFlags & RSTLV_KEY_DISTRIB_PUBLISH )
2014-05-17 09:50:40 -04:00
publishFound = true ;
}
}
// user must have both private and public parts of publish and admin keys
return adminFound & & publishFound ;
}
void RsGenExchange : : publishGrps ( )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
NxsGrpSignPendVect : : iterator vit = mGrpsToPublish . begin ( ) ;
typedef std : : pair < bool , RsGxsGroupId > GrpNote ;
std : : map < uint32_t , GrpNote > toNotify ;
while ( vit ! = mGrpsToPublish . end ( ) )
{
GxsGrpPendingSign & ggps = * vit ;
/* do intial checks to see if this entry has expired */
time_t now = time ( NULL ) ;
uint32_t token = ggps . mToken ;
if ( now > ( ggps . mStartTS + PENDING_SIGN_TIMEOUT ) )
{
// timed out
toNotify . insert ( std : : make_pair (
token , GrpNote ( false , RsGxsGroupId ( ) ) ) ) ;
delete ggps . mItem ;
vit = mGrpsToPublish . erase ( vit ) ;
continue ;
}
RsGxsGroupId grpId ;
RsNxsGrp * grp = new RsNxsGrp ( mServType ) ;
RsGxsGrpItem * grpItem = ggps . mItem ;
RsTlvSecurityKeySet privatekeySet , publicKeySet ;
if ( ! ( ggps . mHaveKeys ) )
{
generateGroupKeys ( privatekeySet , publicKeySet , true ) ;
ggps . mHaveKeys = true ;
ggps . mPrivateKeys = privatekeySet ;
ggps . mPublicKeys = publicKeySet ;
}
else
{
privatekeySet = ggps . mPrivateKeys ;
publicKeySet = ggps . mPublicKeys ;
}
// find private admin key
RsTlvSecurityKey privAdminKey ;
2014-06-12 06:28:23 -04:00
std : : map < RsGxsId , RsTlvSecurityKey > : : iterator mit_keys = privatekeySet . keys . begin ( ) ;
2014-05-17 09:50:40 -04:00
bool privKeyFound = false ;
2014-10-24 18:07:26 -04:00
for ( ; mit_keys ! = privatekeySet . keys . end ( ) ; + + mit_keys )
2014-05-17 09:50:40 -04:00
{
RsTlvSecurityKey & key = mit_keys - > second ;
if ( key . keyFlags = = ( RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL ) )
{
privAdminKey = key ;
privKeyFound = true ;
}
}
uint8_t create = CREATE_FAIL ;
if ( privKeyFound )
{
// get group id from private admin key id
grpItem - > meta . mGroupId = grp - > grpId = RsGxsGroupId ( privAdminKey . keyId ) ;
ServiceCreate_Return ret = service_CreateGroup ( grpItem , privatekeySet ) ;
bool serialOk = false , servCreateOk ;
if ( ret = = SERVICE_CREATE_SUCCESS )
{
uint32_t size = mSerialiser - > size ( grpItem ) ;
char * gData = new char [ size ] ;
serialOk = mSerialiser - > serialise ( grpItem , gData , & size ) ;
grp - > grp . setBinData ( gData , size ) ;
delete [ ] gData ;
servCreateOk = true ;
} else
{
servCreateOk = false ;
}
if ( serialOk & & servCreateOk )
{
grp - > metaData = new RsGxsGrpMetaData ( ) ;
grpItem - > meta . mPublishTs = time ( NULL ) ;
//grpItem->meta.mParentGrpId = std::string("empty");
* ( grp - > metaData ) = grpItem - > meta ;
// TODO: change when publish key optimisation added (public groups don't have publish key
grp - > metaData - > mSubscribeFlags = GXS_SERV : : GROUP_SUBSCRIBE_ADMIN | GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED
| GXS_SERV : : GROUP_SUBSCRIBE_PUBLISH ;
create = createGroup ( grp , privatekeySet , publicKeySet ) ;
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishGrps() " ;
std : : cerr < < " GrpId: " < < grp - > grpId ;
std : : cerr < < " CircleType: " < < ( uint32_t ) grp - > metaData - > mCircleType ;
std : : cerr < < " CircleId: " < < grp - > metaData - > mCircleId . toStdString ( ) ;
std : : cerr < < std : : endl ;
# endif
if ( create = = CREATE_SUCCESS )
{
uint32_t mdSize = grp - > metaData - > serial_size ( ) ;
char * metaData = new char [ mdSize ] ;
serialOk = grp - > metaData - > serialise ( metaData , mdSize ) ;
grp - > meta . setBinData ( metaData , mdSize ) ;
delete [ ] metaData ;
// place back private keys for publisher
grp - > metaData - > keys = privatekeySet ;
if ( mDataStore - > validSize ( grp ) & & serialOk )
{
grpId = grp - > grpId ;
computeHash ( grp - > grp , grp - > metaData - > mHash ) ;
grp - > metaData - > mRecvTS = time ( NULL ) ;
if ( ggps . mIsUpdate )
mDataAccess - > updateGroupData ( grp ) ;
else
mDataAccess - > addGroupData ( grp ) ;
}
else
{
create = CREATE_FAIL ;
}
}
}
else if ( ret = = SERVICE_CREATE_FAIL_TRY_LATER )
{
2015-10-25 09:50:28 -04:00
// if the service is not ready yet, reset the start timestamp to give the service more time
// the service should have it's own timeout mechanism
// services should return SERVICE_CREATE_FAIL if the action timed out
// at the moment this is only important for the idservice:
// the idservice may ask the user for a password, and the user needs time
ggps . mStartTS = now ;
2014-05-17 09:50:40 -04:00
create = CREATE_FAIL_TRY_LATER ;
}
2015-06-12 17:04:11 -04:00
else if ( ret = = SERVICE_CREATE_FAIL )
create = CREATE_FAIL ;
2014-05-17 09:50:40 -04:00
}
else
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishGrps() Could not find private publish keys " < < std : : endl ;
# endif
create = CREATE_FAIL ;
}
if ( create = = CREATE_FAIL )
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishGrps() failed to publish grp " < < std : : endl ;
# endif
delete grp ;
delete grpItem ;
vit = mGrpsToPublish . erase ( vit ) ;
toNotify . insert ( std : : make_pair (
token , GrpNote ( false , grpId ) ) ) ;
}
else if ( create = = CREATE_FAIL_TRY_LATER )
{
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishGrps() failed grp, trying again " < < std : : endl ;
# endif
2015-06-14 19:14:13 -04:00
delete grp ;
2014-05-17 09:50:40 -04:00
ggps . mLastAttemptTS = time ( NULL ) ;
2014-10-24 18:07:26 -04:00
+ + vit ;
2014-05-17 09:50:40 -04:00
}
else if ( create = = CREATE_SUCCESS )
{
delete grpItem ;
vit = mGrpsToPublish . erase ( vit ) ;
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::publishGrps() ok -> pushing to notifies "
< < std : : endl ;
# endif
// add to published to allow acknowledgement
toNotify . insert ( std : : make_pair ( token ,
GrpNote ( true , grpId ) ) ) ;
}
}
std : : map < uint32_t , GrpNote > : : iterator mit = toNotify . begin ( ) ;
std : : list < RsGxsGroupId > grpChanged ;
2014-10-24 18:07:26 -04:00
for ( ; mit ! = toNotify . end ( ) ; + + mit )
2014-05-17 09:50:40 -04:00
{
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 )
grpChanged . push_back ( note . second ) ;
}
if ( ! grpChanged . empty ( ) )
{
2014-07-04 17:51:17 -04:00
RsGxsGroupChange * gc = new RsGxsGroupChange ( RsGxsNotify : : TYPE_PUBLISH , false ) ;
2014-05-17 09:50:40 -04:00
gc - > mGrpIdList = grpChanged ;
mNotifications . push_back ( gc ) ;
}
}
uint32_t RsGenExchange : : generatePublicToken ( )
{
return mDataAccess - > generatePublicToken ( ) ;
}
bool RsGenExchange : : updatePublicRequestStatus ( const uint32_t & token , const uint32_t & status )
{
return mDataAccess - > updatePublicRequestStatus ( token , status ) ;
}
bool RsGenExchange : : disposeOfPublicToken ( const uint32_t & token )
{
return mDataAccess - > disposeOfPublicToken ( token ) ;
}
RsGeneralDataService * RsGenExchange : : getDataStore ( )
{
return mDataStore ;
}
bool RsGenExchange : : getGroupKeys ( const RsGxsGroupId & grpId , RsTlvSecurityKeySet & keySet )
{
if ( grpId . isNull ( ) )
return false ;
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > grpMeta ;
grpMeta [ grpId ] = NULL ;
mDataStore - > retrieveGxsGrpMetaData ( grpMeta ) ;
if ( grpMeta . empty ( ) )
return false ;
RsGxsGrpMetaData * meta = grpMeta [ grpId ] ;
if ( meta = = NULL )
return false ;
keySet = meta - > keys ;
2014-11-11 12:10:16 -05:00
for ( std : : map < RsGxsGroupId , RsGxsGrpMetaData * > : : iterator it = grpMeta . begin ( ) ; it ! = grpMeta . end ( ) ; + + it )
delete it - > second ;
2014-05-17 09:50:40 -04:00
return true ;
}
2015-04-17 17:36:22 -04:00
void RsGenExchange : : shareGroupPublishKey ( const RsGxsGroupId & grpId , const std : : set < RsPeerId > & peers )
2014-10-05 15:14:05 -04:00
{
if ( grpId . isNull ( ) )
return ;
mNetService - > sharePublishKey ( grpId , peers ) ;
}
2014-05-17 09:50:40 -04:00
void RsGenExchange : : processRecvdData ( )
{
processRecvdGroups ( ) ;
processRecvdMessages ( ) ;
performUpdateValidation ( ) ;
2014-10-05 15:14:05 -04:00
2014-05-17 09:50:40 -04:00
}
void RsGenExchange : : computeHash ( const RsTlvBinaryData & data , RsFileHash & hash )
{
pqihash pHash ;
pHash . addData ( data . bin_data , data . bin_len ) ;
pHash . Complete ( hash ) ;
}
void RsGenExchange : : processRecvdMessages ( )
{
2015-10-25 18:27:15 -04:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
if ( ! mMsgPendingValidate . empty ( ) )
std : : cerr < < " processing received messages " < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
NxsMsgPendingVect : : iterator pend_it = mMsgPendingValidate . begin ( ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
if ( ! mMsgPendingValidate . empty ( ) )
std : : cerr < < " pending validation " < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
for ( ; pend_it ! = mMsgPendingValidate . end ( ) ; )
{
GxsPendingItem < RsNxsMsg * , RsGxsGrpMsgIdPair > & gpsi = * pend_it ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " grp= " < < gpsi . mId . first < < " , msg= " < < gpsi . mId . second < < " , attempts= " < < gpsi . mAttempts ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
if ( gpsi . mAttempts = = VALIDATE_MAX_ATTEMPTS )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " = max! deleting. " < < std : : endl ;
# endif
2015-10-25 18:27:15 -04:00
delete gpsi . mItem ;
pend_it = mMsgPendingValidate . erase ( pend_it ) ;
}
else
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " movign to recvd. " < < std : : endl ;
# endif
2015-10-25 18:27:15 -04:00
mReceivedMsgs . push_back ( gpsi . mItem ) ;
+ + pend_it ;
}
}
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( mReceivedMsgs . empty ( ) )
return ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
std : : vector < RsNxsMsg * > : : iterator vit = mReceivedMsgs . begin ( ) ;
GxsMsgReq msgIds ;
std : : map < RsNxsMsg * , RsGxsMsgMetaData * > msgs ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > grpMetas ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
// coalesce group meta retrieval for performance
for ( ; vit ! = mReceivedMsgs . end ( ) ; + + vit )
{
RsNxsMsg * msg = * vit ;
grpMetas . insert ( std : : make_pair ( msg - > grpId , ( RsGxsGrpMetaData * ) NULL ) ) ;
}
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
mDataStore - > retrieveGxsGrpMetaData ( grpMetas ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " updating received messages: " < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
for ( vit = mReceivedMsgs . begin ( ) ; vit ! = mReceivedMsgs . end ( ) ; + + vit )
{
RsNxsMsg * msg = * vit ;
RsGxsMsgMetaData * meta = new RsGxsMsgMetaData ( ) ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
bool ok = false ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( msg - > meta . bin_len ! = 0 )
ok = meta - > deserialise ( msg - > meta . bin_data , & ( msg - > meta . bin_len ) ) ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
msg - > metaData = meta ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " deserialised info: grp id= " < < meta - > mGroupId < < " , msg id= " < < meta - > mMsgId ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
uint8_t validateReturn = VALIDATE_FAIL ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( ok )
{
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > : : iterator mit = grpMetas . find ( msg - > grpId ) ;
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " msg info : grp id= " < < msg - > grpId < < " , msg id= " < < msg - > msgId < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
RsGxsGrpMetaData * grpMeta = NULL ;
// validate msg
if ( mit ! = grpMetas . end ( ) )
{
grpMeta = mit - > second ;
validateReturn = validateMsg ( msg , grpMeta - > mGroupFlags , grpMeta - > mSignFlags , grpMeta - > keys ) ;
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " grpMeta.mSignFlags: " < < std : : hex < < grpMeta - > mSignFlags < < std : : dec < < std : : endl ;
std : : cerr < < " grpMeta.mAuthFlags: " < < std : : hex < < grpMeta - > mAuthenFlags < < std : : dec < < std : : endl ;
std : : cerr < < " message validation result: " < < ( int ) validateReturn < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
}
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( validateReturn = = VALIDATE_SUCCESS )
{
meta - > mMsgStatus = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED | GXS_SERV : : GXS_MSG_STATUS_GUI_NEW | GXS_SERV : : GXS_MSG_STATUS_GUI_UNREAD ;
msgs . insert ( std : : make_pair ( msg , meta ) ) ;
2015-02-06 20:04:51 -05:00
2015-10-25 18:27:15 -04:00
std : : vector < RsGxsMessageId > & msgv = msgIds [ msg - > grpId ] ;
if ( std : : find ( msgv . begin ( ) , msgv . end ( ) , msg - > msgId ) = = msgv . end ( ) )
{
msgv . push_back ( msg - > msgId ) ;
}
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
NxsMsgPendingVect : : iterator validated_entry = std : : find ( mMsgPendingValidate . begin ( ) , mMsgPendingValidate . end ( ) ,
getMsgIdPair ( * msg ) ) ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( validated_entry ! = mMsgPendingValidate . end ( ) ) mMsgPendingValidate . erase ( validated_entry ) ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
computeHash ( msg - > msg , meta - > mHash ) ;
meta - > recvTS = time ( NULL ) ;
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " new status flags: " < < meta - > mMsgStatus < < std : : endl ;
std : : cerr < < " computed hash: " < < meta - > mHash < < std : : endl ;
std : : cerr < < " Message received. Identity= " < < msg - > metaData - > mAuthorId < < " , from peer " < < msg - > PeerId ( ) < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2014-10-22 17:00:20 -04:00
2015-10-25 18:27:15 -04:00
if ( ! msg - > metaData - > mAuthorId . isNull ( ) )
mRoutingClues [ msg - > metaData - > mAuthorId ] . insert ( msg - > PeerId ( ) ) ;
2015-10-25 17:16:16 -04:00
2015-10-25 18:27:15 -04:00
if ( grpMeta - > mSignFlags & GXS_SERV : : FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES )
mTrackingClues . push_back ( std : : make_pair ( msg - > msgId , msg - > PeerId ( ) ) ) ;
}
}
else
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " deserialisation failed! " < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
validateReturn = VALIDATE_FAIL ;
}
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( validateReturn = = VALIDATE_FAIL )
{
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " failed to deserialise incoming meta, msgId: "
< < " msg->grpId: " < < msg - > grpId < < " , msgId: " < < msg - > msgId < < std : : endl ;
2014-05-17 09:50:40 -04:00
# endif
2015-10-25 18:27:15 -04:00
NxsMsgPendingVect : : iterator failed_entry = std : : find ( mMsgPendingValidate . begin ( ) , mMsgPendingValidate . end ( ) ,
getMsgIdPair ( * msg ) ) ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( failed_entry ! = mMsgPendingValidate . end ( ) ) mMsgPendingValidate . erase ( failed_entry ) ;
2014-05-17 09:50:40 -04:00
delete msg ;
2015-10-25 18:27:15 -04:00
}
else if ( validateReturn = = VALIDATE_FAIL_TRY_LATER )
{
2014-05-17 09:50:40 -04:00
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " failed to validate msg, trying again: "
< < " msg->grpId: " < < msg - > grpId < < " , msgId: " < < msg - > msgId < < std : : endl ;
2014-05-17 09:50:40 -04:00
# endif
2015-10-25 18:27:15 -04:00
RsGxsGrpMsgIdPair id ;
id . first = msg - > grpId ;
id . second = msg - > msgId ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
// first check you haven't made too many attempts
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
NxsMsgPendingVect : : iterator vit = std : : find (
mMsgPendingValidate . begin ( ) , mMsgPendingValidate . end ( ) , id ) ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( vit = = mMsgPendingValidate . end ( ) )
{
GxsPendingItem < RsNxsMsg * , RsGxsGrpMsgIdPair > item ( msg , id ) ;
mMsgPendingValidate . push_back ( item ) ;
} else
{
2014-05-17 09:50:40 -04:00
vit - > mAttempts + + ;
2015-10-25 18:27:15 -04:00
}
}
}
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
// clean up resources from group meta retrieval
freeAndClearContainerResource < std : : map < RsGxsGroupId , RsGxsGrpMetaData * > ,
RsGxsGrpMetaData * > ( grpMetas ) ;
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
if ( ! msgIds . empty ( ) )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " removing existing and old messages from incoming list. " < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
removeDeleteExistingMessages ( msgs , msgIds ) ;
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2015-10-25 18:27:15 -04:00
std : : cerr < < " storing remaining messages " < < std : : endl ;
2014-09-20 15:58:07 -04:00
# endif
2015-10-25 18:27:15 -04:00
mDataStore - > storeMessage ( msgs ) ;
2014-09-22 14:50:45 -04:00
2015-10-25 18:27:15 -04:00
RsGxsMsgChange * c = new RsGxsMsgChange ( RsGxsNotify : : TYPE_RECEIVE , false ) ;
c - > msgChangeMap = msgIds ;
mNotifications . push_back ( c ) ;
}
2014-05-17 09:50:40 -04:00
2015-10-25 18:27:15 -04:00
mReceivedMsgs . clear ( ) ;
2014-05-17 09:50:40 -04:00
}
void RsGenExchange : : processRecvdGroups ( )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
if ( mReceivedGrps . empty ( ) )
return ;
NxsGrpPendValidVect : : iterator vit = mReceivedGrps . begin ( ) ;
std : : vector < RsGxsGroupId > existingGrpIds ;
std : : list < RsGxsGroupId > grpIds ;
std : : map < RsNxsGrp * , RsGxsGrpMetaData * > grps ;
mDataStore - > retrieveGroupIds ( existingGrpIds ) ;
while ( vit ! = mReceivedGrps . end ( ) )
{
GxsPendingItem < RsNxsGrp * , RsGxsGroupId > & gpsi = * vit ;
RsNxsGrp * grp = gpsi . mItem ;
RsGxsGrpMetaData * meta = new RsGxsGrpMetaData ( ) ;
bool deserialOk = false ;
if ( grp - > meta . bin_len ! = 0 )
deserialOk = meta - > deserialise ( grp - > meta . bin_data , grp - > meta . bin_len ) ;
bool erase = true ;
if ( deserialOk )
{
grp - > metaData = meta ;
uint8_t ret = validateGrp ( grp ) ;
if ( ret = = VALIDATE_SUCCESS )
{
meta - > mGroupStatus = GXS_SERV : : GXS_GRP_STATUS_UNPROCESSED | GXS_SERV : : GXS_GRP_STATUS_UNREAD ;
meta - > mSubscribeFlags = GXS_SERV : : GROUP_SUBSCRIBE_NOT_SUBSCRIBED ;
computeHash ( grp - > grp , meta - > mHash ) ;
2014-10-22 17:00:20 -04:00
// group has been validated. Let's notify the global router for the clue
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " Group routage info: Identity= " < < meta - > mAuthorId < < " from " < < grp - > PeerId ( ) < < std : : endl ;
# endif
if ( ! meta - > mAuthorId . isNull ( ) )
mRoutingClues [ meta - > mAuthorId ] . insert ( grp - > PeerId ( ) ) ;
2014-05-17 09:50:40 -04:00
// now check if group already existss
if ( std : : find ( existingGrpIds . begin ( ) , existingGrpIds . end ( ) , grp - > grpId ) = = existingGrpIds . end ( ) )
{
meta - > mRecvTS = time ( NULL ) ;
if ( meta - > mCircleType = = GXS_CIRCLE_TYPE_YOUREYESONLY )
meta - > mOriginator = grp - > PeerId ( ) ;
grps . insert ( std : : make_pair ( grp , meta ) ) ;
grpIds . push_back ( grp - > grpId ) ;
}
else
{
GroupUpdate update ;
update . newGrp = grp ;
mGroupUpdates . push_back ( update ) ;
}
erase = true ;
}
else if ( ret = = VALIDATE_FAIL )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " failed to deserialise incoming meta, grpId: "
< < grp - > grpId < < std : : endl ;
# endif
delete grp ;
erase = true ;
}
else if ( ret = = VALIDATE_FAIL_TRY_LATER )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " failed to validate incoming grp, trying again. grpId: "
2014-10-05 15:14:05 -04:00
< < grp - > grpId < < std : : endl ;
2014-05-17 09:50:40 -04:00
# endif
if ( gpsi . mAttempts = = VALIDATE_MAX_ATTEMPTS )
{
delete grp ;
erase = true ;
}
else
{
erase = false ;
}
}
}
else
{
delete grp ;
delete meta ;
erase = true ;
}
if ( erase )
vit = mReceivedGrps . erase ( vit ) ;
else
2014-10-24 18:07:26 -04:00
+ + vit ;
2014-05-17 09:50:40 -04:00
}
if ( ! grpIds . empty ( ) )
{
2014-07-04 17:51:17 -04:00
RsGxsGroupChange * c = new RsGxsGroupChange ( RsGxsNotify : : TYPE_RECEIVE , false ) ;
2014-05-17 09:50:40 -04:00
c - > mGrpIdList = grpIds ;
mNotifications . push_back ( c ) ;
mDataStore - > storeGroup ( grps ) ;
}
}
void RsGenExchange : : performUpdateValidation ( )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
if ( mGroupUpdates . empty ( ) )
return ;
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " RsGenExchange::performUpdateValidation() " < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > grpMetas ;
std : : vector < GroupUpdate > : : iterator vit = mGroupUpdates . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = mGroupUpdates . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
grpMetas . insert ( std : : make_pair ( vit - > newGrp - > grpId , ( RsGxsGrpMetaData * ) NULL ) ) ;
if ( ! grpMetas . empty ( ) )
mDataStore - > retrieveGxsGrpMetaData ( grpMetas ) ;
else
return ;
vit = mGroupUpdates . begin ( ) ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = mGroupUpdates . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
GroupUpdate & gu = * vit ;
std : : map < RsGxsGroupId , RsGxsGrpMetaData * > : : iterator mit =
grpMetas . find ( gu . newGrp - > grpId ) ;
gu . oldGrpMeta = mit - > second ;
gu . validUpdate = updateValid ( * ( gu . oldGrpMeta ) , * ( gu . newGrp ) ) ;
}
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::performUpdateValidation() " < < std : : endl ;
# endif
vit = mGroupUpdates . begin ( ) ;
std : : map < RsNxsGrp * , RsGxsGrpMetaData * > grps ;
2014-10-24 18:07:26 -04:00
for ( ; vit ! = mGroupUpdates . end ( ) ; + + vit )
2014-05-17 09:50:40 -04:00
{
GroupUpdate & gu = * vit ;
if ( gu . validUpdate )
{
if ( gu . newGrp - > metaData - > mCircleType = = GXS_CIRCLE_TYPE_YOUREYESONLY )
gu . newGrp - > metaData - > mOriginator = gu . newGrp - > PeerId ( ) ;
grps . insert ( std : : make_pair ( gu . newGrp , gu . newGrp - > metaData ) ) ;
}
else
{
delete gu . newGrp ;
}
delete gu . oldGrpMeta ;
}
mDataStore - > updateGroup ( grps ) ;
mGroupUpdates . clear ( ) ;
}
bool RsGenExchange : : updateValid ( RsGxsGrpMetaData & oldGrpMeta , RsNxsGrp & newGrp ) const
{
std : : map < SignType , RsTlvKeySignature > & signSet = newGrp . metaData - > signSet . keySignSet ;
2015-10-23 22:53:00 -04:00
std : : map < SignType , RsTlvKeySignature > : : iterator mit = signSet . find ( INDEX_AUTHEN_ADMIN ) ;
2014-05-17 09:50:40 -04:00
if ( mit = = signSet . end ( ) )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::updateValid() new admin sign not found! " < < std : : endl ;
2014-09-20 15:58:07 -04:00
std : : cerr < < " RsGenExchange::updateValid() grpId: " < < oldGrpMeta . mGroupId < < std : : endl ;
2014-05-17 09:50:40 -04:00
# endif
return false ;
}
RsTlvKeySignature adminSign = mit - > second ;
2014-06-12 06:28:23 -04:00
std : : map < RsGxsId , RsTlvSecurityKey > & keys = oldGrpMeta . keys . keys ;
std : : map < RsGxsId , RsTlvSecurityKey > : : iterator keyMit = keys . find ( RsGxsId ( oldGrpMeta . mGroupId ) ) ;
2014-05-17 09:50:40 -04:00
if ( keyMit = = keys . end ( ) )
{
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
2014-05-17 09:50:40 -04:00
std : : cerr < < " RsGenExchange::updateValid() admin key not found! " < < std : : endl ;
# endif
return false ;
}
// also check this is the latest published group
bool latest = newGrp . metaData - > mPublishTs > oldGrpMeta . mPublishTs ;
2015-03-14 10:33:23 -04:00
mGixs - > timeStampKey ( newGrp . metaData - > mAuthorId ) ;
return GxsSecurity : : validateNxsGrp ( newGrp , adminSign , keyMit - > second ) & & latest ;
2014-05-17 09:50:40 -04:00
}
void RsGenExchange : : setGroupReputationCutOff ( uint32_t & token , const RsGxsGroupId & grpId , int CutOff )
{
2014-11-11 14:47:05 -05:00
RS_STACK_MUTEX ( mGenMtx ) ;
2014-05-17 09:50:40 -04:00
token = mDataAccess - > generatePublicToken ( ) ;
GrpLocMetaData g ;
g . grpId = grpId ;
g . val . put ( RsGeneralDataService : : GRP_META_CUTOFF_LEVEL , ( int32_t ) CutOff ) ;
mGrpLocMetaMap . insert ( std : : make_pair ( token , g ) ) ;
}
2014-09-22 14:50:45 -04:00
void RsGenExchange : : removeDeleteExistingMessages ( RsGeneralDataService : : MsgStoreMap & msgs , GxsMsgReq & msgIdsNotify )
{
2014-05-17 09:50:40 -04:00
// first get grp ids of messages to be stored
RsGxsGroupId : : std_set mGrpIdsUnique ;
2014-10-24 18:07:26 -04:00
for ( RsGeneralDataService : : MsgStoreMap : : const_iterator cit = msgs . begin ( ) ; cit ! = msgs . end ( ) ; + + cit )
2014-05-17 09:50:40 -04:00
mGrpIdsUnique . insert ( cit - > second - > mGroupId ) ;
2014-09-20 15:58:07 -04:00
//RsGxsGroupId::std_list grpIds(mGrpIdsUnique.begin(), mGrpIdsUnique.end());
//RsGxsGroupId::std_list::const_iterator it = grpIds.begin();
2014-05-17 09:50:40 -04:00
typedef std : : map < RsGxsGroupId , RsGxsMessageId : : std_vector > MsgIdReq ;
MsgIdReq msgIdReq ;
// now get a list of all msgs ids for each group
2014-10-24 18:07:26 -04:00
for ( RsGxsGroupId : : std_set : : const_iterator it ( mGrpIdsUnique . begin ( ) ) ; it ! = mGrpIdsUnique . end ( ) ; + + it )
2014-05-17 09:50:40 -04:00
{
mDataStore - > retrieveMsgIds ( * it , msgIdReq [ * it ] ) ;
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
const std : : vector < RsGxsMessageId > & vec ( msgIdReq [ * it ] ) ;
std : : cerr < < " retrieved " < < vec . size ( ) < < " message ids for group " < < * it < < std : : endl ;
for ( uint32_t i = 0 ; i < vec . size ( ) ; + + i )
std : : cerr < < " " < < vec [ i ] < < std : : endl ;
# endif
2014-05-17 09:50:40 -04:00
}
2014-09-20 15:58:07 -04:00
//RsGeneralDataService::MsgStoreMap::iterator cit2 = msgs.begin();
2014-05-17 09:50:40 -04:00
RsGeneralDataService : : MsgStoreMap filtered ;
// now for each msg to be stored that exist in the retrieved msg/grp "index" delete and erase from map
2014-10-24 18:07:26 -04:00
for ( RsGeneralDataService : : MsgStoreMap : : iterator cit2 = msgs . begin ( ) ; cit2 ! = msgs . end ( ) ; + + cit2 )
2014-05-17 09:50:40 -04:00
{
const RsGxsMessageId : : std_vector & msgIds = msgIdReq [ cit2 - > second - > mGroupId ] ;
2015-10-24 12:55:49 -04:00
# ifdef GEN_EXCH_DEBUG
2014-09-20 15:58:07 -04:00
std : : cerr < < " grpid= " < < cit2 - > second - > mGroupId < < " , msgid= " < < cit2 - > second - > mMsgId ;
2015-10-24 12:55:49 -04:00
# endif
2014-09-20 15:58:07 -04:00
2014-09-22 14:50:45 -04:00
// Avoid storing messages that are already in the database, as well as messages that are too old (or generally do not pass the database storage test)
//
if ( std : : find ( msgIds . begin ( ) , msgIds . end ( ) , cit2 - > second - > mMsgId ) = = msgIds . end ( ) & & messagePublicationTest ( * cit2 - > second ) )
{
// passes tests, so add to filtered list
//
filtered . insert ( * cit2 ) ;
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " keeping " < < cit2 - > second - > mMsgId < < std : : endl ;
# endif
}
else // remove message from list
2014-05-17 09:50:40 -04:00
{
// msg exist in retrieved index
RsGxsMessageId : : std_vector & notifyIds = msgIdsNotify [ cit2 - > second - > mGroupId ] ;
RsGxsMessageId : : std_vector : : iterator it2 = std : : find ( notifyIds . begin ( ) ,
notifyIds . end ( ) , cit2 - > second - > mMsgId ) ;
if ( it2 ! = notifyIds . end ( ) )
2015-02-06 20:04:51 -05:00
{
2014-05-17 09:50:40 -04:00
notifyIds . erase ( it2 ) ;
2015-02-06 20:04:51 -05:00
if ( notifyIds . empty ( ) )
{
msgIdsNotify . erase ( cit2 - > second - > mGroupId ) ;
}
}
2014-09-20 15:58:07 -04:00
# ifdef GEN_EXCH_DEBUG
std : : cerr < < " discarding " < < cit2 - > second - > mMsgId < < std : : endl ;
# endif
2015-01-15 16:49:33 -05:00
delete cit2 - > first ;
// cit2->second will be deleted too in the destructor of cit2->first (RsNxsMsg)
2014-05-17 09:50:40 -04:00
}
}
msgs = filtered ;
}