diff --git a/TODO.circles.txt b/TODO.circles.txt new file mode 100644 index 000000000..4e70dccc9 --- /dev/null +++ b/TODO.circles.txt @@ -0,0 +1,47 @@ +Legend: + [X]: done, [ ]: pending, [-]: Cancelled, [/]: ongoing + +GUI + [X] disable edit circles or make it work + [X] make GUI update when creating a circle + [ ] handle the display of encrypted forums/channels/etc when we do not have the keys + [ ] disable posting to circles for which we do not have the rights + [ ] warn about creating a circle without one of your ids in it + [X] group "show details" should be made up to date for restrinction options + [ ] allow to share circles publish rights + [X] allow non admin to see circles details but not edit + + [ ] update TS of groups linked to a modified circle, so as to cause updates when a new member is addded to the group + [X] forums GUI should show correct restriction options for restricted forums + [X] changing a circle's name should update the GUI + [ ] make sure we cannot post in forums using IDs that are not in the circle + [ ] make sure unauthorised ids are rejected when validating posts from a circle restricted group + [ ] add GUI for local circles in circle GUI + [ ] share publish rights between circles + [ ] clean GUI (hide IDs) + + +Tests + [X] create a safe testing environment: 2 peers with no other contacts, 2 IDs each, and some forums + [X] test #001: transactions should encrypt and decrypt ok on both sides + [X] test #002: peers inside a circles should see the data + [X] test #003: peers outside of a circles shouldn't see the data + [-] test #004: peers subscribed to encrypted circles shouldn't keep asking for the data if they cannot decrypt + [X] test #005: peers can be added/removed from circles, and the circles update between friends + [ ] test #006: peers subscribed to encrypted circles who recently got added to the circle should get the data + [ ] test #007: peers outside a circle shouldn't be able to post (or posts shouldn't propagate) + +Backend + [X] add debug output later RS_NXS_DEBUG_7 in rsgxsnetservice.cc for the crypto layer + +Bugs + [X] Peers cannot be removed from a circle + [X] Context menu should not allow to edit non admin circles + [X] Editing circles make them subscribed, even non admin ones. + [X] Disable autosync for circles (in rsinit.cc) + [-] Add explicit circle sync request for all grps restricted to a circle (same as IDs) + [X] when a peer receives a circle, there is no way to view its details, only the id is available + [X] if a peer has circles available in "Circles (others)"... if you click on + "Create Circle" on the gui, then all circles are automatically subscribed + + diff --git a/libretroshare/src/grouter/grouterclientservice.h b/libretroshare/src/grouter/grouterclientservice.h index 727d8ea82..a6bef29e1 100644 --- a/libretroshare/src/grouter/grouterclientservice.h +++ b/libretroshare/src/grouter/grouterclientservice.h @@ -66,6 +66,7 @@ public: std::cerr << "!!!!!! Received Data status from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; std::cerr << " message ID = " << received_id << std::endl; std::cerr << " data status = " << data_status << std::endl; + std::cerr << " signer ID = " << signer_id << std::endl; } // This function is mandatory. It should do two things: diff --git a/libretroshare/src/gxs/gxssecurity.cc b/libretroshare/src/gxs/gxssecurity.cc index 8b27fe1bc..248ceaeac 100644 --- a/libretroshare/src/gxs/gxssecurity.cc +++ b/libretroshare/src/gxs/gxssecurity.cc @@ -34,6 +34,11 @@ * #define GXS_SECURITY_DEBUG 1 ***/ +static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_HEADER = 0xFACE; +static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_HEADER_SIZE = 2 ; +static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_NUMBER_OF_KEYS_SIZE = 2 ; +static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE = 256 ; + static RsGxsId getRsaKeyFingerprint(RSA *pubkey) { int lenn = BN_num_bytes(pubkey -> n); @@ -93,7 +98,9 @@ static void setRSAPublicKeyData(RsTlvSecurityKey & key, RSA *rsa_pub) bool GxsSecurity::checkPrivateKey(const RsTlvSecurityKey& key) { +#ifdef GXS_SECURITY_DEBUG std::cerr << "Checking private key " << key.keyId << " ..." << std::endl; +#endif if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_FULL) { @@ -128,7 +135,9 @@ bool GxsSecurity::checkPrivateKey(const RsTlvSecurityKey& key) } bool GxsSecurity::checkPublicKey(const RsTlvSecurityKey& key) { +#ifdef GXS_SECURITY_DEBUG std::cerr << "Checking public key " << key.keyId << " ..." << std::endl; +#endif if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_PUBLIC_ONLY) { @@ -224,7 +233,7 @@ bool GxsSecurity::extractPublicKey(const RsTlvSecurityKey& private_key,RsTlvSecu { std::cerr << std::endl; std::cerr << "WARNING: GXS ID key pair " << private_key.keyId << " has inconsistent fingerprint. This is an old key " << std::endl; - std::cerr << " that is unsecured (can be faked easily) should not be used anymore. Please delete it." << std::endl; + std::cerr << " that is unsecure (can be faked easily). You should delete it!" << std::endl; std::cerr << std::endl; public_key.keyId = private_key.keyId ; @@ -410,10 +419,15 @@ bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, u #ifdef DISTRIB_DEBUG std::cerr << "GxsSecurity::encrypt() " << std::endl; #endif + // Encrypts (in,inlen) into (out,outlen) using the given RSA public key. + // The format of the encrypted data is: + // + // [--- Encrypted session key length ---|--- Encrypted session key ---|--- IV ---|---- Encrypted data ---] + // - RSA *tmpkey = ::extractPublicKey(key) ; - RSA *rsa_publish_pub = RSAPublicKey_dup(tmpkey) ; - RSA_free(tmpkey) ; + RSA *tmpkey = ::extractPublicKey(key) ; + RSA *rsa_publish_pub = RSAPublicKey_dup(tmpkey) ; + RSA_free(tmpkey) ; EVP_PKEY *public_key = NULL; @@ -430,7 +444,7 @@ bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, u { #ifdef DISTRIB_DEBUG std::cerr << "GxsSecurity(): Could not generate publish key " << grpId - << std::endl; + << std::endl; #endif return false; } @@ -477,7 +491,7 @@ bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, u // now encrypt actual data if(!EVP_SealUpdate(&ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) { - free(out) ; + free(out) ; out = NULL ; return false; } @@ -488,7 +502,7 @@ bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, u // add padding if(!EVP_SealFinal(&ctx, (unsigned char*) out + out_offset, &out_currOffset)) { - free(out) ; + free(out) ; out = NULL ; return false; } @@ -499,7 +513,7 @@ bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, u // make sure offset has not gone passed valid memory bounds if(out_offset > max_outlen) { - free(out) ; + free(out) ; out = NULL ; return false; } @@ -511,14 +525,160 @@ bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, u return true; } +bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const std::vector& keys) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "GxsSecurity::encrypt() " << std::endl; +#endif + // Encrypts (in,inlen) into (out,outlen) using the given RSA public key. + // The format of the encrypted data is: + // + // [--- ID ---|--- number of encrypted keys---| n * (--- Encrypted session keys ---) |--- IV ---|---- Encrypted data ---] + // 2 bytes 2 byte = n 256 bytes EVP_MAX_IV_LENGTH Rest of packet + // + + out = NULL ; + + try + { + std::vector public_keys(keys.size(),NULL); + + for(uint32_t i=0;i ek(keys.size(),NULL) ; + std::vector eklen(keys.size(),0) ; + + for(uint32_t i=0;i> 8) & 0xff ; + + // number of keys + + out[out_offset++] = keys.size() & 0xff ; + out[out_offset++] = (keys.size() >> 8) & 0xff ; + + // encrypted keys, each preceeded with its length + + for(uint32_t i=0;i max_outlen) + throw std::runtime_error("Memory used by encryption exceeds allocated memory block") ; + + // free encrypted key data + + for(uint32_t i=0;i& keys) +{ + // Decrypts (in,inlen) into (out,outlen) using one of the given RSA public keys, trying them all in a row. + // The format of the encrypted data is: + // + // [--- ID ---|--- number of encrypted keys---| n * (--- Encrypted session keys ---) |--- IV ---|---- Encrypted data ---] + // 2 bytes 2 byte = n 256 bytes EVP_MAX_IV_LENGTH Rest of packet + // + // This method can be used to decrypt multi-encrypted data, if passing he correct encrypted key block (corresponding to the given key) +#ifdef DISTRIB_DEBUG + std::cerr << "GxsSecurity::decrypt() " << std::endl; +#endif + + try + { + // check that the input block has a valid format. + + uint32_t offset = 0 ; + uint16_t format_id = in[offset] + (in[offset+1] << 8) ; + + if(format_id != MULTI_ENCRYPTION_FORMAT_v001_HEADER) + { + std::cerr << "Unrecognised format in encrypted block. Header id = " << std::hex << format_id << std::dec << std::endl; + throw std::runtime_error("Unrecognised format in encrypted block.") ; + } + offset += MULTI_ENCRYPTION_FORMAT_v001_HEADER_SIZE; + + // read number of encrypted keys + + uint32_t number_of_keys = in[offset] + (in[offset+1] << 8) ; + offset += MULTI_ENCRYPTION_FORMAT_v001_NUMBER_OF_KEYS_SIZE; + + // reach the actual data offset + + uint32_t encrypted_keys_offset = offset ; + uint32_t encrypted_block_size = 0 ; + + uint32_t IV_offset = offset + number_of_keys * MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE ; + uint32_t encrypted_block_offset = IV_offset + EVP_MAX_IV_LENGTH ; + + // read IV offset + + if(encrypted_block_offset >= inlen) + throw std::runtime_error("Offset error") ; + + encrypted_block_size = inlen - encrypted_block_offset ; +#ifdef GXS_SECURITY_DEBUG + std::cerr << " number of keys in envelop: " << number_of_keys << std::endl; + std::cerr << " IV offset : " << IV_offset << std::endl; + std::cerr << " encrypted block offset : " << encrypted_block_offset << std::endl; + std::cerr << " encrypted block size : " << encrypted_block_size << std::endl; +#endif + + // decrypt + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + bool succeed = false; + + for(uint32_t j=0;j& keys) ; /** * Decrypts data using evelope decryption (taken from open ssl's evp_sealinit ) @@ -74,7 +75,8 @@ class GxsSecurity * @param inlen * @return false if encryption failed */ - static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ; + static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ; + static bool decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in, uint32_t inlen, const std::vector& keys); /*! * uses grp signature to check if group has been diff --git a/libretroshare/src/gxs/rsgds.h b/libretroshare/src/gxs/rsgds.h index 1c5c1a500..0593610ce 100644 --- a/libretroshare/src/gxs/rsgds.h +++ b/libretroshare/src/gxs/rsgds.h @@ -92,9 +92,9 @@ public: uint32_t mMaxVisibleCount ; }; -typedef std::map > NxsMsgDataResult; +typedef std::map > NxsMsgDataResult; typedef std::map > NxsMsgRelatedDataResult; -typedef std::map > GxsMsgResult; // +typedef std::map > GxsMsgResult; // /*! * The main role of GDS is the preparation and handing out of messages requested from diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 5536bad28..c1e2dd116 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -156,6 +156,11 @@ RsGenExchange::~RsGenExchange() } +bool RsGenExchange::getGroupServerUpdateTS(const RsGxsGroupId& gid, time_t& grp_server_update_TS, time_t& msg_server_update_TS) +{ + return mNetService->getGroupServerUpdateTS(gid,grp_server_update_TS,msg_server_update_TS) ; +} + void RsGenExchange::data_tick() { @@ -170,7 +175,7 @@ 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. - processGrpMetaChanges(); + processGrpMetaChanges(); processMsgMetaChanges(); mDataAccess->processRequests(); @@ -183,9 +188,9 @@ void RsGenExchange::tick() processGroupDelete(); - processRecvdData(); + processRecvdData(); - processRoutingClues() ; + processRoutingClues() ; if(!mNotifications.empty()) { @@ -234,6 +239,11 @@ void RsGenExchange::tick() RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, false); gc->mGrpIdList = grpIds; +#ifdef GEN_EXCH_DEBUG + std::cerr << " adding the following grp ids to notification: " << std::endl; + for(std::list::const_iterator it(grpIds.begin());it!=grpIds.end();++it) + std::cerr << " " << *it << std::endl; +#endif mNotifications.push_back(gc); } @@ -1137,8 +1147,13 @@ void RsGenExchange::receiveChanges(std::vector& changes) out.mGrps.splice(out.mGrps.end(), gc->mGrpIdList); } } + else + std::cerr << "(EE) Unknown changes type!!" << std::endl; + delete n; } + changes.clear() ; + RsServer::notify()->notifyGxsChange(out); } @@ -1153,6 +1168,8 @@ bool RsGenExchange::subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, if(mNetService != NULL) mNetService->subscribeStatusChanged(grpId,subscribe) ; + else + std::cerr << "(EE) No mNetService in RsGenExchange for service 0x" << std::hex << mServType << std::dec << std::endl; return true; } @@ -1814,6 +1831,11 @@ void RsGenExchange::processGrpMetaChanges() RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, true); gc->mGrpIdList = grpChanged; mNotifications.push_back(gc); +#ifdef GEN_EXCH_DEBUG + std::cerr << " adding the following grp ids to notification: " << std::endl; + for(std::list::const_iterator it(grpChanged.begin());it!=grpChanged.end();++it) + std::cerr << " " << *it << std::endl; +#endif } } @@ -2458,6 +2480,11 @@ void RsGenExchange::publishGrps() RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PUBLISH, false); gc->mGrpIdList = grpChanged; mNotifications.push_back(gc); +#ifdef GEN_EXCH_DEBUG + std::cerr << " adding the following grp ids to notification: " << std::endl; + for(std::list::const_iterator it(grpChanged.begin());it!=grpChanged.end();++it) + std::cerr << " " << *it << std::endl; +#endif } } @@ -2755,30 +2782,30 @@ void RsGenExchange::processRecvdMessages() void RsGenExchange::processRecvdGroups() { - RS_STACK_MUTEX(mGenMtx) ; + RS_STACK_MUTEX(mGenMtx) ; - if(mReceivedGrps.empty()) - return; + if(mReceivedGrps.empty()) + return; - NxsGrpPendValidVect::iterator vit = mReceivedGrps.begin(); - std::vector existingGrpIds; - std::list grpIds; + NxsGrpPendValidVect::iterator vit = mReceivedGrps.begin(); + std::vector existingGrpIds; + std::list grpIds; - std::map grps; + std::map grps; - mDataStore->retrieveGroupIds(existingGrpIds); + mDataStore->retrieveGroupIds(existingGrpIds); - while( vit != mReceivedGrps.end()) - { - GxsPendingItem& gpsi = *vit; - RsNxsGrp* grp = gpsi.mItem; - RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); - bool deserialOk = false; + while( vit != mReceivedGrps.end()) + { + GxsPendingItem& 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); + if(grp->meta.bin_len != 0) + deserialOk = meta->deserialise(grp->meta.bin_data, grp->meta.bin_len); - bool erase = true; + bool erase = true; if(deserialOk) { @@ -2788,22 +2815,22 @@ void RsGenExchange::processRecvdGroups() grp->metaData = meta; uint8_t ret = validateGrp(grp); - - if(ret == VALIDATE_SUCCESS) - { + 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); - // 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 + // group has been validated. Let's notify the global router for the clue if(!meta->mAuthorId.isNull()) - mRoutingClues[meta->mAuthorId].insert(grp->PeerId()) ; + { +#ifdef GEN_EXCH_DEBUG + std::cerr << "Group routage info: Identity=" << meta->mAuthorId << " from " << grp->PeerId() << std::endl; +#endif + + mRoutingClues[meta->mAuthorId].insert(grp->PeerId()) ; + } // This has been moved here (as opposed to inside part for new groups below) because it is used to update the server TS when updates // of grp metadata arrive. @@ -2816,6 +2843,8 @@ void RsGenExchange::processRecvdGroups() if(meta->mCircleType == GXS_CIRCLE_TYPE_YOUREYESONLY) meta->mOriginator = grp->PeerId(); + meta->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED; + grps.insert(std::make_pair(grp, meta)); grpIds.push_back(grp->grpId); } @@ -2826,17 +2855,17 @@ void RsGenExchange::processRecvdGroups() mGroupUpdates.push_back(update); } erase = true; - } - else if(ret == VALIDATE_FAIL) - { + } + else if(ret == VALIDATE_FAIL) + { #ifdef GEN_EXCH_DEBUG std::cerr << " failed to validate incoming meta, grpId: " << grp->grpId << ": wrong signature" << std::endl; #endif delete grp; erase = true; - } - else if(ret == VALIDATE_FAIL_TRY_LATER) - { + } + else if(ret == VALIDATE_FAIL_TRY_LATER) + { #ifdef GEN_EXCH_DEBUG std::cerr << " failed to validate incoming grp, trying again. grpId: " << grp->grpId << std::endl; @@ -2862,21 +2891,26 @@ void RsGenExchange::processRecvdGroups() delete grp; delete meta; erase = true; - } + } - if(erase) - vit = mReceivedGrps.erase(vit); - else - ++vit; - } + if(erase) + vit = mReceivedGrps.erase(vit); + else + ++vit; + } - if(!grpIds.empty()) - { - RsGxsGroupChange* c = new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVE, false); - c->mGrpIdList = grpIds; - mNotifications.push_back(c); - mDataStore->storeGroup(grps); - } + if(!grpIds.empty()) + { + RsGxsGroupChange* c = new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVE, false); + c->mGrpIdList = grpIds; + mNotifications.push_back(c); + mDataStore->storeGroup(grps); +#ifdef GEN_EXCH_DEBUG + std::cerr << " adding the following grp ids to notification: " << std::endl; + for(std::list::const_iterator it(grpIds.begin());it!=grpIds.end();++it) + std::cerr << " " << *it << std::endl; +#endif + } } void RsGenExchange::performUpdateValidation() @@ -2936,22 +2970,35 @@ void RsGenExchange::performUpdateValidation() else { delete gu.newGrp; + gu.newGrp = NULL ; } delete gu.oldGrpMeta; + gu.oldGrpMeta = NULL ; } - - mDataStore->updateGroup(grps); - // notify the client RsGxsGroupChange* c = new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVE, true); for(uint32_t i=0;imGrpIdList.push_back(mGroupUpdates[i].oldGrpMeta->mGroupId) ; + if(mGroupUpdates[i].newGrp != NULL) + { + c->mGrpIdList.push_back(mGroupUpdates[i].newGrp->grpId) ; +#ifdef GEN_EXCH_DEBUG + std::cerr << " " << mGroupUpdates[i].newGrp->grpId << std::endl; +#endif + } mNotifications.push_back(c); + + // Warning: updateGroup will destroy the objects in grps. Dont use it afterwards! + mDataStore->updateGroup(grps); + +#ifdef GEN_EXCH_DEBUG + std::cerr << " adding the following grp ids to notification: " << std::endl; +#endif + // cleanup mGroupUpdates.clear(); diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index 1462b0285..7b71e0795 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -615,6 +615,14 @@ public: */ void shareGroupPublishKey(const RsGxsGroupId& grpId,const std::set& peers) ; + + /*! + * Returns the local TS of the group as known by the network service. + * This is useful to allow various network services to sync their update TS + * when needed. Typical use case is forums and circles. + * @param gid GroupId the TS is which is requested + */ + bool getGroupServerUpdateTS(const RsGxsGroupId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) ; protected: diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h index cf13a77d3..8969f947d 100644 --- a/libretroshare/src/gxs/rsgixs.h +++ b/libretroshare/src/gxs/rsgixs.h @@ -123,16 +123,12 @@ public: virtual bool encryptData(const uint8_t *clear_data,uint32_t clear_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& encryption_error) = 0 ; virtual bool decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& clear_data,uint32_t& clear_data_size,const RsGxsId& encryption_key_id,uint32_t& encryption_error) = 0 ; -// virtual bool getPublicKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; - virtual bool getOwnIds(std::list& ids) = 0; virtual bool isOwnId(const RsGxsId& key_id) = 0 ; virtual void timeStampKey(const RsGxsId& key_id) = 0 ; - // virtual void networkRequestPublicKey(const RsGxsId& key_id,const std::list& peer_ids) = 0 ; - - // Key related interface - used for validating msgs and groups. + // Key related interface - used for validating msgs and groups. /*! * Use to query a whether given key is available by its key reference * @param keyref the keyref of key that is being checked for @@ -147,8 +143,8 @@ public: */ virtual bool havePrivateKey(const RsGxsId &id) = 0; - // The fetchKey has an optional peerList.. this is people that had the msg with the signature. - // These same people should have the identity - so we ask them first. + // The fetchKey has an optional peerList.. this is people that had the msg with the signature. + // These same people should have the identity - so we ask them first. /*! * Use to request a given key reference * @param keyref the KeyRef of the key being requested @@ -167,9 +163,6 @@ public: virtual bool getKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; virtual bool getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; // For signing outgoing messages. virtual bool getIdDetails(const RsGxsId& id, RsIdentityDetails& details) = 0 ; // Proxy function so that we get p3Identity info from Gxs -#ifdef SUSPENDED -#endif - }; class GixsReputation @@ -218,9 +211,13 @@ class RsGcxs virtual bool isLoaded(const RsGxsCircleId &circleId) = 0; virtual bool loadCircle(const RsGxsCircleId &circleId) = 0; - virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id) = 0; - virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) = 0; - virtual bool recipients(const RsGxsCircleId &circleId, std::list &friendlist) = 0; + virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt) = 0; + virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) = 0; + virtual bool recipients(const RsGxsCircleId &circleId, std::list& friendlist) = 0; + virtual bool recipients(const RsGxsCircleId &circleId, std::list& idlist) = 0; + virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) = 0; + + virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) =0; }; @@ -231,8 +228,12 @@ public: RsGxsCircleExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, RsSerialType* serviceSerialiser, uint16_t mServType, RsGixs* gixs, uint32_t authenPolicy) :RsGenExchange(gds,ns,serviceSerialiser,mServType, gixs, authenPolicy) { return; } -virtual ~RsGxsCircleExchange() { return; } - + virtual ~RsGxsCircleExchange() { return; } + + virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) + { + return RsGenExchange::getGroupServerUpdateTS(RsGxsGroupId(gid),grp_server_update_TS,msg_server_update_TS) ; + } }; diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index efcc5c138..e7cc72f4e 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -1,4 +1,3 @@ - /* * libretroshare/src/gxs: rsgxnetservice.cc * @@ -74,6 +73,15 @@ // +------ handleRecvSyncMessage( RsNxsSyncMsg*) // - parse msgs from group // - send all msg IDs for this group +// | +// +---- canSendMsgIds(msgMeta, grpMeta, peer) +// | | +// | +--CIRCLES_TYPE_LOCAL------- false +// | +--CIRCLES_TYPE_PUBLIC------ true +// | +--CIRCLES_TYPE_EXTERNAL---- mCircles->canSend(circleId, getPgpId(peerId)) +// | +--CIRCLES_TYPE_YOUR_EYES--- internal circle stuff +// | +// +---- store in mPendingCircleVet ou directement locked_pushGrpRespFromList() // data_tick() // | // +----------- updateServerSyncTS() @@ -157,6 +165,8 @@ // send RsNxsSyncMsg(ServiceType, grpId, updateTS) | // | | // (Only send if rand() < sendingProb()) +---comes from mClientMsgUpdateMap -----+ +// +// // // Suggestions // =========== @@ -192,11 +202,14 @@ #include #include "rsgxsnetservice.h" +#include "gxssecurity.h" #include "retroshare/rsconfig.h" #include "retroshare/rsreputations.h" #include "retroshare/rsgxsflags.h" #include "retroshare/rsgxscircles.h" #include "pgp/pgpauxutils.h" +#include "util/rsmemory.h" +#include "util/stacktrace.h" /*** * Use the following defines to debug: @@ -206,6 +219,9 @@ NXS_NET_DEBUG_3 publish key exchange NXS_NET_DEBUG_4 vetting NXS_NET_DEBUG_5 summary of transactions (useful to just know what comes in/out) + NXS_NET_DEBUG_6 + NXS_NET_DEBUG_7 encryption/decryption of transactions + ***/ //#define NXS_NET_DEBUG_0 1 //#define NXS_NET_DEBUG_1 1 @@ -214,6 +230,7 @@ //#define NXS_NET_DEBUG_4 1 //#define NXS_NET_DEBUG_5 1 //#define NXS_NET_DEBUG_6 1 +//#define NXS_NET_DEBUG_7 1 #define GIXS_CUT_OFF 0 //#define NXS_FRAG @@ -235,18 +252,25 @@ #define GROUP_STATS_UPDATE_NB_PEERS 2 // number of peers to which the group stats are asked #define MAX_ALLOWED_GXS_MESSAGE_SIZE 199000 // 200,000 bytes including signature and headers +static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN = 0x00 ; +static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR = 0x01 ; +static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR = 0x02 ; +static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR = 0x03 ; +static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR = 0x04 ; +static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ; + // Debug system to allow to print only for some IDs (group, Peer, etc) -#if defined(NXS_NET_DEBUG_0) || defined(NXS_NET_DEBUG_1) || defined(NXS_NET_DEBUG_2) || defined(NXS_NET_DEBUG_3) || defined(NXS_NET_DEBUG_4) || defined(NXS_NET_DEBUG_5) || defined(NXS_NET_DEBUG_6) +#if defined(NXS_NET_DEBUG_0) || defined(NXS_NET_DEBUG_1) || defined(NXS_NET_DEBUG_2) || defined(NXS_NET_DEBUG_3) \ + || defined(NXS_NET_DEBUG_4) || defined(NXS_NET_DEBUG_5) || defined(NXS_NET_DEBUG_6) || defined(NXS_NET_DEBUG_7) static const RsPeerId peer_to_print = RsPeerId(std::string("")) ; static const RsGxsGroupId group_id_to_print = RsGxsGroupId(std::string("" )) ; // use this to allow to this group id only, or "" for all IDs -static const uint32_t service_to_print = 0x215 ; // use this to allow to this service id only, or 0 for all services +static const uint32_t service_to_print = 0x218 ; // use this to allow to this service id only, or 0 for all services // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) class nullstream: public std::ostream {}; -#if defined(NXS_NET_DEBUG_0) || defined(NXS_NET_DEBUG_1) || defined(NXS_NET_DEBUG_2) || defined(NXS_NET_DEBUG_3) || defined(NXS_NET_DEBUG_4) || defined(NXS_NET_DEBUG_5)|| defined(NXS_NET_DEBUG_6) static std::string nice_time_stamp(time_t now,time_t TS) { if(TS == 0) @@ -258,8 +282,8 @@ static std::string nice_time_stamp(time_t now,time_t TS) return s.str() ; } } -#endif + static std::ostream& gxsnetdebug(const RsPeerId& peer_id,const RsGxsGroupId& grp_id,uint32_t service_type) { static nullstream null ; @@ -283,11 +307,14 @@ const uint32_t RsGxsNetService::FRAGMENT_SIZE = 150000; RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, RsNxsNetMgr *netMgr, RsNxsObserver *nxsObs, - const RsServiceInfo serviceInfo, - RsGixsReputation* reputations, RsGcxs* circles, - PgpAuxUtils *pgpUtils, bool grpAutoSync,bool msgAutoSync) + const RsServiceInfo serviceInfo, + RsGixsReputation* reputations, RsGcxs* circles, RsGixs *gixs, + PgpAuxUtils *pgpUtils, bool grpAutoSync,bool msgAutoSync) : p3ThreadedService(), p3Config(), mTransactionN(0), - mObserver(nxsObs), mDataStore(gds), mServType(servType), + mObserver(nxsObs), + mDataStore(gds), + mServType(servType), + mGixs(gixs), mTransactionTimeOut(TRANSAC_TIMEOUT), mNetMgr(netMgr), mNxsMutex("RsGxsNetService"), mSyncTs(0), mLastKeyPublishTs(0),mLastCleanRejectedMessages(0), mSYNC_PERIOD(SYNC_PERIOD), mCircles(circles), mReputations(reputations), mPgpUtils(pgpUtils), @@ -561,6 +588,23 @@ public: } }; +template +class RsGxsMetaDataTemporaryMapVector: public std::vector +{ +public: + virtual ~RsGxsMetaDataTemporaryMapVector() + { + clear() ; + } + + virtual void clear() + { + for(typename RsGxsMetaDataTemporaryMapVector::iterator it = this->begin();it!=this->end();++it) + if(it->second != NULL) + delete it->second ; + std::vector::clear() ; + } +}; void RsGxsNetService::syncWithPeers() { #ifdef NXS_NET_DEBUG_0 @@ -593,7 +637,7 @@ void RsGxsNetService::syncWithPeers() const RsGxsGrpUpdateItem *gui = cit->second; updateTS = gui->grpUpdateTS; } - RsNxsSyncGrp *grp = new RsNxsSyncGrp(mServType); + RsNxsSyncGrpReqItem *grp = new RsNxsSyncGrpReqItem(mServType); grp->clear(); grp->PeerId(*sit); grp->updateTS = updateTS; @@ -687,7 +731,7 @@ void RsGxsNetService::syncWithPeers() updateTS = cit2->second.time_stamp; } - RsNxsSyncMsg* msg = new RsNxsSyncMsg(mServType); + RsNxsSyncMsgReqItem* msg = new RsNxsSyncMsgReqItem(mServType); msg->clear(); msg->PeerId(peerId); msg->grpId = grpId; @@ -767,14 +811,14 @@ void RsGxsNetService::syncGrpStatistics() if(online_peers.find(peer_id) != online_peers.end()) // check that the peer is online { - #ifdef NXS_NET_DEBUG_6 GXSNETDEBUG_PG(peer_id,it->first) << " asking friend " << peer_id << " for an update of stats for group " << it->first << std::endl; #endif - RsNxsSyncGrpStats *grs = new RsNxsSyncGrpStats(mServType) ; + RsNxsSyncGrpStatsItem *grs = new RsNxsSyncGrpStatsItem(mServType) ; + + grs->request_type = RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_REQUEST ; - grs->request_type = RsNxsSyncGrpStats::GROUP_INFO_TYPE_REQUEST ; grs->grpId = it->first ; grs->PeerId(peer_id) ; @@ -789,9 +833,9 @@ void RsGxsNetService::syncGrpStatistics() } } -void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStats *grs) +void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs) { - if(grs->request_type == RsNxsSyncGrpStats::GROUP_INFO_TYPE_REQUEST) + if(grs->request_type == RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_REQUEST) { #ifdef NXS_NET_DEBUG_6 GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << "Received Grp update stats Request for group " << grs->grpId << " from friend " << grs->PeerId() << std::endl; @@ -837,8 +881,8 @@ void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStats *grs) if(vec.empty()) // that means we don't have any, or there isn't any, but since the default is always 0, no need to send. return ; - RsNxsSyncGrpStats *grs_resp = new RsNxsSyncGrpStats(mServType) ; - grs_resp->request_type = RsNxsSyncGrpStats::GROUP_INFO_TYPE_RESPONSE ; + RsNxsSyncGrpStatsItem *grs_resp = new RsNxsSyncGrpStatsItem(mServType) ; + grs_resp->request_type = RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_RESPONSE ; grs_resp->number_of_posts = vec.size(); grs_resp->grpId = grs->grpId; grs_resp->PeerId(grs->PeerId()) ; @@ -858,7 +902,7 @@ void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStats *grs) sendItem(grs_resp) ; } - else if(grs->request_type == RsNxsSyncGrpStats::GROUP_INFO_TYPE_RESPONSE) + else if(grs->request_type == RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_RESPONSE) { #ifdef NXS_NET_DEBUG_6 GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << "Received Grp update stats item from peer " << grs->PeerId() << " for group " << grs->grpId << ", reporting " << grs->number_of_posts << " posts." << std::endl; @@ -866,8 +910,8 @@ void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStats *grs) RS_STACK_MUTEX(mNxsMutex) ; RsGroupNetworkStatsRecord& rec(mGroupNetworkStats[grs->grpId]) ; - int32_t old_count = rec.max_visible_count ; - int32_t old_suppliers_count = rec.suppliers.size() ; + uint32_t old_count = rec.max_visible_count ; + uint32_t old_suppliers_count = rec.suppliers.size() ; rec.suppliers.insert(grs->PeerId()) ; rec.max_visible_count = std::max(rec.max_visible_count,grs->number_of_posts) ; @@ -1125,7 +1169,7 @@ void RsGxsNetService::locked_createTransactionFromPending( MsgRespPending* msgPe } if(!reqList.empty()) - locked_pushMsgTransactionFromList(reqList, msgPend->mPeerId, transN); + locked_pushMsgTransactionFromList(reqList, msgPend->mPeerId, transN) ; #ifdef NXS_NET_DEBUG_1 GXSNETDEBUG_P_(msgPend->mPeerId) << " added " << reqList.size() << " items to transaction." << std::endl; #endif @@ -1167,43 +1211,66 @@ void RsGxsNetService::locked_createTransactionFromPending(GrpRespPending* grpPen } -void RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) +bool RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) { #ifdef NXS_NET_DEBUG_1 GXSNETDEBUG_P_(grpPend->mPeerId) << "locked_createTransactionFromPending(GrpCircleIdReq)" << std::endl; #endif std::vector::iterator cit = grpPend->mGrpCircleV.begin(); - uint32_t transN = locked_getTransactionId(); - std::list itemL; - for(; cit != grpPend->mGrpCircleV.end(); ++cit) - { - const GrpIdCircleVet& entry = *cit; - if(entry.mCleared) - { + uint32_t transN = locked_getTransactionId(); + std::list itemL; + for(; cit != grpPend->mGrpCircleV.end(); ++cit) + { + const GrpIdCircleVet& entry = *cit; + + if(entry.mCleared) + { #ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " PASSED" << std::endl; + GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " PASSED" << std::endl; #endif - RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); - gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - gItem->grpId = entry.mGroupId; - gItem->publishTs = 0; - gItem->PeerId(grpPend->mPeerId); - gItem->transactionNumber = transN; - gItem->authorId = entry.mAuthorId; - // why it authorId not set here??? - itemL.push_back(gItem); - } + RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); + gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; + gItem->grpId = entry.mGroupId; + gItem->publishTs = 0; + gItem->PeerId(grpPend->mPeerId); + gItem->transactionNumber = transN; + gItem->authorId = entry.mAuthorId; + // why it authorId not set here??? + + if(entry.mShouldEncrypt) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " item for this grpId should be encrypted." << std::endl; +#endif + RsNxsItem *encrypted_item = NULL ; + uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; + + if(encryptSingleNxsItem(gItem, entry.mCircleId, encrypted_item,status)) + { + itemL.push_back(encrypted_item) ; + delete gItem ; + } +#ifdef NXS_NET_DEBUG_7 + else + GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Could not encrypt item for grpId " << entry.mGroupId << " for circle " << entry.mCircleId << ". Will try later. Adding to vetting list." << std::endl; +#endif + } + else + itemL.push_back(gItem); + } #ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " FAILED" << std::endl; + else + GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " FAILED" << std::endl; #endif } - if(!itemL.empty()) - locked_pushGrpRespFromList(itemL, grpPend->mPeerId, transN); + if(!itemL.empty()) + locked_pushGrpRespFromList(itemL, grpPend->mPeerId, transN); + + return true ; } -void RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVetting* msgPend) +bool RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVetting* msgPend) { std::vector::iterator vit = msgPend->mMsgs.begin(); std::list itemL; @@ -1214,21 +1281,40 @@ void RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVet for(; vit != msgPend->mMsgs.end(); ++vit) { MsgIdCircleVet& mic = *vit; - RsNxsSyncMsgItem* mItem = new - RsNxsSyncMsgItem(mServType); + RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType); mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; mItem->grpId = msgPend->mGrpId; mItem->msgId = mic.mMsgId; mItem->authorId = mic.mAuthorId; mItem->PeerId(msgPend->mPeerId); mItem->transactionNumber = transN; - itemL.push_back(mItem); - + grp_id = msgPend->mGrpId ; + + if(msgPend->mShouldEncrypt) + { + RsNxsItem *encrypted_item = NULL ; + uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; + + if(encryptSingleNxsItem(mItem,msgPend->mCircleId,encrypted_item,status)) + { + itemL.push_back(encrypted_item) ; + delete mItem ; + } + else + { + std::cerr << "(EE) cannot encrypt Msg ids in circle-restriced response to grp " << msgPend->mGrpId << " for circle " << msgPend->mCircleId << std::endl; + return false ; + } + } + else + itemL.push_back(mItem); } if(!itemL.empty()) locked_pushMsgRespFromList(itemL, msgPend->mPeerId,grp_id, transN); + + return true ; } /*bool RsGxsNetService::locked_canReceive(const RsGxsGrpMetaData * const grpMeta @@ -1478,7 +1564,7 @@ void RsGxsNetService::recvNxsItemQueue() while(NULL != (item=recvItem())) { #ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << "Received RsGxsNetService Item:" << (void*)item << std::endl ; + GXSNETDEBUG_P_(item->PeerId()) << "Received RsGxsNetService Item:" << (void*)item << " type=" << std::hex << item->PacketId() << std::dec << std::endl ; #endif // RsNxsItem needs dynamic_cast, since they have derived siblings. // @@ -1501,10 +1587,11 @@ void RsGxsNetService::recvNxsItemQueue() switch(ni->PacketSubType()) { - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS: handleRecvSyncGrpStatistics (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_SYNC_GRP: handleRecvSyncGroup (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_SYNC_MSG: handleRecvSyncMessage (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY: handleRecvPublishKeys (dynamic_cast(ni)) ; break ; + case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: handleRecvSyncGrpStatistics (dynamic_cast(ni)) ; break ; + case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: handleRecvSyncGroup (dynamic_cast(ni)) ; break ; + case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: handleRecvSyncMessage (dynamic_cast(ni)) ; break ; + case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM:handleRecvPublishKeys (dynamic_cast(ni)) ; break ; + default: std::cerr << "Unhandled item subtype " << (uint32_t) ni->PacketSubType() << " in RsGxsNetService: " << std::endl; break; } @@ -1535,7 +1622,7 @@ bool RsGxsNetService::handleTransaction(RsNxsItem* item) const RsPeerId& peer = item->PeerId(); - RsNxsTransac* transItem = dynamic_cast(item); + RsNxsTransacItem* transItem = dynamic_cast(item); // if this is a RsNxsTransac item process if(transItem) @@ -1577,7 +1664,7 @@ bool RsGxsNetService::handleTransaction(RsNxsItem* item) return false; } -bool RsGxsNetService::locked_processTransac(RsNxsTransac* item) +bool RsGxsNetService::locked_processTransac(RsNxsTransacItem *item) { /*! @@ -1599,7 +1686,7 @@ bool RsGxsNetService::locked_processTransac(RsNxsTransac* item) RsPeerId peer; // for outgoing transaction use own id - if(item->transactFlag & (RsNxsTransac::FLAG_BEGIN_P2 | RsNxsTransac::FLAG_END_SUCCESS)) + if(item->transactFlag & (RsNxsTransacItem::FLAG_BEGIN_P2 | RsNxsTransacItem::FLAG_END_SUCCESS)) peer = mOwnId; else peer = item->PeerId(); @@ -1626,7 +1713,7 @@ bool RsGxsNetService::locked_processTransac(RsNxsTransac* item) } // initiating an incoming transaction - if(item->transactFlag & RsNxsTransac::FLAG_BEGIN_P1) + if(item->transactFlag & RsNxsTransacItem::FLAG_BEGIN_P1) { #ifdef NXS_NET_DEBUG_1 GXSNETDEBUG_P_(peer) << " initiating Incoming transaction." << std::endl; @@ -1662,7 +1749,7 @@ bool RsGxsNetService::locked_processTransac(RsNxsTransac* item) return true; // commencement item for outgoing transaction } - else if(item->transactFlag & RsNxsTransac::FLAG_BEGIN_P2) + else if(item->transactFlag & RsNxsTransacItem::FLAG_BEGIN_P2) { #ifdef NXS_NET_DEBUG_1 GXSNETDEBUG_P_(peer) << " initiating outgoign transaction." << std::endl; @@ -1687,7 +1774,7 @@ bool RsGxsNetService::locked_processTransac(RsNxsTransac* item) return true; // end transac item for outgoing transaction } - else if(item->transactFlag & RsNxsTransac::FLAG_END_SUCCESS) + else if(item->transactFlag & RsNxsTransacItem::FLAG_END_SUCCESS) { #ifdef NXS_NET_DEBUG_1 @@ -1754,6 +1841,13 @@ void RsGxsNetService::debugDump() time_t now = time(NULL) ; GXSNETDEBUG___<< "RsGxsNetService::debugDump():" << std::endl; + + RsGxsMetaDataTemporaryMap grpMetas; + + if(!group_id_to_print.isNull()) + grpMetas[group_id_to_print] = NULL ; + + mDataStore->retrieveGxsGrpMetaData(grpMetas); if(mGrpServerUpdateItem != NULL) GXSNETDEBUG___<< " mGrpServerUpdateItem time stamp: " << nice_time_stamp(time(NULL) , mGrpServerUpdateItem->grpUpdateTS) << " (is the last local modification time over all groups of this service)" << std::endl; @@ -1763,7 +1857,13 @@ void RsGxsNetService::debugDump() GXSNETDEBUG___<< " mServerMsgUpdateMap: (is for each subscribed group, the last local modification time)" << std::endl; for(std::map::const_iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();++it) - GXSNETDEBUG__G(it->first) << " Grp:" << it->first << " last local modification (secs ago): " << nice_time_stamp(time(NULL),it->second->msgUpdateTS) << std::endl; + { + RsGxsMetaDataTemporaryMap::const_iterator it2 = grpMetas.find(it->first) ; + RsGxsGrpMetaData *grpMeta = (it2 != grpMetas.end())? it2->second : NULL; + std::string subscribe_string = (grpMeta==NULL)?"Unknown" : ((grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)?" Subscribed":" NOT Subscribed") ; + + GXSNETDEBUG__G(it->first) << " Grp:" << it->first << " last local modification (secs ago): " << nice_time_stamp(time(NULL),it->second->msgUpdateTS) << ", " << subscribe_string << std::endl; + } GXSNETDEBUG___<< " mClientGrpUpdateMap: (is for each friend, last modif time of group meta data at that friend, all groups included, sent by the friend himself)" << std::endl; @@ -1826,63 +1926,101 @@ void RsGxsNetService::updateClientSyncTS() void RsGxsNetService::updateServerSyncTS() { - RS_STACK_MUTEX(mNxsMutex) ; - RsGxsMetaDataTemporaryMap gxsMap; #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG___<< "updateServerSyncTS(): updating last modification time stamp of local data." << std::endl; #endif - // retrieve all grps and update TS - mDataStore->retrieveGxsGrpMetaData(gxsMap); + { + RS_STACK_MUTEX(mNxsMutex) ; + // retrieve all grps and update TS + mDataStore->retrieveGxsGrpMetaData(gxsMap); - // (cyril) This code was previously removed because it sounded inconsistent: the list of grps normally does not need to be updated when - // new posts arrive. The two (grp list and msg list) are handled independently. Still, when group meta data updates are received, - // the server TS needs to be updated, because it is the only way to propagate the changes. So we update it to the publish time stamp, - // if needed. - - // as a grp list server also note this is the latest item you have - if(mGrpServerUpdateItem == NULL) - mGrpServerUpdateItem = new RsGxsServerGrpUpdateItem(mServType); + // (cyril) This code was previously removed because it sounded inconsistent: the list of grps normally does not need to be updated when + // new posts arrive. The two (grp list and msg list) are handled independently. Still, when group meta data updates are received, + // the server TS needs to be updated, because it is the only way to propagate the changes. So we update it to the publish time stamp, + // if needed. - bool change = false; + // as a grp list server also note this is the latest item you have + if(mGrpServerUpdateItem == NULL) + mGrpServerUpdateItem = new RsGxsServerGrpUpdateItem(mServType); - // then remove from mServerMsgUpdateMap, all items that are not in the group list! - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << " cleaning server map of groups with no data:" << std::endl; -#endif - - for(std::map::iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();) - if(gxsMap.find(it->first) == gxsMap.end()) - { - // not found! Removing server update info for this group + // then remove from mServerMsgUpdateMap, all items that are not in the group list! #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(it->first) << " removing server update info for group " << it->first << std::endl; + GXSNETDEBUG___ << " cleaning server map of groups with no data:" << std::endl; #endif - std::map::iterator tmp(it) ; - ++tmp ; - mServerMsgUpdateMap.erase(it) ; - it = tmp ; - } - else - ++it; + + for(std::map::iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();) + if(gxsMap.find(it->first) == gxsMap.end()) + { + // not found! Removing server update info for this group + +#ifdef NXS_NET_DEBUG_0 + GXSNETDEBUG__G(it->first) << " removing server update info for group " << it->first << std::endl; +#endif + std::map::iterator tmp(it) ; + ++tmp ; + mServerMsgUpdateMap.erase(it) ; + it = tmp ; + } + else + ++it; + } #ifdef NXS_NET_DEBUG_0 if(gxsMap.empty()) GXSNETDEBUG___<< " database seems to be empty. The modification timestamp will be reset." << std::endl; #endif // finally, update timestamps. + bool change = false; for(std::map::const_iterator mit = gxsMap.begin();mit != gxsMap.end(); ++mit) { const RsGxsGroupId& grpId = mit->first; - const RsGxsGrpMetaData* grpMeta = mit->second; - ServerMsgMap::iterator mapIT = mServerMsgUpdateMap.find(grpId); - RsGxsServerMsgUpdateItem* msui = NULL; + // Check if the group is subscribed and restricted to a circle. If the circle has changed, update the + // global TS to reflect that change to clients who may be able to see/subscribe to that particular group. + + if( (mit->second->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) && !mit->second->mCircleId.isNull()) + { + // ask to the GxsNetService of circles what the server TS is for that circle. If more recent, we update the serverTS of the + // local group + + time_t circle_group_server_ts ; + time_t circle_msg_server_ts ; + + // This call needs to be off-mutex, because of self-restricted circles. + + if(mCircles->getLocalCircleServerUpdateTS(mit->second->mCircleId,circle_group_server_ts,circle_msg_server_ts)) + { +#ifdef NXS_NET_DEBUG_0 + GXSNETDEBUG__G(mit->first) << " Group " << mit->first << " is conditionned to circle " << mit->second->mCircleId << ". local Grp TS=" << time(NULL) - mGrpServerUpdateItem->grpUpdateTS << " secs ago, circle grp server update TS=" << time(NULL) - circle_group_server_ts << " secs ago"; +#endif + + if(circle_group_server_ts > mGrpServerUpdateItem->grpUpdateTS) + { +#ifdef NXS_NET_DEBUG_0 + GXSNETDEBUG__G(mit->first) << " - Updating local Grp Server update TS to follow changes in circles." << std::endl; +#endif + + RS_STACK_MUTEX(mNxsMutex) ; + mGrpServerUpdateItem->grpUpdateTS = circle_group_server_ts ; + } +#ifdef NXS_NET_DEBUG_0 + else + GXSNETDEBUG__G(mit->first) << " - Nothing to do." << std::endl; +#endif + } + else + std::cerr << "(EE) Cannot retrieve attached circle TS" << std::endl; + } + + RS_STACK_MUTEX(mNxsMutex) ; + + const RsGxsGrpMetaData* grpMeta = mit->second; + RsGxsServerMsgUpdateItem* msui = NULL; #ifdef TO_REMOVE // That accounts for modification of the meta data. @@ -1895,6 +2033,8 @@ void RsGxsNetService::updateServerSyncTS() } #endif + ServerMsgMap::iterator mapIT = mServerMsgUpdateMap.find(grpId); + if(mapIT == mServerMsgUpdateMap.end()) { msui = new RsGxsServerMsgUpdateItem(mServType); @@ -1942,24 +2082,25 @@ bool RsGxsNetService::locked_checkTransacTimedOut(NxsTransaction* tr) void RsGxsNetService::processTransactions() { -#ifdef NXS_NET_DEBUG_1 - if(!mTransactions.empty()) - GXSNETDEBUG___ << "processTransactions()" << std::endl; -#endif RS_STACK_MUTEX(mNxsMutex) ; - TransactionsPeerMap::iterator mit = mTransactions.begin(); - - for(; mit != mTransactions.end(); ++mit) + for(TransactionsPeerMap::iterator mit = mTransactions.begin();mit != mTransactions.end(); ++mit) { +#ifdef NXS_NET_DEBUG_1 + if(!mit->second.empty()) + GXSNETDEBUG_P_(mit->first) << "processTransactions from/to peer " << mit->first << std::endl; +#endif + TransactionIdMap& transMap = mit->second; TransactionIdMap::iterator mmit = transMap.begin(), mmit_end = transMap.end(); + if(mmit == mmit_end) // no waiting transactions for this peer + continue ; + #ifdef NXS_NET_DEBUG_1 - if(mmit != mmit_end) - GXSNETDEBUG_P_(mit->first) << " peerId=" << mit->first << std::endl; + GXSNETDEBUG_P_(mit->first) << " peerId=" << mit->first << std::endl; #endif - // transaction to be removed + // transaction to be removed std::list toRemove; /*! @@ -2113,23 +2254,40 @@ void RsGxsNetService::processTransactions() #endif // send completion msg - RsNxsTransac* trans = new RsNxsTransac(mServType); + RsNxsTransacItem* trans = new RsNxsTransacItem(mServType); trans->clear(); - trans->transactFlag = RsNxsTransac::FLAG_END_SUCCESS; + trans->transactFlag = RsNxsTransacItem::FLAG_END_SUCCESS; trans->transactionNumber = transN; trans->PeerId(tr->mTransaction->PeerId()); sendItem(trans); // move to completed transactions - mComplTransactions.push_back(tr); -#ifdef NXS_NET_DEBUG_1 - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - GXSNETDEBUG_P_(mit->first) << " incoming completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl; + + // Try to decrypt the items that need to be decrypted. This function returns true if the transaction is not encrypted. + + if(processTransactionForDecryption(tr)) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " successfully decrypted/processed transaction " << transN << ". Adding to completed list." << std::endl; #endif + mComplTransactions.push_back(tr); + + // transaction processing done + // for this id, add to removal list + toRemove.push_back(mmit->first); +#ifdef NXS_NET_DEBUG_1 + int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; + GXSNETDEBUG_P_(mit->first) << " incoming completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl; +#endif + } + else + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " no decryption occurred because of unloaded keys. Will retry later. TransN=" << transN << std::endl; +#endif + } + - // transaction processing done - // for this id, add to removal list - toRemove.push_back(mmit->first); } else if(flag & NxsTransaction::FLAG_STATE_STARTING) { @@ -2138,10 +2296,10 @@ void RsGxsNetService::processTransactions() GXSNETDEBUG_P_(mit->first) << " setting state to Receiving" << std::endl; #endif // send item to tell peer your are ready to start - RsNxsTransac* trans = new RsNxsTransac(mServType); + RsNxsTransacItem* trans = new RsNxsTransacItem(mServType); trans->clear(); - trans->transactFlag = RsNxsTransac::FLAG_BEGIN_P2 | - (tr->mTransaction->transactFlag & RsNxsTransac::FLAG_TYPE_MASK); + trans->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P2 | + (tr->mTransaction->transactFlag & RsNxsTransacItem::FLAG_TYPE_MASK); trans->transactionNumber = transN; trans->PeerId(tr->mTransaction->PeerId()); sendItem(trans); @@ -2229,7 +2387,7 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) #endif // for a completed list response transaction // one needs generate requests from this - if(flag & RsNxsTransac::FLAG_TYPE_MSG_LIST_RESP) + if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msg list response." << std::endl; @@ -2238,7 +2396,7 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) // generate request based on a peers response locked_genReqMsgTransaction(tr); - }else if(flag & RsNxsTransac::FLAG_TYPE_GRP_LIST_RESP) + }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = grp list response." << std::endl; @@ -2247,7 +2405,7 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) locked_genReqGrpTransaction(tr); } // you've finished receiving request information now gen - else if(flag & RsNxsTransac::FLAG_TYPE_MSG_LIST_REQ) + else if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msg list request." << std::endl; @@ -2255,7 +2413,7 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) #endif locked_genSendMsgsTransaction(tr); } - else if(flag & RsNxsTransac::FLAG_TYPE_GRP_LIST_REQ) + else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = grp list request." << std::endl; @@ -2263,7 +2421,7 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) #endif locked_genSendGrpsTransaction(tr); } - else if(flag & RsNxsTransac::FLAG_TYPE_GRPS) + else if(flag & RsNxsTransacItem::FLAG_TYPE_GRPS) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = groups." << std::endl; @@ -2324,7 +2482,8 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) IndicateConfigChanged(); - }else if(flag & RsNxsTransac::FLAG_TYPE_MSGS) + } + else if(flag & RsNxsTransacItem::FLAG_TYPE_MSGS) { std::vector msgs; @@ -2349,6 +2508,9 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) else std::cerr << "RsGxsNetService::processCompletedTransactions(): item did not caste to msg" << std::endl; } + +//#warning We need here to queue all incoming items into a list where the vetting will be checked +//#warning in order to avoid someone without the proper rights to post in a group protected with an external circle #ifdef NXS_FRAG // (cyril) This code does not work. Since we do not really need message fragmenting, I won't fix it. @@ -2397,7 +2559,7 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) return; } -void RsGxsNetService::locked_doMsgUpdateWork(const RsNxsTransac *nxsTrans, const RsGxsGroupId &grpId) +void RsGxsNetService::locked_doMsgUpdateWork(const RsNxsTransacItem *nxsTrans, const RsGxsGroupId &grpId) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_PG(nxsTrans->PeerId(),grpId) << "updating MsgUpdate time stamps for peerId=" << nxsTrans->PeerId() << ", grpId=" << grpId << std::endl; @@ -2406,6 +2568,13 @@ void RsGxsNetService::locked_doMsgUpdateWork(const RsNxsTransac *nxsTrans, const const RsPeerId& peerFrom = nxsTrans->PeerId(); ClientMsgMap::iterator it = mClientMsgUpdateMap.find(peerFrom); + + if(peerFrom.isNull()) + { + std::cerr << "(EE) update from null peer!" << std::endl; + print_stacktrace() ; + } + RsGxsMsgUpdateItem* mui = NULL; @@ -2446,7 +2615,7 @@ void RsGxsNetService::locked_processCompletedOutgoingTrans(NxsTransaction* tr) uint16_t flag = tr->mTransaction->transactFlag; #ifdef NXS_NET_DEBUG_0 - RsNxsTransac *nxsTrans = tr->mTransaction; + RsNxsTransacItem *nxsTrans = tr->mTransaction; GXSNETDEBUG_P_(nxsTrans->PeerId()) << "locked_processCompletedOutgoingTrans(): tr->flags = " << flag << std::endl; #endif @@ -2454,33 +2623,33 @@ void RsGxsNetService::locked_processCompletedOutgoingTrans(NxsTransaction* tr) { // for a completed list response transaction // one needs generate requests from this - if(flag & RsNxsTransac::FLAG_TYPE_MSG_LIST_RESP) + if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg List Response, transN: " << tr->mTransaction->transactionNumber << std::endl; #endif - }else if(flag & RsNxsTransac::FLAG_TYPE_GRP_LIST_RESP) + }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Grp Response, transN: " << tr->mTransaction->transactionNumber << std::endl; #endif } // you've finished sending a request so don't do anything - else if( (flag & RsNxsTransac::FLAG_TYPE_MSG_LIST_REQ) || - (flag & RsNxsTransac::FLAG_TYPE_GRP_LIST_REQ) ) + else if( (flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ) || + (flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ) ) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg/Grp Request, transN: " << tr->mTransaction->transactionNumber << std::endl; #endif - }else if(flag & RsNxsTransac::FLAG_TYPE_GRPS) + }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRPS) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Grp Data, transN: " << tr->mTransaction->transactionNumber << std::endl; #endif - }else if(flag & RsNxsTransac::FLAG_TYPE_MSGS) + }else if(flag & RsNxsTransacItem::FLAG_TYPE_MSGS) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg Data, transN: " << tr->mTransaction->transactionNumber << std::endl; @@ -2511,9 +2680,9 @@ void RsGxsNetService::locked_pushMsgTransactionFromList(std::list& r GXSNETDEBUG_P_ (peerId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending message request to peer " << peerId << " for " << reqList.size() << " messages" << std::endl; #endif - RsNxsTransac* transac = new RsNxsTransac(mServType); - transac->transactFlag = RsNxsTransac::FLAG_TYPE_MSG_LIST_REQ - | RsNxsTransac::FLAG_BEGIN_P1; + RsNxsTransacItem* transac = new RsNxsTransacItem(mServType); + transac->transactFlag = RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ + | RsNxsTransacItem::FLAG_BEGIN_P1; transac->timestamp = 0; transac->nItems = reqList.size(); transac->PeerId(peerId); @@ -2524,12 +2693,16 @@ void RsGxsNetService::locked_pushMsgTransactionFromList(std::list& r newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; // create transaction copy with your id to indicate // its an outgoing transaction - newTrans->mTransaction = new RsNxsTransac(*transac); + newTrans->mTransaction = new RsNxsTransacItem(*transac); newTrans->mTransaction->PeerId(mOwnId); - sendItem(transac); - if (!locked_addTransaction(newTrans)) + if (locked_addTransaction(newTrans)) + sendItem(transac); + else + { delete newTrans; + delete transac; + } #ifdef NXS_NET_DEBUG_1 GXSNETDEBUG_P_(peerId) << " Requested new transaction for " << reqList.size() << " items." << std::endl; @@ -2613,10 +2786,10 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr) // we never compare times from different (and potentially badly sync-ed clocks) std::cerr << "(EE) stepping in part of the code (" << __PRETTY_FUNCTION__ << ") where we shouldn't. This is a bug." << std::endl; + #ifdef TO_REMOVE locked_stampPeerGroupUpdateTime(pid,grpId,tr->mTransaction->updateTS,msgItemL.size()) ; #endif - return ; } @@ -2834,8 +3007,8 @@ void RsGxsNetService::locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const { pitem = new RsGxsMsgUpdateItem(mServType) ; pitem->peerId = pid ; - - mClientMsgUpdateMap[pid] = pitem ; + + mClientMsgUpdateMap[pid] = pitem ; } else pitem = it->second ; @@ -2858,9 +3031,9 @@ void RsGxsNetService::locked_pushGrpTransactionFromList( std::list& GXSNETDEBUG_P_ (peerId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending group request to peer " << peerId << " for " << reqList.size() << " groups" << std::endl; #endif - RsNxsTransac* transac = new RsNxsTransac(mServType); - transac->transactFlag = RsNxsTransac::FLAG_TYPE_GRP_LIST_REQ - | RsNxsTransac::FLAG_BEGIN_P1; + RsNxsTransacItem* transac = new RsNxsTransacItem(mServType); + transac->transactFlag = RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ + | RsNxsTransacItem::FLAG_BEGIN_P1; transac->timestamp = 0; transac->nItems = reqList.size(); transac->PeerId(peerId); @@ -2869,11 +3042,16 @@ void RsGxsNetService::locked_pushGrpTransactionFromList( std::list& newTrans->mItems = reqList; newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; - newTrans->mTransaction = new RsNxsTransac(*transac); + newTrans->mTransaction = new RsNxsTransacItem(*transac); newTrans->mTransaction->PeerId(mOwnId); - sendItem(transac); - if (!locked_addTransaction(newTrans)) - delete newTrans; + + if (locked_addTransaction(newTrans)) + sendItem(transac); + else + { + delete newTrans; + delete transac; + } } void RsGxsNetService::addGroupItemToList(NxsTransaction*& tr, const RsGxsGroupId& grpId, uint32_t& transN, std::list& reqList) { @@ -3090,27 +3268,37 @@ void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) GXSNETDEBUG_P_ (tr->mTransaction->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending global group TS " << updateTS << " to peer " << tr->mTransaction->PeerId() << std::endl; #endif - RsNxsTransac* ntr = new RsNxsTransac(mServType); + RsNxsTransacItem* ntr = new RsNxsTransacItem(mServType); ntr->transactionNumber = transN; - ntr->transactFlag = RsNxsTransac::FLAG_BEGIN_P1 | RsNxsTransac::FLAG_TYPE_GRPS; - ntr->updateTS = updateTS; + ntr->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | RsNxsTransacItem::FLAG_TYPE_GRPS; + ntr->updateTS = updateTS; ntr->nItems = grps.size(); ntr->PeerId(tr->mTransaction->PeerId()); - newTr->mTransaction = new RsNxsTransac(*ntr); + newTr->mTransaction = new RsNxsTransacItem(*ntr); newTr->mTransaction->PeerId(mOwnId); newTr->mTimeOut = time(NULL) + mTransactionTimeOut; ntr->PeerId(tr->mTransaction->PeerId()); - sendItem(ntr); - locked_addTransaction(newTr); + if(locked_addTransaction(newTr)) + sendItem(ntr); + else + { + delete ntr ; + delete newTr; + } return; } void RsGxsNetService::runVetting() { + // The vetting operation consists in transforming pending group/msg Id requests and grp/msg content requests + // into real transactions, based on the authorisations of the Peer Id these transactions are targeted to using the + // reputation system. + // + RS_STACK_MUTEX(mNxsMutex) ; std::vector::iterator vit = mPendingResp.begin(); @@ -3149,23 +3337,43 @@ void RsGxsNetService::runVetting() std::vector::iterator vit2 = mPendingCircleVets.begin(); for(; vit2 != mPendingCircleVets.end(); ) { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG___ << " Examining/clearing pending vetting of type " << (*vit2)->getType() << std::endl; +#endif GrpCircleVetting*& gcv = *vit2; if(gcv->cleared() || gcv->expired()) { if(gcv->getType() == GrpCircleVetting::GRP_ID_PEND) { - GrpCircleIdRequestVetting* gcirv = - static_cast(gcv); + GrpCircleIdRequestVetting* gcirv = static_cast(gcv); +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_P_(gcirv->mPeerId) << " vetting is a GRP ID PENDING Response" << std::endl; +#endif - locked_createTransactionFromPending(gcirv); + if(!locked_createTransactionFromPending(gcirv)) + { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_P_(gcirv->mPeerId) << " Response sent!" << std::endl; +#endif + ++vit2 ; + continue ; + } } else if(gcv->getType() == GrpCircleVetting::MSG_ID_SEND_PEND) { - MsgCircleIdsRequestVetting* mcirv = - static_cast(gcv); + MsgCircleIdsRequestVetting* mcirv = static_cast(gcv); +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_P_(mcirv->mPeerId) << " vetting is a MSG ID PENDING Response" << std::endl; +#endif if(mcirv->cleared()) - locked_createTransactionFromPending(mcirv); + { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_P_(mcirv->mPeerId) << " vetting cleared! Sending..." << std::endl; +#endif + if(!locked_createTransactionFromPending(mcirv)) + continue ; // keep it in the list for retry + } } else { @@ -3179,6 +3387,9 @@ void RsGxsNetService::runVetting() } else { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG___ << " ... not cleared yet." << std::endl; +#endif ++vit2; } } @@ -3186,132 +3397,194 @@ void RsGxsNetService::runVetting() void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr) { - #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genSendMsgsTransaction() Generating Msg data send fron TransN: " << tr->mTransaction->transactionNumber << std::endl; + GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genSendMsgsTransaction() Generating Msg data send fron TransN: " << tr->mTransaction->transactionNumber << std::endl; #endif - // go groups requested in transaction tr + // go groups requested in transaction tr - std::list::iterator lit = tr->mItems.begin(); + std::list::iterator lit = tr->mItems.begin(); - GxsMsgReq msgIds; - GxsMsgResult msgs; + GxsMsgReq msgIds; + GxsMsgResult msgs; - if(tr->mItems.empty()){ - return; - } + if(tr->mItems.empty()){ + return; + } - // hacky assumes a transaction only consist of a single grpId - RsGxsGroupId grpId; + // hacky assumes a transaction only consist of a single grpId + RsGxsGroupId grpId; - for(;lit != tr->mItems.end(); ++lit) - { - RsNxsSyncMsgItem* item = dynamic_cast(*lit); - if (item) - { - msgIds[item->grpId].push_back(item->msgId); + for(;lit != tr->mItems.end(); ++lit) + { + RsNxsSyncMsgItem* item = dynamic_cast(*lit); + if (item) + { + msgIds[item->grpId].push_back(item->msgId); - if(grpId.isNull()) - grpId = item->grpId; - } - else - { + if(grpId.isNull()) + grpId = item->grpId; + else if(grpId != item->grpId) + { + std::cerr << "RsGxsNetService::locked_genSendMsgsTransaction(): transaction on two different groups! ERROR!" << std::endl; + return ; + } + } + else + { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << "RsGxsNetService::locked_genSendMsgsTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl; + GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << "RsGxsNetService::locked_genSendMsgsTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl; #endif - } - } + } + } + +#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA + // now if transaction is limited to an external group, encrypt it for members of the group. - mDataStore->retrieveNxsMsgs(msgIds, msgs, false, false); + RsGxsCircleId encryption_circle ; + std::map grp; + grp[grpId] = NULL ; - NxsTransaction* newTr = new NxsTransaction(); - newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; + mDataStore->retrieveGxsGrpMetaData(grp); - uint32_t transN = locked_getTransactionId(); + RsGxsGrpMetaData *grpMeta = grp[grpId] ; - // store msg items to send in transaction - GxsMsgResult::iterator mit = msgs.begin(); - RsPeerId peerId = tr->mTransaction->PeerId(); - uint32_t msgSize = 0; + if(grpMeta == NULL) + { + std::cerr << "(EE) cannot retrieve group meta data for message transaction " << tr->mTransaction->transactionNumber << std::endl; + return ; + } - for(;mit != msgs.end(); ++mit) - { - std::vector& msgV = mit->second; - std::vector::iterator vit = msgV.begin(); + encryption_circle = grpMeta->mCircleId ; + delete grpMeta ; + grp.clear() ; +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Msg transaction items will be encrypted for circle " << std::endl; +#endif +#endif - for(; vit != msgV.end(); ++vit) - { - RsNxsMsg* msg = *vit; - msg->PeerId(peerId); - msg->transactionNumber = transN; - - // Quick trick to clamp messages with an exceptionnally large size. Signature will fail on client side, and the message - // will be rejected. - - if(msg->msg.bin_len > MAX_ALLOWED_GXS_MESSAGE_SIZE) - { - std::cerr << "(WW) message with ID " << msg->msgId << " in group " << msg->grpId << " exceeds size limit of " << MAX_ALLOWED_GXS_MESSAGE_SIZE << " bytes. Actual size is " << msg->msg.bin_len << " bytes. Message will be truncated and rejected at client." << std::endl; - msg->msg.bin_len = 1 ; // arbitrary small size, but not 0. No need to send the data since it's going to be rejected. - } -#ifdef NXS_FRAG - MsgFragments fragments; - fragmentMsg(*msg, fragments); - - delete msg ; + mDataStore->retrieveNxsMsgs(msgIds, msgs, false, false); - MsgFragments::iterator mit = fragments.begin(); + NxsTransaction* newTr = new NxsTransaction(); + newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - for(; mit != fragments.end(); ++mit) - { - newTr->mItems.push_back(*mit); - msgSize++; - } + uint32_t transN = locked_getTransactionId(); + + // store msg items to send in transaction + GxsMsgResult::iterator mit = msgs.begin(); + RsPeerId peerId = tr->mTransaction->PeerId(); + uint32_t msgSize = 0; + + for(;mit != msgs.end(); ++mit) + { + std::vector& msgV = mit->second; + std::vector::iterator vit = msgV.begin(); + + for(; vit != msgV.end(); ++vit) + { + RsNxsMsg* msg = *vit; + msg->PeerId(peerId); + msg->transactionNumber = transN; + + // Quick trick to clamp messages with an exceptionnally large size. Signature will fail on client side, and the message + // will be rejected. + + if(msg->msg.bin_len > MAX_ALLOWED_GXS_MESSAGE_SIZE) + { + std::cerr << "(WW) message with ID " << msg->msgId << " in group " << msg->grpId << " exceeds size limit of " << MAX_ALLOWED_GXS_MESSAGE_SIZE << " bytes. Actual size is " << msg->msg.bin_len << " bytes. Message will be truncated and rejected at client." << std::endl; + msg->msg.bin_len = 1 ; // arbitrary small size, but not 0. No need to send the data since it's going to be rejected. + } + +#ifdef NXS_FRAG + MsgFragments fragments; + fragmentMsg(*msg, fragments); + + delete msg ; + + MsgFragments::iterator mit = fragments.begin(); + + for(; mit != fragments.end(); ++mit) + { + newTr->mItems.push_back(*mit); + msgSize++; + } #else - msg->count = 1; // only one piece. This is to keep compatibility if we ever implement fragmenting in the future. - msg->pos = 0; + + msg->count = 1; // only one piece. This is to keep compatibility if we ever implement fragmenting in the future. + msg->pos = 0; - newTr->mItems.push_back(msg); - msgSize++; -#endif + newTr->mItems.push_back(msg); + msgSize++; +#endif - } - } +#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA + // encrypt - if(newTr->mItems.empty()){ - delete newTr; - return; - } + if(!encryption_circle.isNull()) + { + uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - uint32_t updateTS = 0; + RsNxsEncryptedDataItem encrypted_msg_item = NULL ; - ServerMsgMap::const_iterator cit = mServerMsgUpdateMap.find(grpId); + if(encryptSingleNxsItem(msg,encryption_circle,encrypted_msg_item,status)) + { + newTr->mItems.push_back(msg); + delete msg ; + } + else + { + } + } + else + { + newTr->mItems.push_back(msg); - if(cit != mServerMsgUpdateMap.end()) - updateTS = cit->second->msgUpdateTS; + msgSize++; + } +#endif + } + } - RsNxsTransac* ntr = new RsNxsTransac(mServType); - ntr->transactionNumber = transN; - ntr->transactFlag = RsNxsTransac::FLAG_BEGIN_P1 | - RsNxsTransac::FLAG_TYPE_MSGS; - ntr->updateTS = updateTS; - ntr->nItems = msgSize; - ntr->PeerId(peerId); + if(newTr->mItems.empty()){ + delete newTr; + return; + } - newTr->mTransaction = new RsNxsTransac(*ntr); - newTr->mTransaction->PeerId(mOwnId); + // now send a transaction item and store the transaction data + + uint32_t updateTS = 0; + ServerMsgMap::const_iterator cit = mServerMsgUpdateMap.find(grpId); + + if(cit != mServerMsgUpdateMap.end()) + updateTS = cit->second->msgUpdateTS; + + RsNxsTransacItem* ntr = new RsNxsTransacItem(mServType); + ntr->transactionNumber = transN; + ntr->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | + RsNxsTransacItem::FLAG_TYPE_MSGS; + ntr->updateTS = updateTS; + ntr->nItems = msgSize; + ntr->PeerId(peerId); + + newTr->mTransaction = new RsNxsTransacItem(*ntr); + newTr->mTransaction->PeerId(mOwnId); newTr->mTimeOut = time(NULL) + mTransactionTimeOut; #ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_PG (peerId,grpId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending message update to peer " - << peerId << " for group " << grpId << " with TS=" << nice_time_stamp(time(NULL),updateTS) <<" (secs ago)" << std::endl; + GXSNETDEBUG_PG (peerId,grpId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending message update to peer " << peerId << " for group " << grpId << " with TS=" << nice_time_stamp(time(NULL),updateTS) <<" (secs ago)" << std::endl; + #endif - ntr->PeerId(tr->mTransaction->PeerId()); - sendItem(ntr); + ntr->PeerId(tr->mTransaction->PeerId()); - locked_addTransaction(newTr); + if(locked_addTransaction(newTr)) + sendItem(ntr); + else + { + delete ntr ; + delete newTr; + } - return; + return; } uint32_t RsGxsNetService::locked_getTransactionId() { @@ -3319,27 +3592,249 @@ uint32_t RsGxsNetService::locked_getTransactionId() } bool RsGxsNetService::locked_addTransaction(NxsTransaction* tr) { - const RsPeerId& peer = tr->mTransaction->PeerId(); - uint32_t transN = tr->mTransaction->transactionNumber; - TransactionIdMap& transMap = mTransactions[peer]; - bool transNumExist = transMap.find(transN) - != transMap.end(); - - - if(transNumExist){ + const RsPeerId& peer = tr->mTransaction->PeerId(); #ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << "locked_addTransaction() " << std::endl; - GXSNETDEBUG_P_(peer) << "Transaction number exist already, transN: " << transN << std::endl; + GXSNETDEBUG_P_(peer) << "locked_addTransaction() " << std::endl; #endif - return false; - }else{ + uint32_t transN = tr->mTransaction->transactionNumber; + TransactionIdMap& transMap = mTransactions[peer]; + bool transNumExist = transMap.find(transN) != transMap.end(); + + if(transNumExist) + { #ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << "locked_addTransaction() " << std::endl; - GXSNETDEBUG_P_(peer) << "Added transaction number " << transN << std::endl; + GXSNETDEBUG_P_(peer) << " Transaction number exist already, transN: " << transN << std::endl; #endif - transMap[transN] = tr; - return true; + return false; + } + + transMap[transN] = tr; + + return true; +} + +// Turns a single RsNxsItem into an encrypted one, suitable for the supplied destination circle. +// Returns false when the keys are not loaded. Question to solve: what do we do if we miss some keys?? +// We should probably send anyway. + +bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *&encrypted_item, uint32_t& status) +{ + encrypted_item = NULL ; + status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_ (item->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Encrypting single item for peer " << item->PeerId() << ", for circle ID " << destination_circle << std::endl; +#endif + std::cerr << "RsGxsNetService::encryptSingleNxsItem()" << std::endl; + + // 1 - Find out the list of GXS ids to encrypt for + // We could do smarter things (like see if the peer_id owns one of the circle's identities + // but for now we aim at the simplest solution: encrypt for all identities in the circle. + + std::list recipients ; + + if(!mCircles->recipients(destination_circle,recipients)) + { + std::cerr << " (EE) Cannot encrypt transaction: recipients list not available. Should re-try later." << std::endl; + status = RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR ; + return false ; } + + if(recipients.empty()) + { + std::cerr << " (EE) No recipients found for circle " << destination_circle << ". Circle not in cache, or empty circle?" << std::endl; + return false ; + } + +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_ (item->PeerId()) << " Dest Ids: " << std::endl; +#endif + std::vector recipient_keys ; + + for(std::list::const_iterator it(recipients.begin());it!=recipients.end();++it) + { + RsTlvSecurityKey pkey ; + + if(!mGixs->getKey(*it,pkey)) + { + std::cerr << " (EE) Cannot retrieve public key " << *it << " for circle encryption. Should retry later?" << std::endl; + + // we should probably request the key? + status = RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING ; + continue ; + } +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_ (item->PeerId()) << " added key " << *it << std::endl; +#endif + recipient_keys.push_back(pkey) ; + } + + // 2 - call GXSSecurity to make a header item that encrypts for the given list of peers. + +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_ (item->PeerId()) << " Encrypting..." << std::endl; +#endif + uint32_t size = item->serial_size() ; + RsTemporaryMemory tempmem( size ) ; + + if(!item->serialise(tempmem,size)) + { + std::cerr << " (EE) Cannot serialise item. Something went wrong." << std::endl; + status = RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR ; + return false ; + } + + unsigned char *encrypted_data = NULL ; + uint32_t encrypted_len = 0 ; + + if(!GxsSecurity::encrypt(encrypted_data, encrypted_len,tempmem,size,recipient_keys)) + { + std::cerr << " (EE) Cannot multi-encrypt item. Something went wrong." << std::endl; + status = RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR ; + return false ; + } + + RsNxsEncryptedDataItem *enc_item = new RsNxsEncryptedDataItem(mServType) ; + + enc_item->encrypted_data.bin_len = encrypted_len ; + enc_item->encrypted_data.bin_data = encrypted_data ; + + // also copy all the important data. + + enc_item->transactionNumber = item->transactionNumber ; + enc_item->PeerId(item->PeerId()) ; + + encrypted_item = enc_item ; +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(item->PeerId()) << " encrypted item of size " << encrypted_len << std::endl; +#endif + status = RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR ; + + return true ; +} + +// Tries to decrypt the transaction. First load the keys and process all items. +// If keys are loaded, encrypted items that cannot be decrypted are discarded. +// Otherwise the transaction is untouched for retry later. + +bool RsGxsNetService::processTransactionForDecryption(NxsTransaction *tr) +{ +#ifdef NXS_NET_DEBUG_7 + RsPeerId peerId = tr->mTransaction->PeerId() ; + GXSNETDEBUG_P_(peerId) << "RsGxsNetService::decryptTransaction()" << std::endl; +#endif + + std::list decrypted_items ; + std::vector private_keys ; + + // get all private keys. Normally we should look into the circle name and only supply the keys that we have + + for(std::list::iterator it(tr->mItems.begin());it!=tr->mItems.end();) + { + RsNxsEncryptedDataItem *encrypted_item = dynamic_cast(*it) ; + + if(encrypted_item == NULL) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(peerId) << " skipping unencrypted item..." << std::endl; +#endif + ++it ; + continue ; + } + + // we need the private keys to decrypt the item. First load them in! + bool key_loading_failed = false ; + + if(private_keys.empty()) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(peerId) << " need to retrieve private keys..." << std::endl; +#endif + + std::list own_keys ; + mGixs->getOwnIds(own_keys) ; + + for(std::list::const_iterator it(own_keys.begin());it!=own_keys.end();++it) + { + RsTlvSecurityKey private_key ; + + if(mGixs->getPrivateKey(*it,private_key)) + { + private_keys.push_back(private_key) ; +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(peerId)<< " retrieved private key " << *it << std::endl; +#endif + } + else + { + std::cerr << " (EE) Cannot retrieve private key for ID " << *it << std::endl; + key_loading_failed = true ; + break ; + } + } + } + if(key_loading_failed) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(peerId) << " Some keys not loaded.Returning false to retry later." << std::endl; +#endif + return false ; + } + + // we do this only when something actually needs to be decrypted. + + unsigned char *decrypted_mem = NULL; + uint32_t decrypted_len =0; + +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(peerId)<< " Trying to decrypt item..." ; +#endif + + if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->encrypted_data.bin_data,encrypted_item->encrypted_data.bin_len,private_keys)) + { + std::cerr << "Failed! Cannot decrypt this item." << std::endl; + decrypted_mem = NULL ; // for safety + } +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(peerId)<< " Succeeded! deserialising..." << std::endl; +#endif + + // deserialise the item + + + RsItem *ditem = NULL ; + RsNxsItem *nxsitem = NULL ; + + if(decrypted_mem!=NULL) + { + ditem = RsNxsSerialiser(mServType).deserialise(decrypted_mem,&decrypted_len) ; + + if(ditem != NULL) + { + ditem->PeerId((*it)->PeerId()) ; // This is needed because the deserialised item has no peer id + nxsitem = dynamic_cast(ditem) ; + } + else + std::cerr << " Cannot deserialise. Item encoding error!" << std::endl; + + if(nxsitem == NULL) + std::cerr << " (EE) Deserialised item is not an NxsItem. Weird. Dropping transaction." << std::endl; + } + + // remove the encrypted item. After that it points to the next item to handle + it = tr->mItems.erase(it) ; + + if(nxsitem != NULL) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_P_(peerId) << " Replacing the encrypted item with the clear one." << std::endl; +#endif + tr->mItems.insert(it,nxsitem) ; // inserts before it, so no need to ++it + } + + delete encrypted_item ; + } + + return true ; } void RsGxsNetService::cleanTransactionItems(NxsTransaction* tr) const @@ -3366,9 +3861,9 @@ void RsGxsNetService::locked_pushGrpRespFromList(std::list& respList tr->mItems = respList; tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - RsNxsTransac* trItem = new RsNxsTransac(mServType); - trItem->transactFlag = RsNxsTransac::FLAG_BEGIN_P1 - | RsNxsTransac::FLAG_TYPE_GRP_LIST_RESP; + RsNxsTransacItem* trItem = new RsNxsTransacItem(mServType); + trItem->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 + | RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP; trItem->nItems = respList.size(); trItem->timestamp = 0; trItem->PeerId(peer); @@ -3378,7 +3873,7 @@ void RsGxsNetService::locked_pushGrpRespFromList(std::list& respList #endif trItem->updateTS = mGrpServerUpdateItem->grpUpdateTS; // also make a copy for the resident transaction - tr->mTransaction = new RsNxsTransac(*trItem); + tr->mTransaction = new RsNxsTransacItem(*trItem); tr->mTransaction->PeerId(mOwnId); tr->mTimeOut = time(NULL) + mTransactionTimeOut; // signal peer to prepare for transaction @@ -3386,11 +3881,16 @@ void RsGxsNetService::locked_pushGrpRespFromList(std::list& respList GXSNETDEBUG_P_ (peer) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending group response to peer " << peer << " with " << respList.size() << " groups " << std::endl; #endif - sendItem(trItem); - locked_addTransaction(tr); + if(locked_addTransaction(tr)) + sendItem(trItem); + else + { + delete tr ; + delete trItem ; + } } -bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncGrp *item) +bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncGrpReqItem *item) { // Do we have new updates for this peer? @@ -3413,94 +3913,126 @@ bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncGrp *item) return false; } -void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrp* item) +void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item) { - if (!item) - return; + if (!item) + return; - RS_STACK_MUTEX(mNxsMutex) ; + RS_STACK_MUTEX(mNxsMutex) ; - RsPeerId peer = item->PeerId(); + RsPeerId peer = item->PeerId(); #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << "HandleRecvSyncGroup(): Service: " << mServType << " from " << peer << ", Last update TS (from myself) sent from peer is T = " << std::dec<< time(NULL) - item->updateTS << " secs ago" << std::endl; + GXSNETDEBUG_P_(peer) << "HandleRecvSyncGroup(): Service: " << mServType << " from " << peer << ", Last update TS (from myself) sent from peer is T = " << std::dec<< time(NULL) - item->updateTS << " secs ago" << std::endl; #endif - if(!locked_CanReceiveUpdate(item)) - { + if(!locked_CanReceiveUpdate(item)) + { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() update will not be sent." << std::endl; + GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() update will not be sent." << std::endl; #endif - return; - } + return; + } - RsGxsMetaDataTemporaryMap grp; - mDataStore->retrieveGxsGrpMetaData(grp); + RsGxsMetaDataTemporaryMap grp; + mDataStore->retrieveGxsGrpMetaData(grp); #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() retrieving local list of groups..." << std::endl; + GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() retrieving local list of groups..." << std::endl; #endif - if(grp.empty()) - { + if(grp.empty()) + { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() Grp Empty" << std::endl; + GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() Grp Empty" << std::endl; #endif - return; - } + return; + } - std::list itemL; + std::list itemL; - uint32_t transN = locked_getTransactionId(); + uint32_t transN = locked_getTransactionId(); - std::vector toVet; + std::vector toVet; #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " Group list beings being sent: " << std::endl; + GXSNETDEBUG_P_(peer) << " Group list beings being sent: " << std::endl; #endif - for(std::map::iterator mit = grp.begin(); mit != grp.end(); ++mit) - { - RsGxsGrpMetaData* grpMeta = mit->second; + for(std::map::iterator mit = grp.begin(); mit != grp.end(); ++mit) + { + RsGxsGrpMetaData* grpMeta = mit->second; - // Only send info about subscribed groups. + // Only send info about subscribed groups. - if(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { + if(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { - // check if you can send this id to peer - // or if you need to add to the holding - // pen for peer to be vetted - if(canSendGrpId(peer, *grpMeta, toVet)) - { - RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); - gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - gItem->grpId = mit->first; - gItem->publishTs = mit->second->mPublishTs; - gItem->authorId = grpMeta->mAuthorId; - gItem->PeerId(peer); - gItem->transactionNumber = transN; - itemL.push_back(gItem); + // check if you can send this id to peer + // or if you need to add to the holding + // pen for peer to be vetted + + bool should_encrypt = false ; + + if(canSendGrpId(peer, *grpMeta, toVet,should_encrypt)) + { + RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); + gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; + gItem->grpId = mit->first; + gItem->publishTs = mit->second->mPublishTs; + gItem->authorId = grpMeta->mAuthorId; + gItem->PeerId(peer); + gItem->transactionNumber = transN; + + if(should_encrypt) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_PG(peer,mit->first) << " item for this grpId should be encrypted." << std::endl; +#endif + RsNxsItem *encrypted_item = NULL ; + uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; + + if(encryptSingleNxsItem(gItem, grpMeta->mCircleId, encrypted_item,status)) + { + itemL.push_back(encrypted_item) ; + delete gItem ; + } + else + { + switch(status) + { + case RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR: + case RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING: toVet.push_back(GrpIdCircleVet(grpMeta->mGroupId, grpMeta->mCircleId, grpMeta->mAuthorId)); +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_PG(peer,mit->first) << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Will try later. Adding to vetting list." << std::endl; +#endif + break ; + default: + std::cerr << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Not sending it." << std::endl; + } + } + } + else + itemL.push_back(gItem); + #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(peer,mit->first) << " sending item for Grp " << mit->first << " name=" << grpMeta->mGroupName << ", publishTS=" << std::dec<< time(NULL) - mit->second->mPublishTs << " secs ago to peer ID " << peer << std::endl; + GXSNETDEBUG_PG(peer,mit->first) << " sending item for Grp " << mit->first << " name=" << grpMeta->mGroupName << ", publishTS=" << std::dec<< time(NULL) - mit->second->mPublishTs << " secs ago to peer ID " << peer << std::endl; #endif - } - } - } + } + } + } - if(!toVet.empty()) - { - mPendingCircleVets.push_back(new GrpCircleIdRequestVetting(mCircles, mPgpUtils, toVet, peer)); - } + if(!toVet.empty()) + mPendingCircleVets.push_back(new GrpCircleIdRequestVetting(mCircles, mPgpUtils, toVet, peer)); #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " final list sent (after vetting): " << itemL.size() << " elements." << std::endl; + GXSNETDEBUG_P_(peer) << " final list sent (after vetting): " << itemL.size() << " elements." << std::endl; #endif - locked_pushGrpRespFromList(itemL, peer, transN); + locked_pushGrpRespFromList(itemL, peer, transN); - return; + return; } -bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector& toVet) +bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector& toVet, bool& should_encrypt) { #ifdef NXS_NET_DEBUG_4 GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId()"<< std::endl; @@ -3511,7 +4043,7 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM if(circleType == GXS_CIRCLE_TYPE_LOCAL) { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< "RsGxsNetService::canSendGrpId() LOCAL_CIRCLE, cannot send"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " LOCAL_CIRCLE, cannot send"<< std::endl; #endif return false; } @@ -3519,17 +4051,24 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM if(circleType == GXS_CIRCLE_TYPE_PUBLIC) { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< "RsGxsNetService::canSendGrpId() PUBLIC_CIRCLE, can send"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " PUBLIC_CIRCLE, can send"<< std::endl; #endif return true; } if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " EXTERNAL_CIRCLE, will be sent encrypted."<< std::endl; +#endif + should_encrypt = true ; + return true ; + +#ifdef TO_BE_REMOVED_OLD_VETTING_FOR_EXTERNAL_CIRCLES const RsGxsCircleId& circleId = grpMeta.mCircleId; if(circleId.isNull()) { - std::cerr << "RsGxsNetService::canSendGrpId() ERROR; EXTERNAL_CIRCLE missing NULL CircleId: " << grpMeta.mGroupId<< std::endl; + std::cerr << " EXTERNAL_CIRCLE missing NULL CircleId: " << grpMeta.mGroupId<< std::endl; // ERROR, will never be shared. return false; @@ -3538,20 +4077,32 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM if(mCircles->isLoaded(circleId)) { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< "RsGxsNetService::canSendGrpId() EXTERNAL_CIRCLE, checking mCircles->canSend"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " EXTERNAL_CIRCLE, checking mCircles->canSend"<< std::endl; #endif + // the sending authorisation is based on: + // getPgpId(peer_id) being a signer of one GxsId in the Circle + // const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId); - return mCircles->canSend(circleId, pgpId); + + bool res = mCircles->canSend(circleId, pgpId); +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " answer is: " << res << std::endl; +#endif + return res ; } +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " grp not ready. Adding to vetting list." << std::endl; +#endif toVet.push_back(GrpIdCircleVet(grpMeta.mGroupId, circleId, grpMeta.mAuthorId)); return false; +#endif } if(circleType == GXS_CIRCLE_TYPE_YOUREYESONLY) { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< "RsGxsNetService::canSendGrpId() YOUREYESONLY, checking further"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " YOUREYESONLY, checking further"<< std::endl; #endif // a non empty internal circle id means this // is the personal circle owner @@ -3559,22 +4110,28 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM { const RsGxsCircleId& internalCircleId = grpMeta.mInternalCircle; #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() have mInternalCircle - we are Group creator" << std::endl; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() mCircleId: " << grpMeta.mCircleId << std::endl; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() mInternalCircle: " << grpMeta.mInternalCircle << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " have mInternalCircle - we are Group creator" << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " mCircleId: " << grpMeta.mCircleId << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " mInternalCircle: " << grpMeta.mInternalCircle << std::endl; #endif if(mCircles->isLoaded(internalCircleId)) { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() circle Loaded - checking mCircles->canSend" << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " circle Loaded - checking mCircles->canSend" << std::endl; #endif const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId); - return mCircles->canSend(internalCircleId, pgpId); + bool should_encrypt = false ; + + bool res = mCircles->canSend(internalCircleId, pgpId,should_encrypt); +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " answer is: " << res << std::endl; +#endif + return res ; } #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() Circle Not Loaded - add to vetting"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle Not Loaded - add to vetting"<< std::endl; #endif toVet.push_back(GrpIdCircleVet(grpMeta.mGroupId, internalCircleId, grpMeta.mAuthorId)); return false; @@ -3584,19 +4141,19 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM // an empty internal circle id means this peer can only // send circle related info from peer he received it #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() mInternalCircle not set, someone else's personal circle"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " mInternalCircle not set, someone else's personal circle"<< std::endl; #endif if(grpMeta.mOriginator == sslId) { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() Originator matches -> can send"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Originator matches -> can send"<< std::endl; #endif return true; } else { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId() Originator doesn't match -> cannot send"<< std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Originator doesn't match -> cannot send"<< std::endl; #endif return false; } @@ -3634,6 +4191,11 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs will be encrypted." << std::endl; +#endif + return true ; +#ifdef TO_BE_REMOVED_OLD_VETTING_FOR_EXTERNAL_CIRCLES const RsGxsCircleId& circleId = grpMeta.mCircleId; if(circleId.isNull()) { @@ -3660,6 +4222,7 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs mCircles->loadCircle(circleId); // simply request for next pass return false; +#endif } if(circleType == GXS_CIRCLE_TYPE_YOUREYESONLY) // do not attempt to sync msg unless to originator or those permitted @@ -3684,7 +4247,8 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " circle Loaded - checking mCircles->canSend" << std::endl; #endif const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId); - return mCircles->canSend(internalCircleId, pgpId); + bool should_encrypt ; + return mCircles->canSend(internalCircleId, pgpId,should_encrypt); } else mCircles->loadCircle(internalCircleId); // request for next pass @@ -3718,7 +4282,7 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs return true; } -bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncMsg *item) +bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncMsgReqItem *item) { // Do we have new updates for this peer? // Here we compare times in the same clock: the friend's clock, so it should be fine. @@ -3730,17 +4294,17 @@ bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncMsg *item) const RsGxsServerMsgUpdateItem *msui = cit->second; #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " local time stamp: " << std::dec<< time(NULL) - msui->msgUpdateTS << " secs ago. Update sent: " << (item->updateTS < msui->msgUpdateTS) ; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " local time stamp: " << std::dec<< time(NULL) - msui->msgUpdateTS << " secs ago. Update sent: " << (item->updateTS < msui->msgUpdateTS) << std::endl; #endif return item->updateTS < msui->msgUpdateTS ; } #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no local time stamp for this grp. " ; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no local time stamp for this grp. "<< std::endl; #endif return false; } -void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsg* item) +void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item) { if (!item) return; @@ -3760,97 +4324,128 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsg* item) GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "handleRecvSyncMsg(): Received last update TS of group " << item->grpId << ", for peer " << peer << ", TS = " << time(NULL) - item->updateTS << " secs ago." ; #endif - if(!locked_CanReceiveUpdate(item)) + if(!locked_CanReceiveUpdate(item)) { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no update will be sent." << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no update will be sent." << std::endl; #endif - return; + return; } - GxsMsgMetaResult metaResult; - GxsMsgReq req; + RsGxsMetaDataTemporaryMap grpMetas; + grpMetas[item->grpId] = NULL; - RsGxsMetaDataTemporaryMap grpMetas; - grpMetas[item->grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetas); - RsGxsGrpMetaData* grpMeta = grpMetas[item->grpId]; + mDataStore->retrieveGxsGrpMetaData(grpMetas); + RsGxsGrpMetaData* grpMeta = grpMetas[item->grpId]; - if(grpMeta == NULL) - { + if(grpMeta == NULL) + { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is unknown." << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is unknown." << std::endl; #endif - return; - } - if(!(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { + return; + } + if(!(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) + { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is not subscribed." << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is not subscribed." << std::endl; #endif - return ; - } + return ; + } - req[item->grpId] = std::vector(); - mDataStore->retrieveGxsMsgMetaData(req, metaResult); - std::vector& msgMetas = metaResult[item->grpId]; + GxsMsgReq req; + req[item->grpId] = std::vector(); + + GxsMsgMetaResult metaResult; + mDataStore->retrieveGxsMsgMetaData(req, metaResult); + std::vector& msgMetas = metaResult[item->grpId]; #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " retrieving message meta data." << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " retrieving message meta data." << std::endl; #endif - if(req.empty()) - { + if(req.empty()) + { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " No msg meta data.." << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " No msg meta data.." << std::endl; #endif - } + } #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Sending MSG meta data!" << std::endl; #endif - std::list itemL; + std::list itemL; - uint32_t transN = locked_getTransactionId(); + uint32_t transN = locked_getTransactionId(); + RsGxsCircleId should_encrypt_to_this_circle_id ; - if(canSendMsgIds(msgMetas, *grpMeta, peer)) - { - std::vector::iterator vit = msgMetas.begin(); + if(canSendMsgIds(msgMetas, *grpMeta, peer, should_encrypt_to_this_circle_id)) + for(std::vector::iterator vit = msgMetas.begin();vit != msgMetas.end(); ++vit) + { + RsGxsMsgMetaData* m = *vit; - for(; vit != msgMetas.end(); ++vit) - { - RsGxsMsgMetaData* m = *vit; + RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType); + mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; + mItem->grpId = m->mGroupId; + mItem->msgId = m->mMsgId; + mItem->authorId = m->mAuthorId; + mItem->PeerId(peer); + mItem->transactionNumber = transN; - RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType); - mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - mItem->grpId = m->mGroupId; - mItem->msgId = m->mMsgId; - mItem->authorId = m->mAuthorId; - mItem->PeerId(peer); - mItem->transactionNumber = transN; - itemL.push_back(mItem); -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << std::endl; + if(!should_encrypt_to_this_circle_id.isNull()) + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << ". Transaction will be encrypted for group " << should_encrypt_to_this_circle_id << std::endl; #endif - } + RsNxsItem *encrypted_item = NULL ; + uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - if(!itemL.empty()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending final msg info list of " << itemL.size() << " items." << std::endl; + if(encryptSingleNxsItem(mItem, grpMeta->mCircleId, encrypted_item,status)) + { + itemL.push_back(encrypted_item) ; + delete mItem ; + } + else + { + // Something's not ready (probably the circle content. We could put on a vetting list, but actually the client will re-ask the list asap. + + std::cerr << " (EE) Cannot encrypt msg meta data. MsgId=" << mItem->msgId << ", grpId=" << mItem->grpId << ", circleId=" << should_encrypt_to_this_circle_id << ". Dropping the whole list." << std::endl; + + for(std::list::const_iterator it(itemL.begin());it!=itemL.end();++it) + delete *it ; + + itemL.clear() ; + break ; + } + } + else + { +#ifdef NXS_NET_DEBUG_7 + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << " in clear." << std::endl; #endif - locked_pushMsgRespFromList(itemL, peer, item->grpId,transN); - } - } + itemL.push_back(mItem); + } + } #ifdef NXS_NET_DEBUG_0 else - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " vetting forbids sending. Nothing will be sent." << itemL.size() << " items." << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " vetting forbids sending. Nothing will be sent." << itemL.size() << " items." << std::endl; #endif - std::vector::iterator vit = msgMetas.begin(); - // release meta resource - for(vit = msgMetas.begin(); vit != msgMetas.end(); ++vit) - delete *vit; + if(!itemL.empty()) + { +#ifdef NXS_NET_DEBUG_0 + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending final msg info list of " << itemL.size() << " items." << std::endl; +#endif + locked_pushMsgRespFromList(itemL, peer, item->grpId,transN); + } +#ifdef NXS_NET_DEBUG_0 + else + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " list is empty! Not sending anything." << std::endl; +#endif + + + // release meta resource + for(std::vector::iterator vit = msgMetas.begin(); vit != msgMetas.end(); ++vit) + delete *vit; } void RsGxsNetService::locked_pushMsgRespFromList(std::list& itemL, const RsPeerId& sslId, const RsGxsGroupId& grp_id,const uint32_t& transN) @@ -3864,13 +4459,19 @@ void RsGxsNetService::locked_pushMsgRespFromList(std::list& itemL, c NxsTransaction* tr = new NxsTransaction(); tr->mItems = itemL; tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - RsNxsTransac* trItem = new RsNxsTransac(mServType); - trItem->transactFlag = RsNxsTransac::FLAG_BEGIN_P1 | RsNxsTransac::FLAG_TYPE_MSG_LIST_RESP; - trItem->nItems = itemL.size(); - trItem->timestamp = 0 ; + + RsNxsTransacItem* trItem = new RsNxsTransacItem(mServType); + trItem->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP; + trItem->nItems = itemL.size(); + trItem->timestamp = 0; trItem->PeerId(sslId); trItem->transactionNumber = transN; + // also make a copy for the resident transaction + tr->mTransaction = new RsNxsTransacItem(*trItem); + tr->mTransaction->PeerId(mOwnId); + tr->mTimeOut = time(NULL) + mTransactionTimeOut; + ServerMsgMap::const_iterator cit = mServerMsgUpdateMap.find(grp_id); // This time stamp is not supposed to be used on the other side. We just set it to avoid sending an uninitialiszed value. @@ -3883,47 +4484,94 @@ void RsGxsNetService::locked_pushMsgRespFromList(std::list& itemL, c trItem->updateTS = 0 ; } - // also make a copy for the resident transaction - tr->mTransaction = new RsNxsTransac(*trItem); - tr->mTransaction->PeerId(mOwnId); - tr->mTimeOut = time(NULL) + mTransactionTimeOut; - #ifdef NXS_NET_DEBUG_5 GXSNETDEBUG_P_ (sslId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending messages response to peer " << sslId << " with " << itemL.size() << " messages " << std::endl; #endif // signal peer to prepare for transaction - sendItem(trItem); - - locked_addTransaction(tr); + if(locked_addTransaction(tr)) + sendItem(trItem); + else + { + delete tr ; + delete trItem ; + } + } -bool RsGxsNetService::canSendMsgIds(const std::vector& msgMetas, - const RsGxsGrpMetaData& grpMeta, const RsPeerId& sslId) +bool RsGxsNetService::canSendMsgIds(std::vector& msgMetas, const RsGxsGrpMetaData& grpMeta, const RsPeerId& sslId,RsGxsCircleId& should_encrypt_id) { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG__G(grpMeta.mGroupId) << "RsGxsNetService::canSendMsgIds() CIRCLE VETTING" << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendMsgIds() CIRCLE VETTING" << std::endl; #endif // first do the simple checks uint8_t circleType = grpMeta.mCircleType; if(circleType == GXS_CIRCLE_TYPE_LOCAL) - return false; + { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: LOCAL => returning false" << std::endl; +#endif + return false; + } - if(circleType == GXS_CIRCLE_TYPE_PUBLIC) - return true; + if(circleType == GXS_CIRCLE_TYPE_PUBLIC) + { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: PUBLIC => returning true" << std::endl; +#endif + return true; + } const RsGxsCircleId& circleId = grpMeta.mCircleId; if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs ids list will be encrypted." << std::endl; +#endif + should_encrypt_id = circleId ; + + // For each message ID, check that the author is in the circle. If not, do not send the message, which means, remove it from the list. + + if(mCircles->isLoaded(circleId)) + { + for(uint32_t i=0;iisRecipient(circleId, msgMetas[i]->mAuthorId)) + { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " deleting MsgMeta entry for msg ID " << msgMetas[i]->mMsgId << " signed by " << msgMetas[i]->mAuthorId << " who is not in group circle " << circleId << std::endl; +#endif + + delete msgMetas[i] ; + msgMetas[i] = msgMetas[msgMetas.size()-1] ; + msgMetas.pop_back() ; + } + else + ++i ; + + return true ; + } + +#ifdef TO_BE_REMOVED_OLD_VETTING_FOR_EXTERNAL_CIRCLES +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL. Circle Id: " << circleId << std::endl; +#endif if(mCircles->isLoaded(circleId)) { const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId); - return mCircles->canSend(circleId, pgpId); + bool res = mCircles->canSend(circleId, pgpId); +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Answer from circle::canSend(): " << res << std::endl; +#endif + return res ; } +#endif +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle info not loaded. Putting in vetting list and returning false." << std::endl; +#endif std::vector toVet; std::vector::const_iterator vit = msgMetas.begin(); @@ -3936,24 +4584,41 @@ bool RsGxsNetService::canSendMsgIds(const std::vector& msgMet } if(!toVet.empty()) - mPendingCircleVets.push_back(new MsgCircleIdsRequestVetting(mCircles, mPgpUtils, toVet, grpMeta.mGroupId, - sslId, grpMeta.mCircleId)); + mPendingCircleVets.push_back(new MsgCircleIdsRequestVetting(mCircles, mPgpUtils, toVet, grpMeta.mGroupId, sslId, grpMeta.mCircleId)); return false; } if(circleType == GXS_CIRCLE_TYPE_YOUREYESONLY) { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: YOUR EYES ONLY" << std::endl; +#endif // a non empty internal circle id means this // is the personal circle owner if(!grpMeta.mInternalCircle.isNull()) { const RsGxsCircleId& internalCircleId = grpMeta.mInternalCircle; +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Group internal circle: " << internalCircleId << std::endl; +#endif if(mCircles->isLoaded(internalCircleId)) { const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId); - return mCircles->canSend(internalCircleId, pgpId); + bool should_encrypt = false ; + + bool res= mCircles->canSend(internalCircleId, pgpId,should_encrypt); + + if(should_encrypt) + std::cerr << "(EE) inconsistent response: vetting requests to encrypt circle of type YOUR_EYES_ONLY" << std::endl; +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Answer from circle::canSend(): " << res << std::endl; +#endif + return res ; } +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Not loaded. Putting in vetting list and returning false." << std::endl; +#endif std::vector toVet; std::vector::const_iterator vit = msgMetas.begin(); @@ -3977,6 +4642,10 @@ bool RsGxsNetService::canSendMsgIds(const std::vector& msgMet { // an empty internal circle id means this peer can only // send circle related info from peer he received it + +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Empty internal circle: cannot only send info from Peer we received it (grpMeta.mOriginator=" << grpMeta.mOriginator << " answer is: " << (grpMeta.mOriginator == sslId) << std::endl; +#endif if(grpMeta.mOriginator == sslId) return true; else @@ -4253,3 +4922,22 @@ void RsGxsNetService::handleRecvPublishKeys(RsNxsGroupPublishKeyItem *item) std::cerr << "(EE) could not update database. Something went wrong." << std::endl; } } + +bool RsGxsNetService::getGroupServerUpdateTS(const RsGxsGroupId& gid,time_t& group_server_update_TS, time_t& msg_server_update_TS) +{ + RS_STACK_MUTEX(mNxsMutex) ; + + if(mGrpServerUpdateItem == NULL) + return false ; + + group_server_update_TS = mGrpServerUpdateItem->grpUpdateTS ; + + std::map::iterator it = mServerMsgUpdateMap.find(gid) ; + + if(mServerMsgUpdateMap.end() == it) + msg_server_update_TS = 0 ; + else + msg_server_update_TS = it->second->msgUpdateTS ; + + return true ; +} diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h index ffc47235b..136d9cbea 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ b/libretroshare/src/gxs/rsgxsnetservice.h @@ -91,7 +91,7 @@ public: RsNxsNetMgr *netMgr, RsNxsObserver *nxsObs, // used to be = NULL. const RsServiceInfo serviceInfo, - RsGixsReputation* reputations = NULL, RsGcxs* circles = NULL, + RsGixsReputation* reputations = NULL, RsGcxs* circles = NULL, RsGixs *gixs=NULL, PgpAuxUtils *pgpUtils = NULL, bool grpAutoSync = true, bool msgAutoSync = true); @@ -154,6 +154,8 @@ public: virtual void rejectMessage(const RsGxsMessageId& msg_id) ; + virtual bool getGroupServerUpdateTS(const RsGxsGroupId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) ; + /* p3Config methods */ public: @@ -215,7 +217,7 @@ private: * @param item the transaction item to process * @return false ownership of item left with callee */ - bool locked_processTransac(RsNxsTransac* item); + bool locked_processTransac(RsNxsTransacItem* item); /*! * This adds a transaction @@ -318,19 +320,19 @@ private: * of groups held by user * @param item contains grp sync info */ - void handleRecvSyncGroup(RsNxsSyncGrp* item); + void handleRecvSyncGroup(RsNxsSyncGrpReqItem* item); /*! * Handles an nxs item for group statistics * @param item contaims update time stamp and number of messages */ - void handleRecvSyncGrpStatistics(RsNxsSyncGrpStats *grs); + void handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs); /*! * Handles an nxs item for msgs synchronisation * @param item contaims msg sync info */ - void handleRecvSyncMessage(RsNxsSyncMsg* item); + void handleRecvSyncMessage(RsNxsSyncMsgReqItem* item); /*! * Handles an nxs item for group publish key @@ -349,22 +351,21 @@ private: * @param toVet groupid/peer to vet are stored here if their circle id is not cached * @return false, if you cannot send to this peer, true otherwise */ - bool canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector& toVet); - - - bool canSendMsgIds(const std::vector& msgMetas, const RsGxsGrpMetaData&, const RsPeerId& sslId); + bool canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector& toVet, bool &should_encrypt); + bool canSendMsgIds(std::vector& msgMetas, const RsGxsGrpMetaData&, const RsPeerId& sslId, RsGxsCircleId &should_encrypt_id); bool checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& meta); void locked_createTransactionFromPending(MsgRespPending* grpPend); void locked_createTransactionFromPending(GrpRespPending* msgPend); - void locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend); - void locked_createTransactionFromPending(MsgCircleIdsRequestVetting* grpPend); + bool locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) ; + bool locked_createTransactionFromPending(MsgCircleIdsRequestVetting* grpPend) ; - void locked_pushMsgTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); - void locked_pushGrpTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); + void locked_pushGrpTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a grp list request + void locked_pushMsgTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a msg list request void locked_pushGrpRespFromList(std::list& respList, const RsPeerId& peer, const uint32_t& transN); void locked_pushMsgRespFromList(std::list& itemL, const RsPeerId& sslId, const RsGxsGroupId &grp_id, const uint32_t& transN); + void syncWithPeers(); void syncGrpStatistics(); void addGroupItemToList(NxsTransaction*& tr, @@ -375,15 +376,15 @@ private: void processExplicitGroupRequests(); - void locked_doMsgUpdateWork(const RsNxsTransac* nxsTrans, const RsGxsGroupId& grpId); + void locked_doMsgUpdateWork(const RsNxsTransacItem* nxsTrans, const RsGxsGroupId& grpId); void updateServerSyncTS(); #ifdef TO_REMOVE void updateClientSyncTS(); #endif - bool locked_CanReceiveUpdate(const RsNxsSyncGrp* item); - bool locked_CanReceiveUpdate(const RsNxsSyncMsg* item); + bool locked_CanReceiveUpdate(const RsNxsSyncGrpReqItem *item); + bool locked_CanReceiveUpdate(const RsNxsSyncMsgReqItem* item); private: @@ -450,8 +451,15 @@ private: void locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const RsGxsGroupId& grpId,time_t tm,uint32_t n_messages) ; + /*! + * encrypts/decrypts the transaction for the destination circle id. + */ + bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *& encrypted_item, uint32_t &status) ; + bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later + void cleanRejectedMessages(); void processObserverNotifications(); + private: @@ -469,8 +477,8 @@ private: /*** transactions ***/ /*** synchronisation ***/ - std::list mSyncGrp; - std::list mSyncMsg; + std::list mSyncGrp; + std::list mSyncMsg; /*** synchronisation ***/ RsNxsObserver* mObserver; @@ -496,6 +504,7 @@ private: int mUpdateCounter ; RsGcxs* mCircles; + RsGixs *mGixs; RsGixsReputation* mReputations; PgpAuxUtils *mPgpUtils; bool mGrpAutoSync; @@ -516,7 +525,6 @@ public: typedef std::map ClientMsgMap; typedef std::map ServerMsgMap; typedef std::map ClientGrpMap; - private: ClientMsgMap mClientMsgUpdateMap; diff --git a/libretroshare/src/gxs/rsgxsnetutils.cc b/libretroshare/src/gxs/rsgxsnetutils.cc index 76dd8a68d..1de8ec9a4 100644 --- a/libretroshare/src/gxs/rsgxsnetutils.cc +++ b/libretroshare/src/gxs/rsgxsnetutils.cc @@ -222,12 +222,12 @@ bool GrpCircleVetting::expired() { return time(NULL) > (mTimeStamp + EXPIRY_PERIOD_OFFSET); } -bool GrpCircleVetting::canSend(const SSLIdType& peerId, const RsGxsCircleId& circleId) +bool GrpCircleVetting::canSend(const SSLIdType& peerId, const RsGxsCircleId& circleId,bool& should_encrypt) { if(mCircles->isLoaded(circleId)) { const RsPgpId& pgpId = mPgpUtils->getPGPId(peerId); - return mCircles->canSend(circleId, pgpId); + return mCircles->canSend(circleId, pgpId,should_encrypt); } mCircles->loadCircle(circleId); @@ -250,7 +250,7 @@ bool GrpCircleIdRequestVetting::cleared() if(!gic.mCleared) { - if(canSend(mPeerId, gic.mCircleId)) + if(canSend(mPeerId, gic.mCircleId,gic.mShouldEncrypt)) { gic.mCleared = true; count++; @@ -284,9 +284,30 @@ MsgCircleIdsRequestVetting::MsgCircleIdsRequestVetting(RsGcxs* const circles, bool MsgCircleIdsRequestVetting::cleared() { - - return canSend(mPeerId, mCircleId); - + if(!mCircles->isLoaded(mCircleId)) + { + mCircles->loadCircle(mCircleId); + return false ; + } + + for(uint32_t i=0;iisRecipient(mCircleId,mMsgs[i].mAuthorId)) + { + std::cerr << "(WW) MsgCircleIdsRequestVetting::cleared() filtering out message " << mMsgs[i].mMsgId << " because it's signed by author " << mMsgs[i].mAuthorId << " which is not in circle " << mCircleId << std::endl; + + mMsgs[i] = mMsgs[mMsgs.size()-1] ; + mMsgs.pop_back(); + } + else + ++i ; + + RsPgpId pgpId = mPgpUtils->getPGPId(mPeerId); + bool can_send_res = mCircles->canSend(mCircleId, pgpId,mShouldEncrypt); + + if(mShouldEncrypt) // that means the circle is external + return true ; + else + return can_send_res ; } int MsgCircleIdsRequestVetting::getType() const diff --git a/libretroshare/src/gxs/rsgxsnetutils.h b/libretroshare/src/gxs/rsgxsnetutils.h index 10c3350e1..df82cb2b3 100644 --- a/libretroshare/src/gxs/rsgxsnetutils.h +++ b/libretroshare/src/gxs/rsgxsnetutils.h @@ -66,7 +66,7 @@ public: * c timeout set for this transaction * c and itemCount */ - RsNxsTransac* mTransaction; + RsNxsTransacItem* mTransaction; std::list mItems; // items received or sent }; @@ -214,7 +214,9 @@ public: RsGxsGroupId mGroupId; RsGxsCircleId mCircleId; RsGxsId mAuthorId; + bool mCleared; + bool mShouldEncrypt; }; class MsgIdCircleVet @@ -252,9 +254,7 @@ public: virtual bool cleared() = 0; protected: - bool canSend(const RsPeerId& peerId, const RsGxsCircleId& circleId); - -private: + bool canSend(const RsPeerId& peerId, const RsGxsCircleId& circleId, bool& should_encrypt); RsGcxs* const mCircles; PgpAuxUtils *mPgpUtils; @@ -286,6 +286,7 @@ public: RsGxsGroupId mGrpId; RsPeerId mPeerId; RsGxsCircleId mCircleId; + bool mShouldEncrypt; }; diff --git a/libretroshare/src/gxs/rsnxs.h b/libretroshare/src/gxs/rsnxs.h index 746d7649f..4a083a0f6 100644 --- a/libretroshare/src/gxs/rsnxs.h +++ b/libretroshare/src/gxs/rsnxs.h @@ -134,6 +134,16 @@ public: * \param msgId */ virtual void rejectMessage(const RsGxsMessageId& msgId) =0; + + /*! + * \brief getGroupServerUpdateTS + * Returns the server update time stamp for that group. This is used for synchronisation of TS between + * various network exchange services, suhc as channels/circles or forums/circles + * \param gid group for that request + * \param tm time stamp computed + * \return false if the group is not found, true otherwise + */ + virtual bool getGroupServerUpdateTS(const RsGxsGroupId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) =0; }; #endif // RSGNP_H diff --git a/libretroshare/src/retroshare/rsgxscircles.h b/libretroshare/src/retroshare/rsgxscircles.h index 2736adc75..5f6dcd7c3 100644 --- a/libretroshare/src/retroshare/rsgxscircles.h +++ b/libretroshare/src/retroshare/rsgxscircles.h @@ -111,8 +111,8 @@ class RsGxsCircleDetails && mCircleName == rGxsDetails.mCircleName && mCircleType == rGxsDetails.mCircleType && mIsExternal == rGxsDetails.mIsExternal - && mUnknownPeers == rGxsDetails.mUnknownPeers - && mAllowedPeers == rGxsDetails.mAllowedPeers + && mAllowedAnonPeers == rGxsDetails.mAllowedAnonPeers + && mAllowedSignedPeers == rGxsDetails.mAllowedSignedPeers ); } @@ -121,13 +121,13 @@ class RsGxsCircleDetails || mCircleName != rGxsDetails.mCircleName || mCircleType != rGxsDetails.mCircleType || mIsExternal != rGxsDetails.mIsExternal - || mUnknownPeers != rGxsDetails.mUnknownPeers - || mAllowedPeers != rGxsDetails.mAllowedPeers + || mAllowedAnonPeers != rGxsDetails.mAllowedAnonPeers + || mAllowedSignedPeers != rGxsDetails.mAllowedSignedPeers ); } - std::set mUnknownPeers; - std::map > mAllowedPeers; + std::set mAllowedAnonPeers; + std::map > mAllowedSignedPeers; }; class RsGxsCircles: public RsGxsIfaceHelper diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 6c32438ff..1b4b393ab 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1334,7 +1334,7 @@ int RsServer::StartupRetroShare() RsGxsNetService* gxsid_ns = new RsGxsNetService( RS_SERVICE_GXS_TYPE_GXSID, gxsid_ds, nxsMgr, mGxsIdService, mGxsIdService->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, pgpAuxUtils, false,false); // don't synchronise group automatic (need explicit group request) // don't sync messages at all. @@ -1353,9 +1353,13 @@ int RsServer::StartupRetroShare() RsGxsNetService* gxscircles_ns = new RsGxsNetService( RS_SERVICE_GXS_TYPE_GXSCIRCLE, gxscircles_ds, nxsMgr, mGxsCircles, mGxsCircles->getServiceInfo(), - mGxsIdService, mGxsCircles, - pgpAuxUtils); + mGxsIdService, mGxsCircles,mGxsIdService, + pgpAuxUtils, + true,false); // synchronise group automatic + // don't sync messages at all. + mGxsCircles->setNetworkExchangeService(gxscircles_ns) ; + /**** Posted GXS service ****/ @@ -1370,7 +1374,7 @@ int RsServer::StartupRetroShare() RsGxsNetService* posted_ns = new RsGxsNetService( RS_SERVICE_GXS_TYPE_POSTED, posted_ds, nxsMgr, mPosted, mPosted->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, pgpAuxUtils); mPosted->setNetworkExchangeService(posted_ns) ; @@ -1410,7 +1414,7 @@ int RsServer::StartupRetroShare() RsGxsNetService* gxsforums_ns = new RsGxsNetService( RS_SERVICE_GXS_TYPE_FORUMS, gxsforums_ds, nxsMgr, mGxsForums, mGxsForums->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, pgpAuxUtils); mGxsForums->setNetworkExchangeService(gxsforums_ns) ; @@ -1426,7 +1430,7 @@ int RsServer::StartupRetroShare() RsGxsNetService* gxschannels_ns = new RsGxsNetService( RS_SERVICE_GXS_TYPE_CHANNELS, gxschannels_ds, nxsMgr, mGxsChannels, mGxsChannels->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, pgpAuxUtils); mGxsChannels->setNetworkExchangeService(gxschannels_ns) ; @@ -1443,7 +1447,7 @@ int RsServer::StartupRetroShare() RsGxsNetService* photo_ns = new RsGxsNetService( RS_SERVICE_GXS_TYPE_PHOTO, photo_ds, nxsMgr, mPhoto, mPhoto->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, pgpAuxUtils); #endif @@ -1459,7 +1463,7 @@ int RsServer::StartupRetroShare() RsGxsNetService* wire_ns = new RsGxsNetService( RS_SERVICE_GXS_TYPE_WIRE, wire_ds, nxsMgr, mWire, mWire->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, pgpAuxUtils); #endif // now add to p3service diff --git a/libretroshare/src/serialiser/rsgxscircleitems.cc b/libretroshare/src/serialiser/rsgxscircleitems.cc index c9011091e..0132c358e 100644 --- a/libretroshare/src/serialiser/rsgxscircleitems.cc +++ b/libretroshare/src/serialiser/rsgxscircleitems.cc @@ -29,8 +29,7 @@ #include "serialiser/rstlvbase.h" #include "serialiser/rsbaseserial.h" -#define CIRCLE_DEBUG 1 - +//#define CIRCLE_DEBUG 1 uint32_t RsGxsCircleSerialiser::size(RsItem *item) { diff --git a/libretroshare/src/serialiser/rsnxsitems.cc b/libretroshare/src/serialiser/rsnxsitems.cc index 858760b76..1a7cf45b4 100644 --- a/libretroshare/src/serialiser/rsnxsitems.cc +++ b/libretroshare/src/serialiser/rsnxsitems.cc @@ -1,1601 +1,1347 @@ -#include "rsnxsitems.h" -#include "rsbaseserial.h" - -/*** - * #define RSSERIAL_DEBUG 1 - ***/ - -const uint8_t RsNxsSyncGrpItem::FLAG_REQUEST = 0x001; -const uint8_t RsNxsSyncGrpItem::FLAG_RESPONSE = 0x002; - -const uint8_t RsNxsSyncMsgItem::FLAG_REQUEST = 0x001; -const uint8_t RsNxsSyncMsgItem::FLAG_RESPONSE = 0x002; - -const uint8_t RsNxsSyncGrp::FLAG_USE_SYNC_HASH = 0x001; -const uint8_t RsNxsSyncMsg::FLAG_USE_SYNC_HASH = 0x001; - -/** transaction state **/ -const uint16_t RsNxsTransac::FLAG_BEGIN_P1 = 0x0001; -const uint16_t RsNxsTransac::FLAG_BEGIN_P2 = 0x0002; -const uint16_t RsNxsTransac::FLAG_END_SUCCESS = 0x0004; -const uint16_t RsNxsTransac::FLAG_CANCEL = 0x0008; -const uint16_t RsNxsTransac::FLAG_END_FAIL_NUM = 0x0010; -const uint16_t RsNxsTransac::FLAG_END_FAIL_TIMEOUT = 0x0020; -const uint16_t RsNxsTransac::FLAG_END_FAIL_FULL = 0x0040; - - -/** transaction type **/ -const uint16_t RsNxsTransac::FLAG_TYPE_GRP_LIST_RESP = 0x0100; -const uint16_t RsNxsTransac::FLAG_TYPE_MSG_LIST_RESP = 0x0200; -const uint16_t RsNxsTransac::FLAG_TYPE_GRP_LIST_REQ = 0x0400; -const uint16_t RsNxsTransac::FLAG_TYPE_MSG_LIST_REQ = 0x0800; -const uint16_t RsNxsTransac::FLAG_TYPE_GRPS = 0x1000; -const uint16_t RsNxsTransac::FLAG_TYPE_MSGS = 0x2000; - - -uint32_t RsNxsSerialiser::size(RsItem *item) { - - RsNxsGrp* ngp; - RsNxsMsg* nmg; - RsNxsSyncGrp* sg; - RsNxsSyncGrpStats* sgs; - RsNxsSyncGrpItem* sgl; - RsNxsSyncMsg* sgm; - RsNxsSyncMsgItem* sgml; - RsNxsTransac* ntx; - RsNxsGroupPublishKeyItem* npk; - - - if((npk = dynamic_cast(item)) != NULL) - { - return sizeNxsGroupPublishKeyItem(npk); - } else if((sg = dynamic_cast(item)) != NULL) - { - return sizeNxsSyncGrp(sg); - - } else if((sgs = dynamic_cast(item)) != NULL) - { - return sizeNxsSyncGrpStats(sgs); - }else if(( ntx = dynamic_cast(item)) != NULL){ - return sizeNxsTrans(ntx); - } - else if ((sgl = dynamic_cast(item)) != NULL) - { - return sizeNxsSyncGrpItem(sgl); - - }else if ((sgm = dynamic_cast(item)) != NULL) - { - return sizeNxsSyncMsg(sgm); - }else if ((sgml = dynamic_cast(item)) != NULL) - { - return sizeNxsSyncMsgItem(sgml); - }else if((ngp = dynamic_cast(item)) != NULL) - { - return sizeNxsGrp(ngp); - }else if((nmg = dynamic_cast(item)) != NULL) - { - return sizeNxsMsg(nmg); - }else{ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::size(): Could not find appropriate size function" - << std::endl; -#endif - return 0; - } -} - - -RsItem* RsNxsSerialiser::deserialise(void *data, uint32_t *size) { - - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialise()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - - case RS_PKT_SUBTYPE_NXS_SYNC_GRP: - return deserialNxsSyncGrp(data, size); - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM: - return deserialNxsSyncGrpItem(data, size); - case RS_PKT_SUBTYPE_NXS_SYNC_MSG: - return deserialNxsSyncMsg(data, size); - case RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM: - return deserialNxsSyncMsgItem(data, size); - case RS_PKT_SUBTYPE_NXS_GRP: - return deserialNxsGrp(data, size); - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS: - return deserialNxsSyncGrpStats(data, size); - case RS_PKT_SUBTYPE_NXS_MSG: - return deserialNxsMsg(data, size); - case RS_PKT_SUBTYPE_NXS_TRANS: - return deserialNxsTrans(data, size); - case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY: - return deserialNxsGroupPublishKeyItem(data, size); - default: - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialise() : data has no type" - << std::endl; -#endif - return NULL; - - } - } -} - - - -bool RsNxsSerialiser::serialise(RsItem *item, void *data, uint32_t *size){ - - RsNxsGrp* ngp; - RsNxsMsg* nmg; - RsNxsSyncGrp* sg; - RsNxsSyncGrpStats* sgs; - RsNxsSyncGrpItem* sgl; - RsNxsSyncMsg* sgm; - RsNxsSyncMsgItem* sgml; - RsNxsTransac* ntx; - RsNxsGroupPublishKeyItem* gpk; - - if((sg = dynamic_cast(item)) != NULL) - { - return serialiseNxsSyncGrp(sg, data, size); - - }else if((sgs = dynamic_cast(item)) != NULL) - { - return serialiseNxsSyncGrpStats(sgs, data, size); - - }else if ((ntx = dynamic_cast(item)) != NULL) - { - return serialiseNxsTrans(ntx, data, size); - - }else if ((sgl = dynamic_cast(item)) != NULL) - { - return serialiseNxsSyncGrpItem(sgl, data, size); - - }else if ((sgm = dynamic_cast(item)) != NULL) - { - return serialiseNxsSyncMsg(sgm, data, size); - }else if ((sgml = dynamic_cast(item)) != NULL) - { - return serialiseNxsSynMsgItem(sgml, data, size); - }else if((ngp = dynamic_cast(item)) != NULL) - { - return serialiseNxsGrp(ngp, data, size); - }else if((nmg = dynamic_cast(item)) != NULL) - { - return serialiseNxsMsg(nmg, data, size); - }else if((gpk = dynamic_cast(item)) != NULL) - { - return serialiseNxsGroupPublishKeyItem(gpk, data, size); - } - -#ifdef NXS_DEBUG - std::cerr << "RsNxsSerialiser::serialise() item does not caste to know type" - << std::endl; -#endif - - return NULL; -} - - -bool RsNxsSerialiser::serialiseNxsSynMsgItem(RsNxsSyncMsgItem *item, void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSynMsgItem()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsSyncMsgItem(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSynMsgItem()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* RsNxsSyncMsgItem */ - - ok &= setRawUInt32(data, *size, &offset, item->transactionNumber); - ok &= setRawUInt8(data, *size, &offset, item->flag); - ok &= item->grpId.serialise(data, *size, offset); - ok &= item->msgId.serialise(data, *size, offset); - ok &= item->authorId.serialise(data, *size, offset); - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSynMsgItem() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseNxsSynMsgItem() NOK" << std::endl; - } -#endif - - return ok; -} - - -bool RsNxsSerialiser::serialiseNxsMsg(RsNxsMsg *item, void *data, uint32_t *size) -{ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsMsg()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsMsg(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsMsg()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= setRawUInt32(data, *size, &offset, item->transactionNumber); - ok &= setRawUInt8(data, *size, &offset, item->pos); - ok &= item->msgId.serialise(data, *size, offset); - ok &= item->grpId.serialise(data, *size, offset); - ok &= item->msg.SetTlv(data, tlvsize, &offset); - ok &= item->meta.SetTlv(data, *size, &offset); - - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsMsg() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseNxsMsg() NOK" << std::endl; - } -#endif - - return ok; -} - - -bool RsNxsSerialiser::serialiseNxsGrp(RsNxsGrp *item, void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsGrp()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsGrp(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsGrp()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - // grp id - ok &= setRawUInt32(data, *size, &offset, item->transactionNumber); - ok &= setRawUInt8(data, *size, &offset, item->pos); - ok &= item->grpId.serialise(data, *size, offset); - ok &= item->grp.SetTlv(data, tlvsize, &offset); - ok &= item->meta.SetTlv(data, *size, &offset); - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsGrp() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseNxsGrp() NOK" << std::endl; - } -#endif - - return ok; -} - - -bool RsNxsSerialiser::serialiseNxsSyncGrpStats(RsNxsSyncGrpStats *item, void *data, uint32_t *size) -{ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrpStats()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsSyncGrpStats(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrpStats()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= setRawUInt32(data, *size, &offset, item->request_type); - ok &= item->grpId.serialise(data, *size, offset) ; - ok &= setRawUInt32(data, *size, &offset, item->number_of_posts); - ok &= setRawUInt32(data, *size, &offset, item->last_post_TS); - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseSyncGrpStats() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseSyncGrpStats() NOK" << std::endl; - } -#endif - - return ok; -} -bool RsNxsSerialiser::serialiseNxsSyncGrp(RsNxsSyncGrp *item, void *data, uint32_t *size) -{ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrp()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsSyncGrp(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrp()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= setRawUInt32(data, *size, &offset, item->transactionNumber); - ok &= setRawUInt8(data, *size, &offset, item->flag); - ok &= setRawUInt32(data, *size, &offset, item->createdSince); - ok &= SetTlvString(data, *size, &offset, TLV_TYPE_STR_HASH_SHA1, item->syncHash); - ok &= setRawUInt32(data, *size, &offset, item->updateTS); - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseSyncGrp() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseSyncGrp() NOK" << std::endl; - } -#endif - - return ok; -} - - -bool RsNxsSerialiser::serialiseNxsTrans(RsNxsTransac *item, void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsTrans()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsTrans(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsTrans() size do not match" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= setRawUInt32(data, *size, &offset, item->transactionNumber); - ok &= setRawUInt16(data, *size, &offset, item->transactFlag); - ok &= setRawUInt32(data, *size, &offset, item->nItems); - ok &= setRawUInt32(data, *size, &offset, item->updateTS); - - - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsTrans() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseNxsTrans() NOK" << std::endl; - } -#endif - - return ok; -} - -bool RsNxsSerialiser::serialiseNxsSyncGrpItem(RsNxsSyncGrpItem *item, void *data, uint32_t *size) -{ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrpItem()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsSyncGrpItem(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncm() size do not match" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* RsNxsSyncm */ - - ok &= setRawUInt32(data, *size, &offset, item->transactionNumber); - ok &= setRawUInt8(data, *size, &offset, item->flag); - ok &= item->grpId.serialise(data, *size, offset); - ok &= setRawUInt32(data, *size, &offset, item->publishTs); - ok &= item->authorId.serialise(data, *size, offset); - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncm( FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseNxsSyncm() NOK" << std::endl; - } -#endif - - return ok; -} - -bool RsNxsSerialiser::serialiseNxsSyncMsg(RsNxsSyncMsg *item, void *data, uint32_t *size){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsSyncMsg(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= setRawUInt32(data, *size, &offset, item->transactionNumber); - ok &= setRawUInt8(data, *size, &offset, item->flag); - ok &= setRawUInt32(data, *size, &offset, item->createdSince); - ok &= SetTlvString(data, *size, &offset, TLV_TYPE_STR_HASH_SHA1, item->syncHash); - ok &= item->grpId.serialise(data, *size, offset); - ok &= setRawUInt32(data, *size, &offset, item->updateTS); - - if(offset != tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef RSSERIAL_DEBUG - if (!ok) - { - std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg( NOK" << std::endl; - } -#endif - - return ok; -} - - -bool RsNxsSerialiser::serialiseNxsGroupPublishKeyItem(RsNxsGroupPublishKeyItem *item, void *data, uint32_t *size){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg()" << std::endl; -#endif - - uint32_t tlvsize = sizeNxsGroupPublishKeyItem(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= item->grpId.serialise(data, *size, offset) ; - ok &= item->key.SetTlv(data, *size, &offset) ; - - if(offset != tlvsize) - { - std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem() FAIL Size Error! " << std::endl; - ok = false; - } - - if (!ok) - std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem( NOK" << std::endl; - - return ok; -} - -/*** deserialisation ***/ - - -RsNxsGrp* RsNxsSerialiser::deserialNxsGrp(void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGrp()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_GRP != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGrp() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGrp() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsGrp* item = new RsNxsGrp(SERVICE_TYPE); - - /* skip the header */ - offset += 8; - - ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); - ok &= getRawUInt8(data, *size, &offset, &(item->pos)); - ok &= item->grpId.deserialise(data, *size, offset); - ok &= item->grp.GetTlv(data, *size, &offset); - ok &= item->meta.GetTlv(data, *size, &offset); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGrp() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGrp() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - - -RsNxsMsg* RsNxsSerialiser::deserialNxsMsg(void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsMsg()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_MSG != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsMsg() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsMsg() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsMsg* item = new RsNxsMsg(getRsItemService(rstype)); - /* skip the header */ - - offset += 8; - - ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); - ok &= getRawUInt8(data, *size, &offset, &(item->pos)); - ok &= item->msgId.deserialise(data, *size, offset); - ok &= item->grpId.deserialise(data, *size, offset); - ok &= item->msg.GetTlv(data, *size, &offset); - ok &= item->meta.GetTlv(data, *size, &offset); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsMsg() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsMsg() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - -RsNxsSyncGrpStats* RsNxsSerialiser::deserialNxsSyncGrpStats(void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (SERVICE_TYPE != getRsItemService(rstype)) || (RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsSyncGrpStats* item = new RsNxsSyncGrpStats(getRsItemService(rstype)); - /* skip the header */ - offset += 8; - - ok &= getRawUInt32(data, *size, &offset, &(item->request_type)); - ok &= item->grpId.deserialise(data, *size, offset) ; - ok &= getRawUInt32(data, *size, &offset, &(item->number_of_posts)); - ok &= getRawUInt32(data, *size, &offset, &(item->last_post_TS)); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - - - -RsNxsSyncGrp* RsNxsSerialiser::deserialNxsSyncGrp(void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_SYNC_GRP != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsSyncGrp* item = new RsNxsSyncGrp(getRsItemService(rstype)); - /* skip the header */ - offset += 8; - - ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); - ok &= getRawUInt8(data, *size, &offset, &(item->flag)); - ok &= getRawUInt32(data, *size, &offset, &(item->createdSince)); - ok &= GetTlvString(data, *size, &offset, TLV_TYPE_STR_HASH_SHA1, item->syncHash); - ok &= getRawUInt32(data, *size, &offset, &(item->updateTS)); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - - -RsNxsSyncGrpItem* RsNxsSerialiser::deserialNxsSyncGrpItem(void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpItem() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpItem() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsSyncGrpItem* item = new RsNxsSyncGrpItem(SERVICE_TYPE); - /* skip the header */ - offset += 8; - - ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); - ok &= getRawUInt8(data, *size, &offset, &(item->flag)); - ok &= item->grpId.deserialise(data, *size, offset); - ok &= getRawUInt32(data, *size, &offset, &(item->publishTs)); - ok &= item->authorId.deserialise(data, *size, offset); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - -RsNxsTransac* RsNxsSerialiser::deserialNxsTrans(void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsTrans()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_TRANS != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsTrans() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem( FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - /* skip the header */ - offset += 8; - - bool ok = true; - - RsNxsTransac* item = new RsNxsTransac(SERVICE_TYPE); - - ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); - ok &= getRawUInt16(data, *size, &offset, &(item->transactFlag)); - ok &= getRawUInt32(data, *size, &offset, &(item->nItems)); - ok &= getRawUInt32(data, *size, &offset, &(item->updateTS)); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsTrans() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsTrans() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; - - -} - -RsNxsSyncMsgItem* RsNxsSerialiser::deserialNxsSyncMsgItem(void *data, uint32_t *size){ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem( FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsSyncMsgItem* item = new RsNxsSyncMsgItem(getRsItemService(rstype)); - /* skip the header */ - offset += 8; - - ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); - ok &= getRawUInt8(data, *size, &offset, &(item->flag)); - ok &= item->grpId.deserialise(data, *size, offset); - ok &= item->msgId.deserialise(data, *size, offset); - ok &= item->authorId.deserialise(data, *size, offset); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - - -RsNxsSyncMsg* RsNxsSerialiser::deserialNxsSyncMsg(void *data, uint32_t *size) -{ - - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_SYNC_MSG != getRsItemSubType(rstype))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsg() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsg() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsSyncMsg* item = new RsNxsSyncMsg(getRsItemService(rstype)); - - /* skip the header */ - offset += 8; - - ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); - ok &= getRawUInt8(data, *size, &offset, &(item->flag)); - ok &= getRawUInt32(data, *size, &offset, &(item->createdSince)); - ok &= GetTlvString(data, *size, &offset, TLV_TYPE_STR_HASH_SHA1, item->syncHash); - ok &= item->grpId.deserialise(data, *size, offset); - ok &= getRawUInt32(data, *size, &offset, &(item->updateTS)); - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsg() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsSyncMsg() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} -RsNxsGroupPublishKeyItem* RsNxsSerialiser::deserialNxsGroupPublishKeyItem(void *data, uint32_t *size) -{ - - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (SERVICE_TYPE != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY != getRsItemSubType(rstype))) - { - std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() FAIL wrong type" << std::endl; - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { - std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() FAIL wrong size" << std::endl; - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsNxsGroupPublishKeyItem* item = new RsNxsGroupPublishKeyItem(getRsItemService(rstype)); - - /* skip the header */ - offset += 8; - - ok &= item->grpId.deserialise(data, *size, offset); - ok &= item->key.GetTlv(data, *size, &offset) ; - - if (offset != rssize) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - - -/*** size functions ***/ - - -uint32_t RsNxsSerialiser::sizeNxsMsg(RsNxsMsg *item) -{ - - uint32_t s = 8; //header size - - s += 4; // transaction number - s += 1; // pos - s += item->grpId.serial_size(); - s += item->msgId.serial_size(); - s += item->msg.TlvSize(); - s += item->meta.TlvSize(); - - return s; -} - -uint32_t RsNxsSerialiser::sizeNxsGrp(RsNxsGrp *item) -{ - uint32_t s = 8; // header size - - s += 4; // transaction number - s += 1; // pos - s += item->grpId.serial_size(); - s += item->grp.TlvSize(); - s += item->meta.TlvSize(); - - return s; -} - -uint32_t RsNxsSerialiser::sizeNxsGroupPublishKeyItem(RsNxsGroupPublishKeyItem *item) -{ - uint32_t s = 8; // header size - - s += item->grpId.serial_size() ; - s += item->key.TlvSize(); - - return s; -} -uint32_t RsNxsSerialiser::sizeNxsSyncGrp(RsNxsSyncGrp *item) -{ - uint32_t s = 8; // header size - - s += 4; // transaction number - s += 1; // flag - s += 4; // sync age - s += GetTlvStringSize(item->syncHash); - s += 4; // updateTS - - return s; -} -uint32_t RsNxsSerialiser::sizeNxsSyncGrpStats(RsNxsSyncGrpStats *item) -{ - uint32_t s = 8; // header size - - s += 4; // request type - s += item->grpId.serial_size(); - s += 4; // number_of_posts - s += 4; // last_post_TS - - return s; -} - -uint32_t RsNxsSerialiser::sizeNxsSyncGrpItem(RsNxsSyncGrpItem *item) -{ - uint32_t s = 8; // header size - - s += 4; // transaction number - s += 4; // publishTs - s += 1; // flag - s += item->grpId.serial_size(); - s += item->authorId.serial_size(); - - return s; -} - - -uint32_t RsNxsSerialiser::sizeNxsSyncMsg(RsNxsSyncMsg *item) -{ - - uint32_t s = 8; - - s += 4; // transaction number - s += 1; // flag - s += 4; // age - s += item->grpId.serial_size(); - s += GetTlvStringSize(item->syncHash); - s += 4; // updateTS - - return s; -} - - -uint32_t RsNxsSerialiser::sizeNxsSyncMsgItem(RsNxsSyncMsgItem *item) -{ - uint32_t s = 8; // header size - - s += 4; // transaction number - s += 1; // flag - s += item->grpId.serial_size(); - s += item->msgId.serial_size(); - s += item->authorId.serial_size(); - - return s; -} - -uint32_t RsNxsSerialiser::sizeNxsTrans(RsNxsTransac *item){ - - uint32_t s = 8; // header size - - s += 4; // transaction number - s += 2; // flag - s += 4; // nMsgs - s += 4; // updateTS - - return s; -} - - -int RsNxsGrp::refcount = 0; -/** print and clear functions **/ -int RsNxsMsg::refcount = 0; -void RsNxsMsg::clear() -{ - - msg.TlvClear(); - meta.TlvClear(); -} - -void RsNxsGrp::clear() -{ - grpId.clear(); - grp.TlvClear(); - meta.TlvClear(); -} - -void RsNxsSyncGrp::clear() -{ - flag = 0; - createdSince = 0; - syncHash.clear(); - updateTS = 0; -} -void RsNxsGroupPublishKeyItem::clear() -{ - key.TlvClear(); -} -void RsNxsSyncMsg::clear() -{ - grpId.clear(); - flag = 0; - createdSince = 0; - syncHash.clear(); - updateTS = 0; -} -void RsNxsSyncGrpItem::clear() -{ - flag = 0; - publishTs = 0; - grpId.clear(); - authorId.clear(); -} - -void RsNxsSyncMsgItem::clear() -{ - flag = 0; - msgId.clear(); - grpId.clear(); - authorId.clear(); -} - -void RsNxsTransac::clear(){ - transactFlag = 0; - nItems = 0; - updateTS = 0; - timestamp = 0; - transactionNumber = 0; -} -std::ostream& RsNxsSyncGrp::print(std::ostream &out, uint16_t indent) -{ - - printRsItemBase(out, "RsNxsSyncGrp", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out , int_Indent); - out << "Hash: " << syncHash << std::endl; - printIndent(out , int_Indent); - out << "Sync Age: " << createdSince << std::endl; - printIndent(out , int_Indent); - out << "flag: " << (uint32_t) flag << std::endl; - printIndent(out , int_Indent); - out << "updateTS: " << updateTS << std::endl; - - printRsItemEnd(out ,"RsNxsSyncGrp", indent); - - return out; -} -std::ostream& RsNxsGroupPublishKeyItem::print(std::ostream &out, uint16_t indent) -{ - - printRsItemBase(out, "RsNxsGroupPublishKeyItem", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out , int_Indent); - out << "GroupId: " << grpId << std::endl; - printIndent(out , int_Indent); - out << "keyId: " << key.keyId << std::endl; - - printRsItemEnd(out ,"RsNxsGroupPublishKeyItem", indent); - - return out; -} - - -std::ostream& RsNxsSyncMsg::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsNxsSyncMsg", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out , int_Indent); - out << "GrpId: " << grpId << std::endl; - printIndent(out , int_Indent); - out << "createdSince: " << createdSince << std::endl; - printIndent(out , int_Indent); - out << "syncHash: " << syncHash << std::endl; - printIndent(out , int_Indent); - out << "flag: " << (uint32_t) flag << std::endl; - printIndent(out , int_Indent); - out << "updateTS: " << updateTS << std::endl; - - printRsItemEnd(out, "RsNxsSyncMsg", indent); - return out; -} - -std::ostream& RsNxsSyncGrpItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsNxsSyncGrpItem", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out , int_Indent); - out << "flag: " << (uint32_t) flag << std::endl; - printIndent(out , int_Indent); - out << "grpId: " << grpId << std::endl; - printIndent(out , int_Indent); - out << "publishTs: " << publishTs << std::endl; - printIndent(out , int_Indent); - out << "authorId: " << authorId << std::endl; - - printRsItemEnd(out , "RsNxsSyncGrpItem", indent); - return out; -} - - - -std::ostream& RsNxsSyncMsgItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsNxsSyncMsgItem", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out , int_Indent); - out << "flag: " << (uint32_t) flag << std::endl; - printIndent(out , int_Indent); - out << "grpId: " << grpId << std::endl; - printIndent(out , int_Indent); - out << "msgId: " << msgId << std::endl; - printIndent(out , int_Indent); - out << "authorId: " << authorId << std::endl; - printIndent(out , int_Indent); - - printRsItemEnd(out ,"RsNxsSyncMsgItem", indent); - return out; -} - -RsNxsGrp* RsNxsGrp::clone() const { - RsNxsGrp* grp = new RsNxsGrp(PacketService()); - *grp = *this; - - if(this->metaData) - { - grp->metaData = new RsGxsGrpMetaData(); - *(grp->metaData) = *(this->metaData); - } - - return grp; -} - -std::ostream& RsNxsGrp::print(std::ostream &out, uint16_t indent){ - - printRsItemBase(out, "RsNxsGrp", indent); - uint16_t int_Indent = indent + 2; - - out << "grpId: " << grpId << std::endl; - printIndent(out , int_Indent); - out << "grp: " << std::endl; - printIndent(out , int_Indent); - out << "pos: " << pos << std::endl; - grp.print(out, int_Indent); - out << "meta: " << std::endl; - meta.print(out, int_Indent); - - printRsItemEnd(out, "RsNxsGrp", indent); - return out; -} - -std::ostream& RsNxsMsg::print(std::ostream &out, uint16_t indent){ - - printRsItemBase(out, "RsNxsMsg", indent); - uint16_t int_Indent = indent + 2; - - out << "msgId: " << msgId << std::endl; - printIndent(out , int_Indent); - out << "grpId: " << grpId << std::endl; - printIndent(out , int_Indent); - out << "pos: " << pos << std::endl; - printIndent(out , int_Indent); - out << "msg: " << std::endl; - msg.print(out, indent); - out << "meta: " << std::endl; - meta.print(out, int_Indent); - - printRsItemEnd(out ,"RsNxsMsg", indent); - return out; -} - -std::ostream& RsNxsSyncGrpStats::print(std::ostream &out, uint16_t indent){ - - printRsItemBase(out, "RsNxsSyncGrpStats", indent); - uint16_t int_Indent = indent + 2; - - out << "available posts: " << number_of_posts << std::endl; - printIndent(out , int_Indent); - out << "last update: " << last_post_TS << std::endl; - printIndent(out , int_Indent); - out << "group ID: " << grpId << std::endl; - printIndent(out , int_Indent); - out << "request type: " << request_type << std::endl; - printIndent(out , int_Indent); - - printRsItemEnd(out ,"RsNxsSyncGrpStats", indent); - return out; -} -std::ostream& RsNxsTransac::print(std::ostream &out, uint16_t indent){ - - printRsItemBase(out, "RsNxsTransac", indent); - uint16_t int_Indent = indent + 2; - - out << "transactFlag: " << transactFlag << std::endl; - printIndent(out , int_Indent); - out << "nItems: " << nItems << std::endl; - printIndent(out , int_Indent); - out << "timeout: " << timestamp << std::endl; - printIndent(out , int_Indent); - out << "updateTS: " << updateTS << std::endl; - printIndent(out , int_Indent); - out << "transactionNumber: " << transactionNumber << std::endl; - printIndent(out , int_Indent); - - printRsItemEnd(out ,"RsNxsTransac", indent); - return out; -} +#include "rsnxsitems.h" +#include "rsbaseserial.h" +#include "util/rsprint.h" +#include + +/*** + * #define RSSERIAL_DEBUG 1 + ***/ + +const uint8_t RsNxsSyncGrpItem::FLAG_REQUEST = 0x001; +const uint8_t RsNxsSyncGrpItem::FLAG_RESPONSE = 0x002; + +const uint8_t RsNxsSyncMsgItem::FLAG_REQUEST = 0x001; +const uint8_t RsNxsSyncMsgItem::FLAG_RESPONSE = 0x002; + +const uint8_t RsNxsSyncGrpItem::FLAG_USE_SYNC_HASH = 0x001; +const uint8_t RsNxsSyncMsgItem::FLAG_USE_SYNC_HASH = 0x001; + +/** transaction state **/ +const uint16_t RsNxsTransacItem::FLAG_BEGIN_P1 = 0x0001; +const uint16_t RsNxsTransacItem::FLAG_BEGIN_P2 = 0x0002; +const uint16_t RsNxsTransacItem::FLAG_END_SUCCESS = 0x0004; +const uint16_t RsNxsTransacItem::FLAG_CANCEL = 0x0008; +const uint16_t RsNxsTransacItem::FLAG_END_FAIL_NUM = 0x0010; +const uint16_t RsNxsTransacItem::FLAG_END_FAIL_TIMEOUT = 0x0020; +const uint16_t RsNxsTransacItem::FLAG_END_FAIL_FULL = 0x0040; + + +/** transaction type **/ +const uint16_t RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP = 0x0100; +const uint16_t RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP = 0x0200; +const uint16_t RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ = 0x0400; +const uint16_t RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ = 0x0800; +const uint16_t RsNxsTransacItem::FLAG_TYPE_GRPS = 0x1000; +const uint16_t RsNxsTransacItem::FLAG_TYPE_MSGS = 0x2000; +const uint16_t RsNxsTransacItem::FLAG_TYPE_ENCRYPTED_DATA = 0x4000; + +RsItem* RsNxsSerialiser::deserialise(void *data, uint32_t *size) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (SERVICE_TYPE != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: return deserialNxsSyncGrpReqItem(data, size); + case RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM: return deserialNxsSyncGrpItem(data, size); + case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: return deserialNxsSyncMsgReqItem(data, size); + case RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM: return deserialNxsSyncMsgItem(data, size); + case RS_PKT_SUBTYPE_NXS_GRP_ITEM: return deserialNxsGrpItem(data, size); + case RS_PKT_SUBTYPE_NXS_MSG_ITEM: return deserialNxsMsgItem(data, size); + case RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM: return deserialNxsTransacItem(data, size); + case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM:return deserialNxsGroupPublishKeyItem(data, size); + case RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM: return deserialNxsSessionKeyItem(data, size); + case RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM: return deserialNxsEncryptedDataItem(data, size); + case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: return deserialNxsSyncGrpStatsItem(data, size); + + default: + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialise() : data has no type" + << std::endl; +#endif + return NULL; + + } + } +} + + +uint32_t RsNxsSerialiser::size(RsItem *item) +{ + RsNxsItem *nxs_item = dynamic_cast(item) ; + + if(nxs_item != NULL) + return nxs_item->serial_size() ; + else + { + std::cerr << "RsNxsSerialiser::serialise(): Not an RsNxsItem!" << std::endl; + return 0; + } +} + +bool RsNxsSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsNxsItem *nxs_item = dynamic_cast(item) ; + + if(nxs_item != NULL) + return nxs_item->serialise(data,*size) ; + else + { + std::cerr << "RsNxsSerialiser::serialise(): Not an RsNxsItem!" << std::endl; + return 0; + } +} + +bool RsNxsItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) const +{ + tlvsize = serial_size() ; + offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + if(!setRsItemHeader(data, tlvsize, PacketId(), tlvsize)) + { + std::cerr << "RsFileTransferItem::serialise_header(): ERROR. Not enough size!" << std::endl; + return false ; + } +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + offset += 8; + + return true ; +} + +bool RsNxsSyncMsgItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsSynMsgItem()" << std::endl; +#endif + + /* RsNxsSyncMsgItem */ + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= setRawUInt8(data, size, &offset, flag); + ok &= grpId.serialise(data, size, offset); + ok &= msgId.serialise(data, size, offset); + ok &= authorId.serialise(data, size, offset); + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsSynMsgItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseNxsSynMsgItem() NOK" << std::endl; + } +#endif + + return ok; +} + + +bool RsNxsMsg::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= setRawUInt8(data, size, &offset, pos); + ok &= msgId.serialise(data, size, offset); + ok &= grpId.serialise(data, size, offset); + ok &= msg.SetTlv(data, size, &offset); + ok &= meta.SetTlv(data, size, &offset); + + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsMsg() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseNxsMsg() NOK" << std::endl; + } +#endif + + return ok; +} + + +bool RsNxsGrp::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + // grp id + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= setRawUInt8(data, size, &offset, pos); + ok &= grpId.serialise(data, size, offset); + ok &= grp.SetTlv(data, size, &offset); + ok &= meta.SetTlv(data, size, &offset); + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsGrp() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseNxsGrp() NOK" << std::endl; + } +#endif + + return ok; +} + +bool RsNxsSyncGrpStatsItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrpStats()" << std::endl; +#endif + + ok &= setRawUInt32(data, size, &offset, request_type); + ok &= grpId.serialise(data, size, offset) ; + ok &= setRawUInt32(data, size, &offset, number_of_posts); + ok &= setRawUInt32(data, size, &offset, last_post_TS); + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseSyncGrpStats() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseSyncGrpStats() NOK" << std::endl; + } +#endif + + return ok; +} + +bool RsNxsSyncGrpReqItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= setRawUInt8(data, size, &offset, flag); + ok &= setRawUInt32(data, size, &offset, createdSince); + ok &= SetTlvString(data, size, &offset, TLV_TYPE_STR_HASH_SHA1, syncHash); + ok &= setRawUInt32(data, size, &offset, updateTS); + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseSyncGrp() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseSyncGrp() NOK" << std::endl; + } +#endif + + return ok; +} + + +bool RsNxsTransacItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= setRawUInt16(data, size, &offset, transactFlag); + ok &= setRawUInt32(data, size, &offset, nItems); + ok &= setRawUInt32(data, size, &offset, updateTS); + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsTrans() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseNxsTrans() NOK" << std::endl; + } +#endif + + return ok; +} + +bool RsNxsSyncGrpItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + /* RsNxsSyncm */ + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= setRawUInt8(data, size, &offset, flag); + ok &= grpId.serialise(data, size, offset); + ok &= setRawUInt32(data, size, &offset, publishTs); + ok &= authorId.serialise(data, size, offset); + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsSyncm( FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseNxsSyncm() NOK" << std::endl; + } +#endif + + return ok; +} + +bool RsNxsSyncMsgReqItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= setRawUInt8(data, size, &offset, flag); + ok &= setRawUInt32(data, size, &offset, createdSince); + ok &= SetTlvString(data, size, &offset, TLV_TYPE_STR_HASH_SHA1, syncHash); + ok &= grpId.serialise(data, size, offset); + ok &= setRawUInt32(data, size, &offset, updateTS); + + if(offset != tlvsize){ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsNxsSerialiser::serialiseNxsSyncMsg( NOK" << std::endl; + } +#endif + + return ok; +} + + +bool RsNxsGroupPublishKeyItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= grpId.serialise(data, size, offset) ; + ok &= key.SetTlv(data, size, &offset) ; + + if(offset != tlvsize) + { + std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem() FAIL Size Error! " << std::endl; + ok = false; + } + + if (!ok) + std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem( NOK" << std::endl; + + return ok; +} + +bool RsNxsSessionKeyItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + + if(offset + EVP_MAX_IV_LENGTH >= size) + { + std::cerr << "RsNxsSessionKeyItem::serialize(): error. Not enough room for IV !" << std::endl; + return false ; + } + memcpy(&((uint8_t*)data)[offset],iv,EVP_MAX_IV_LENGTH) ; + offset += EVP_MAX_IV_LENGTH ; + + ok &= setRawUInt32(data, size, &offset, encrypted_session_keys.size()); + + for(std::map::const_iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it) + { + ok &= it->first.serialise(data, size, offset) ; + ok &= it->second.SetTlv(data, size, &offset) ; + } + + if(offset != tlvsize) + { + std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem() FAIL Size Error! " << std::endl; + ok = false; + } + + if (!ok) + std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem( NOK" << std::endl; + + return ok; +} +bool RsNxsEncryptedDataItem::serialise(void *data, uint32_t& size) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + ok &= setRawUInt32(data, size, &offset, transactionNumber); + ok &= encrypted_data.SetTlv(data, size, &offset) ; + + if(offset != tlvsize) + { + std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem() FAIL Size Error! " << std::endl; + ok = false; + } + + if (!ok) + std::cerr << "RsNxsSerialiser::serialiseGroupPublishKeyItem( NOK" << std::endl; + + return ok; +} + + + +/*** deserialisation ***/ + +RsNxsGrp* RsNxsSerialiser::deserialNxsGrpItem(void *data, uint32_t *size) +{ + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_GRP_ITEM); + uint32_t offset = 8; + + RsNxsGrp* item = new RsNxsGrp(SERVICE_TYPE); + + /* skip the header */ + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + ok &= getRawUInt8(data, *size, &offset, &(item->pos)); + ok &= item->grpId.deserialise(data, *size, offset); + ok &= item->grp.GetTlv(data, *size, &offset); + ok &= item->meta.GetTlv(data, *size, &offset); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGrp() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGrp() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +RsNxsMsg* RsNxsSerialiser::deserialNxsMsgItem(void *data, uint32_t *size){ + + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_MSG_ITEM); + uint32_t offset = 8; + + RsNxsMsg* item = new RsNxsMsg(SERVICE_TYPE); + /* skip the header */ + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + ok &= getRawUInt8(data, *size, &offset, &(item->pos)); + ok &= item->msgId.deserialise(data, *size, offset); + ok &= item->grpId.deserialise(data, *size, offset); + ok &= item->msg.GetTlv(data, *size, &offset); + ok &= item->meta.GetTlv(data, *size, &offset); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsMsg() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsMsg() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +RsNxsSyncGrpStatsItem* RsNxsSerialiser::deserialNxsSyncGrpStatsItem(void *data, uint32_t *size) +{ + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM); + uint32_t offset = 8; + + RsNxsSyncGrpStatsItem* item = new RsNxsSyncGrpStatsItem(SERVICE_TYPE) ; + /* skip the header */ + + ok &= getRawUInt32(data, *size, &offset, &(item->request_type)); + ok &= item->grpId.deserialise(data, *size, offset) ; + ok &= getRawUInt32(data, *size, &offset, &(item->number_of_posts)); + ok &= getRawUInt32(data, *size, &offset, &(item->last_post_TS)); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +bool RsNxsSerialiser::checkItemHeader(void *data,uint32_t *size,uint8_t subservice_type) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::checkItemHeader()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (SERVICE_TYPE != getRsItemService(rstype)) || (subservice_type != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::checkItemHeader() FAIL wrong type" << std::endl; +#endif + return false; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::checkItemHeader() FAIL wrong size" << std::endl; +#endif + return false; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + return true ; +} + +RsNxsSyncGrpReqItem* RsNxsSerialiser::deserialNxsSyncGrpReqItem(void *data, uint32_t *size) +{ + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM); + + RsNxsSyncGrpReqItem* item = new RsNxsSyncGrpReqItem(SERVICE_TYPE); + /* skip the header */ + uint32_t offset = 8; + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + ok &= getRawUInt8(data, *size, &offset, &(item->flag)); + ok &= getRawUInt32(data, *size, &offset, &(item->createdSince)); + ok &= GetTlvString(data, *size, &offset, TLV_TYPE_STR_HASH_SHA1, item->syncHash); + ok &= getRawUInt32(data, *size, &offset, &(item->updateTS)); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncGrp() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +RsNxsSyncGrpItem* RsNxsSerialiser::deserialNxsSyncGrpItem(void *data, uint32_t *size){ + + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM); + + RsNxsSyncGrpItem* item = new RsNxsSyncGrpItem(SERVICE_TYPE); + /* skip the header */ + uint32_t offset = 8; + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + ok &= getRawUInt8(data, *size, &offset, &(item->flag)); + ok &= item->grpId.deserialise(data, *size, offset); + ok &= getRawUInt32(data, *size, &offset, &(item->publishTs)); + ok &= item->authorId.deserialise(data, *size, offset); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +RsNxsTransacItem* RsNxsSerialiser::deserialNxsTransacItem(void *data, uint32_t *size){ + + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM); + uint32_t offset = 8 ; + + RsNxsTransacItem* item = new RsNxsTransacItem(SERVICE_TYPE); + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + ok &= getRawUInt16(data, *size, &offset, &(item->transactFlag)); + ok &= getRawUInt32(data, *size, &offset, &(item->nItems)); + ok &= getRawUInt32(data, *size, &offset, &(item->updateTS)); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsTrans() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsTrans() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; + + +} + +RsNxsSyncMsgItem* RsNxsSerialiser::deserialNxsSyncMsgItem(void *data, uint32_t *size){ + + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM); + uint32_t offset = 8 ; + + RsNxsSyncMsgItem* item = new RsNxsSyncMsgItem(SERVICE_TYPE); + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + ok &= getRawUInt8(data, *size, &offset, &(item->flag)); + ok &= item->grpId.deserialise(data, *size, offset); + ok &= item->msgId.deserialise(data, *size, offset); + ok &= item->authorId.deserialise(data, *size, offset); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncMsgItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +RsNxsSyncMsgReqItem* RsNxsSerialiser::deserialNxsSyncMsgReqItem(void *data, uint32_t *size) +{ + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM); + uint32_t offset = 8 ; + + RsNxsSyncMsgReqItem* item = new RsNxsSyncMsgReqItem(SERVICE_TYPE); + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + ok &= getRawUInt8(data, *size, &offset, &(item->flag)); + ok &= getRawUInt32(data, *size, &offset, &(item->createdSince)); + ok &= GetTlvString(data, *size, &offset, TLV_TYPE_STR_HASH_SHA1, item->syncHash); + ok &= item->grpId.deserialise(data, *size, offset); + ok &= getRawUInt32(data, *size, &offset, &(item->updateTS)); + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncMsg() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsSyncMsg() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} +RsNxsGroupPublishKeyItem* RsNxsSerialiser::deserialNxsGroupPublishKeyItem(void *data, uint32_t *size) +{ + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM); + uint32_t offset = 8 ; + + RsNxsGroupPublishKeyItem* item = new RsNxsGroupPublishKeyItem(SERVICE_TYPE); + + ok &= item->grpId.deserialise(data, *size, offset); + ok &= item->key.GetTlv(data, *size, &offset) ; + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +RsNxsSessionKeyItem *RsNxsSerialiser::deserialNxsSessionKeyItem(void* data, uint32_t *size) +{ + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM); + uint32_t offset = 8 ; + + RsNxsSessionKeyItem* item = new RsNxsSessionKeyItem(SERVICE_TYPE); + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + + if(offset + EVP_MAX_IV_LENGTH >= *size) + { + std::cerr << __PRETTY_FUNCTION__ << ": not enough room for IV." << std::endl; + return NULL ; + } + memcpy(item->iv,&((uint8_t*)data)[offset],EVP_MAX_IV_LENGTH) ; + offset += EVP_MAX_IV_LENGTH ; + + uint32_t n ; + ok &= getRawUInt32(data, *size, &offset, &n) ; + + for(uint32_t i=0;ok && iencrypted_session_keys[gxs_id] = bdata ; + } + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} +RsNxsEncryptedDataItem *RsNxsSerialiser::deserialNxsEncryptedDataItem(void* data, uint32_t *size) +{ + bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM); + uint32_t offset = 8 ; + + RsNxsEncryptedDataItem* item = new RsNxsEncryptedDataItem(SERVICE_TYPE); + + ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber)); + item->encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ; + + ok &= item->encrypted_data.GetTlv(data,*size,&offset) ; + + if (offset != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsNxsSerialiser::deserialNxsGroupPublishKeyItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +/*** size functions ***/ + + +uint32_t RsNxsMsg::serial_size()const +{ + + uint32_t s = 8; //header size + + s += 4; // transaction number + s += 1; // pos + s += grpId.serial_size(); + s += msgId.serial_size(); + s += msg.TlvSize(); + s += meta.TlvSize(); + + return s; +} + +uint32_t RsNxsGrp::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // transaction number + s += 1; // pos + s += grpId.serial_size(); + s += grp.TlvSize(); + s += meta.TlvSize(); + + return s; +} + +uint32_t RsNxsGroupPublishKeyItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += grpId.serial_size() ; + s += key.TlvSize(); + + return s; +} +uint32_t RsNxsSyncGrpReqItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // transaction number + s += 1; // flag + s += 4; // sync age + s += GetTlvStringSize(syncHash); + s += 4; // updateTS + + return s; +} +uint32_t RsNxsSyncGrpStatsItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // request type + s += grpId.serial_size(); + s += 4; // number_of_posts + s += 4; // last_post_TS + + return s; +} + +uint32_t RsNxsSyncGrpItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // transaction number + s += 4; // publishTs + s += 1; // flag + s += grpId.serial_size(); + s += authorId.serial_size(); + + return s; +} + + +uint32_t RsNxsSyncMsgReqItem::serial_size() const +{ + + uint32_t s = 8; + + s += 4; // transaction number + s += 1; // flag + s += 4; // age + s += grpId.serial_size(); + s += GetTlvStringSize(syncHash); + s += 4; // updateTS + + return s; +} + + +uint32_t RsNxsSyncMsgItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // transaction number + s += 1; // flag + s += grpId.serial_size(); + s += msgId.serial_size(); + s += authorId.serial_size(); + + return s; +} + +uint32_t RsNxsTransacItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // transaction number + s += 2; // flag + s += 4; // nMsgs + s += 4; // updateTS + + return s; +} +uint32_t RsNxsEncryptedDataItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // transaction number + s += encrypted_data.TlvSize() ; + + return s; +} +uint32_t RsNxsSessionKeyItem::serial_size() const +{ + uint32_t s = 8; // header size + + s += 4; // transaction number + s += EVP_MAX_IV_LENGTH ; // iv + s += 4 ; // encrypted_session_keys.size() ; + + for(std::map::const_iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it) + s += it->first.serial_size() + it->second.TlvSize() ; + + return s; +} + + + + +int RsNxsGrp::refcount = 0; +/** print and clear functions **/ +int RsNxsMsg::refcount = 0; +void RsNxsMsg::clear() +{ + + msg.TlvClear(); + meta.TlvClear(); +} + +void RsNxsGrp::clear() +{ + grpId.clear(); + grp.TlvClear(); + meta.TlvClear(); +} + +void RsNxsSyncGrpReqItem::clear() +{ + flag = 0; + createdSince = 0; + syncHash.clear(); + updateTS = 0; +} +void RsNxsGroupPublishKeyItem::clear() +{ + key.TlvClear(); +} +void RsNxsSyncMsgReqItem::clear() +{ + grpId.clear(); + flag = 0; + createdSince = 0; + syncHash.clear(); + updateTS = 0; +} +void RsNxsSyncGrpItem::clear() +{ + flag = 0; + publishTs = 0; + grpId.clear(); + authorId.clear(); +} + +void RsNxsSyncMsgItem::clear() +{ + flag = 0; + msgId.clear(); + grpId.clear(); + authorId.clear(); +} + +void RsNxsTransacItem::clear(){ + transactFlag = 0; + nItems = 0; + updateTS = 0; + timestamp = 0; + transactionNumber = 0; +} +void RsNxsEncryptedDataItem::clear(){ + encrypted_data.TlvClear() ; +} +void RsNxsSessionKeyItem::clear() +{ + for(std::map::iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it) + it->second.TlvClear() ; + + encrypted_session_keys.clear() ; +} + +std::ostream& RsNxsSyncGrpReqItem::print(std::ostream &out, uint16_t indent) +{ + + printRsItemBase(out, "RsNxsSyncGrp", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out , int_Indent); + out << "Hash: " << syncHash << std::endl; + printIndent(out , int_Indent); + out << "Sync Age: " << createdSince << std::endl; + printIndent(out , int_Indent); + out << "flag: " << (uint32_t) flag << std::endl; + printIndent(out , int_Indent); + out << "updateTS: " << updateTS << std::endl; + + printRsItemEnd(out ,"RsNxsSyncGrp", indent); + + return out; +} +std::ostream& RsNxsGroupPublishKeyItem::print(std::ostream &out, uint16_t indent) +{ + + printRsItemBase(out, "RsNxsGroupPublishKeyItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out , int_Indent); + out << "GroupId: " << grpId << std::endl; + printIndent(out , int_Indent); + out << "keyId: " << key.keyId << std::endl; + + printRsItemEnd(out ,"RsNxsGroupPublishKeyItem", indent); + + return out; +} + + +std::ostream& RsNxsSyncMsgReqItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsNxsSyncMsg", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out , int_Indent); + out << "GrpId: " << grpId << std::endl; + printIndent(out , int_Indent); + out << "createdSince: " << createdSince << std::endl; + printIndent(out , int_Indent); + out << "syncHash: " << syncHash << std::endl; + printIndent(out , int_Indent); + out << "flag: " << (uint32_t) flag << std::endl; + printIndent(out , int_Indent); + out << "updateTS: " << updateTS << std::endl; + + printRsItemEnd(out, "RsNxsSyncMsg", indent); + return out; +} + +std::ostream& RsNxsSyncGrpItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsNxsSyncGrpItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out , int_Indent); + out << "flag: " << (uint32_t) flag << std::endl; + printIndent(out , int_Indent); + out << "grpId: " << grpId << std::endl; + printIndent(out , int_Indent); + out << "publishTs: " << publishTs << std::endl; + printIndent(out , int_Indent); + out << "authorId: " << authorId << std::endl; + + printRsItemEnd(out , "RsNxsSyncGrpItem", indent); + return out; +} + + + +std::ostream& RsNxsSyncMsgItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsNxsSyncMsgItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out , int_Indent); + out << "flag: " << (uint32_t) flag << std::endl; + printIndent(out , int_Indent); + out << "grpId: " << grpId << std::endl; + printIndent(out , int_Indent); + out << "msgId: " << msgId << std::endl; + printIndent(out , int_Indent); + out << "authorId: " << authorId << std::endl; + printIndent(out , int_Indent); + + printRsItemEnd(out ,"RsNxsSyncMsgItem", indent); + return out; +} + +RsNxsGrp* RsNxsGrp::clone() const { + RsNxsGrp* grp = new RsNxsGrp(PacketService()); + *grp = *this; + + if(this->metaData) + { + grp->metaData = new RsGxsGrpMetaData(); + *(grp->metaData) = *(this->metaData); + } + + return grp; +} + +std::ostream& RsNxsGrp::print(std::ostream &out, uint16_t indent){ + + printRsItemBase(out, "RsNxsGrp", indent); + uint16_t int_Indent = indent + 2; + + out << "grpId: " << grpId << std::endl; + printIndent(out , int_Indent); + out << "grp: " << std::endl; + printIndent(out , int_Indent); + out << "pos: " << pos << std::endl; + grp.print(out, int_Indent); + out << "meta: " << std::endl; + meta.print(out, int_Indent); + + printRsItemEnd(out, "RsNxsGrp", indent); + return out; +} + +std::ostream& RsNxsMsg::print(std::ostream &out, uint16_t indent){ + + printRsItemBase(out, "RsNxsMsg", indent); + uint16_t int_Indent = indent + 2; + + out << "msgId: " << msgId << std::endl; + printIndent(out , int_Indent); + out << "grpId: " << grpId << std::endl; + printIndent(out , int_Indent); + out << "pos: " << pos << std::endl; + printIndent(out , int_Indent); + out << "msg: " << std::endl; + msg.print(out, indent); + out << "meta: " << std::endl; + meta.print(out, int_Indent); + + printRsItemEnd(out ,"RsNxsMsg", indent); + return out; +} + +std::ostream& RsNxsSyncGrpStatsItem::print(std::ostream &out, uint16_t indent){ + + printRsItemBase(out, "RsNxsSyncGrpStats", indent); + uint16_t int_Indent = indent + 2; + + out << "available posts: " << number_of_posts << std::endl; + printIndent(out , int_Indent); + out << "last update: " << last_post_TS << std::endl; + printIndent(out , int_Indent); + out << "group ID: " << grpId << std::endl; + printIndent(out , int_Indent); + out << "request type: " << request_type << std::endl; + printIndent(out , int_Indent); + + printRsItemEnd(out ,"RsNxsSyncGrpStats", indent); + return out; +} +std::ostream& RsNxsTransacItem::print(std::ostream &out, uint16_t indent){ + + printRsItemBase(out, "RsNxsTransac", indent); + uint16_t int_Indent = indent + 2; + + out << "transactFlag: " << transactFlag << std::endl; + printIndent(out , int_Indent); + out << "nItems: " << nItems << std::endl; + printIndent(out , int_Indent); + out << "timeout: " << timestamp << std::endl; + printIndent(out , int_Indent); + out << "updateTS: " << updateTS << std::endl; + printIndent(out , int_Indent); + out << "transactionNumber: " << transactionNumber << std::endl; + printIndent(out , int_Indent); + + printRsItemEnd(out ,"RsNxsTransac", indent); + return out; +} +std::ostream& RsNxsSessionKeyItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsNxsSessionKeyItem", indent); + + out << " iv: " << RsUtil::BinToHex((char*)iv,EVP_MAX_IV_LENGTH) << std::endl; + + out << " encrypted keys: " << std::endl; + + for(std::map::const_iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it) + out << " id=" << it->first << ": ekey=" << RsUtil::BinToHex((char*)it->second.bin_data,it->second.bin_len) << std::endl; + + printRsItemEnd(out ,"RsNxsSessionKeyItem", indent); + return out; +} +std::ostream& RsNxsEncryptedDataItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsNxsEncryptedDataItem", indent); + + out << " encrypted data: " << RsUtil::BinToHex((char*)encrypted_data.bin_data,std::min(50u,encrypted_data.bin_len)) ; + + if(encrypted_data.bin_len > 50u) + out << "..." ; + + out << std::endl; + + printRsItemEnd(out ,"RsNxsSessionKeyItem", indent); + return out; +} diff --git a/libretroshare/src/serialiser/rsnxsitems.h b/libretroshare/src/serialiser/rsnxsitems.h index 76a4d91b3..6be81ecbe 100644 --- a/libretroshare/src/serialiser/rsnxsitems.h +++ b/libretroshare/src/serialiser/rsnxsitems.h @@ -1,522 +1,578 @@ -#ifndef RSNXSITEMS_H -#define RSNXSITEMS_H - -/* - * libretroshare/src/serialiser: rsnxssitems.h - * - * RetroShare Serialiser. - * - * Copyright 2012 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 - -#include "serialiser/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvkeys.h" -#include "gxs/rsgxsdata.h" - -// These items have "flag type" numbers, but this is not used. - -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP = 0x01; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS = 0x03; -const uint8_t RS_PKT_SUBTYPE_NXS_GRP = 0x04; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM = 0x08; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG = 0x10; -const uint8_t RS_PKT_SUBTYPE_NXS_MSG = 0x20; -const uint8_t RS_PKT_SUBTYPE_NXS_TRANS = 0x40; -const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY = 0x80; - - -// possibility create second service to deal with this functionality - -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_GRP = 0x0001; -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_MSG = 0x0002; -const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_GRP = 0x0004; -const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_MSG = 0x0008; -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010; - - -/*! - * Base class for Network exchange service - * Main purpose is for rtti based routing used in the - * serialisation and deserialisation of NXS packets - * - * Service type is set by plugin service - */ -class RsNxsItem : public RsItem -{ - -public: - RsNxsItem(uint16_t servtype, uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0) - { - setPriorityLevel(QOS_PRIORITY_RS_GXS_NET); - return; - } - virtual ~RsNxsItem(){ return; } - - virtual void clear() = 0; - virtual std::ostream &print(std::ostream &out, uint16_t indent = 0) = 0; - - uint32_t transactionNumber; // set to zero if this is not a transaction item -}; - - -/*! - * Use to request grp list from peer - * Server may advise client peer to use sync file - * while serving his request. This results - */ -class RsNxsSyncGrp : public RsNxsItem { - -public: - - static const uint8_t FLAG_USE_SYNC_HASH; - static const uint8_t FLAG_ONLY_CURRENT; // only send most current version of grps / ignores sync hash - - RsNxsSyncGrp(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP) { clear(); return;} - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - uint8_t flag; // advises whether to use sync hash - uint32_t createdSince; // how far back to sync data - uint32_t updateTS; // time of last group update - std::string syncHash; // use to determine if changes that have occured since last hash - - -}; - -/*! - * Use to request statistics about a particular group - */ -class RsNxsSyncGrpStats : public RsNxsItem -{ -public: - - RsNxsSyncGrpStats(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS) {} - - virtual void clear() {} - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - static const uint8_t GROUP_INFO_TYPE_REQUEST = 0x01; - static const uint8_t GROUP_INFO_TYPE_RESPONSE = 0x02; - - uint32_t request_type; // used to determine the type of request - RsGxsGroupId grpId; // id of the group - uint32_t number_of_posts; // number of posts in that group - uint32_t last_post_TS; // time_stamp of last post -}; - -/*! - * Use to request grp list from peer - * Server may advise client peer to use sync file - * while serving his request. This results - */ -class RsNxsGroupPublishKeyItem : public RsNxsItem -{ -public: - RsNxsGroupPublishKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY) { clear(); return;} - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - RsGxsGroupId grpId ; - RsTlvSecurityKey key ; -}; - - - -/*! - * This RsNxsItem is for use in enabling transactions - * in order to guaranttee a collection of item have been - * received - */ -class RsNxsTransac : public RsNxsItem { - -public: - - static const uint16_t FLAG_STATE_MASK = 0xff; - static const uint16_t FLAG_TYPE_MASK = 0xff00; - - /** transaction state **/ - static const uint16_t FLAG_BEGIN_P1; - static const uint16_t FLAG_BEGIN_P2; - static const uint16_t FLAG_END_SUCCESS; - static const uint16_t FLAG_CANCEL; - static const uint16_t FLAG_END_FAIL_NUM; - static const uint16_t FLAG_END_FAIL_TIMEOUT; - static const uint16_t FLAG_END_FAIL_FULL; - - - /** transaction type **/ - static const uint16_t FLAG_TYPE_GRP_LIST_RESP; - static const uint16_t FLAG_TYPE_MSG_LIST_RESP; - static const uint16_t FLAG_TYPE_GRP_LIST_REQ; - static const uint16_t FLAG_TYPE_MSG_LIST_REQ; - static const uint16_t FLAG_TYPE_GRPS; - static const uint16_t FLAG_TYPE_MSGS; - - RsNxsTransac(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_TRANS) { clear(); return; } - virtual ~RsNxsTransac() { return ; } - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - uint16_t transactFlag; - uint32_t nItems; - uint32_t updateTS; - - // not serialised - uint32_t timestamp; -}; - -/*! - * Use to send to peer list of grps - * held by server peer - */ -class RsNxsSyncGrpItem : public RsNxsItem -{ - -public: - - static const uint8_t FLAG_REQUEST; - static const uint8_t FLAG_RESPONSE; - static const uint8_t FLAG_USE_SYNC_HASH; - - RsNxsSyncGrpItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM) { clear(); return ; } - virtual ~RsNxsSyncGrpItem() { return; } - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - - uint8_t flag; // request or response - - uint32_t publishTs; // to compare to Ts of receiving peer's grp of same id - - /// grpId of grp held by sending peer - RsGxsGroupId grpId; - RsGxsId authorId; - -}; - -/*! - * Contains serialised group items - * Each item corresponds to a group which needs to be - * deserialised - */ -class RsNxsGrp : public RsNxsItem -{ - -public: - - RsNxsGrp(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP), grp(servtype), meta(servtype), - metaData(NULL) { clear(); - //std::cout << "\nGrp refcount++ : " << ++refcount << std::endl; - return; } - virtual ~RsNxsGrp() { if(metaData) delete metaData; - //std::cout << "\nGrp refcount-- : " << --refcount << std::endl; - } - - RsNxsGrp* clone() const; - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - RsGxsGroupId grpId; /// group Id, needed to complete version Id (ncvi) - static int refcount; - RsTlvBinaryData grp; /// actual group data - uint8_t pos; /// used for splitting up grp - uint8_t count; /// number of split up messages - - /*! - * This should contains all data - * which is not specific to the Gxs service data - */ - RsTlvBinaryData meta; - - // deserialised metaData, this is not serialised - RsGxsGrpMetaData* metaData; -}; - -/*! - * Use to request list of msg held by peer - * for a given group - */ -class RsNxsSyncMsg : public RsNxsItem -{ - -public: - - static const uint8_t FLAG_USE_SYNC_HASH; - - RsNxsSyncMsg(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG) { clear(); return; } - - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - RsGxsGroupId grpId; - uint8_t flag; - uint32_t createdSince; - uint32_t updateTS; // time of last update - std::string syncHash; -}; - -/*! - * Use to send list msgs for a group held by - * a peer - */ -class RsNxsSyncMsgItem : public RsNxsItem -{ -public: - - static const uint8_t FLAG_REQUEST; - static const uint8_t FLAG_RESPONSE; - static const uint8_t FLAG_USE_SYNC_HASH; - RsNxsSyncMsgItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM) { clear(); return; } - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - uint8_t flag; // response/req - RsGxsGroupId grpId; - RsGxsMessageId msgId; - RsGxsId authorId; - -}; - - -/*! - * Used to respond to a RsGrpMsgsReq - * with message items satisfying request - */ -class RsNxsMsg : public RsNxsItem -{ -public: - - RsNxsMsg(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_MSG), meta(servtype), msg(servtype), - metaData(NULL) { - // std::cout << "\nrefcount++ : " << ++refcount << std::endl; - clear(); return; - } - virtual ~RsNxsMsg() - { - //std::cout << "\nrefcount-- : " << --refcount << std::endl; - if(metaData){ - //std::cout << "\ndeleted\n"; - delete metaData; - } - } - - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); - - uint8_t pos; /// used for splitting up msg - uint8_t count; /// number of split up messages - RsGxsGroupId grpId; /// group id, forms part of version id - RsGxsMessageId msgId; /// msg id - static int refcount; - - /*! - * This should contains all the data - * which is not specific to the Gxs service data - */ - RsTlvBinaryData meta; - - /*! - * This contains Gxs specific data - * only client of API knows who to decode this - */ - RsTlvBinaryData msg; - - RsGxsMsgMetaData* metaData; - -}; - -/*! - * Used to request a search of user data - */ -class RsNxsSearchReq : public RsNxsItem -{ -public: - - RsNxsSearchReq(uint16_t servtype): RsNxsItem(servtype, RS_PKT_SUBTYPE_EXT_SEARCH_REQ), serviceSearchItem(servtype) { return; } - virtual ~RsNxsSearchReq() { return;} - - virtual void clear() { return;} - virtual std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } - - uint8_t nHops; /// how many peers to jump to - uint32_t token; // search token - RsTlvBinaryData serviceSearchItem; // service aware of item class - uint32_t expiration; // expiration date -}; - - -/*! - * Used to respond to a RsGrpSearchReq - * with grpId/MsgIds that satisfy search request - */ -class RsNxsSearchResultMsg -{ -public: - - RsNxsSearchResultMsg() : context(0) { return;} - void clear() {} - std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } - - uint32_t token; // search token to be redeemed - RsTlvBinaryData context; // used by client service - std::string msgId; - std::string grpId; - RsTlvKeySignature idSign; - - uint32_t expiration; // expiration date -}; - -/*! - * Used to respond to a RsGrpSearchReq - * with grpId/MsgIds that satisfy search request - */ -class RsNxsSearchResultGrp -{ -public: - - RsNxsSearchResultGrp(); - void clear() {} - std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } - - uint32_t token; // search token to be redeemed - - RsTlvBinaryData context; // used by client service - - std::string grpId; - RsTlvKeySignature adminSign; - - uint32_t expiration; // expiration date -}; - - -class RsNxsDeleteMsg -{ -public: - - RsNxsDeleteMsg() { return; } - - std::string msgId; - std::string grpId; - RsTlvKeySignature deleteSign; // ( msgId + grpId + msg data ) sign //TODO: add warning not to place msgId+grpId in msg! - -}; - -class RsNxsDeleteGrp -{ -public: - - RsNxsDeleteGrp() { return;} - - std::string grpId; - RsTlvKeySignature idSign; - RsTlvKeySignature deleteSign; // (grpId + grp data) sign // TODO: add warning not to place grpId in msg -}; - - - -class RsNxsSerialiser : public RsSerialType -{ -public: - - RsNxsSerialiser(uint16_t servtype) : - RsSerialType(RS_PKT_VERSION_SERVICE, servtype), SERVICE_TYPE(servtype) { return; } - - virtual ~RsNxsSerialiser() { return; } - - virtual uint32_t size(RsItem *item); - virtual bool serialise(RsItem *item, void *data, uint32_t *size); - virtual RsItem* deserialise(void *data, uint32_t *size); - -private: - - - /* for RS_PKT_SUBTYPE_SYNC_GRP */ - - virtual uint32_t sizeNxsSyncGrp(RsNxsSyncGrp* item); - virtual bool serialiseNxsSyncGrp(RsNxsSyncGrp *item, void *data, uint32_t *size); - virtual RsNxsSyncGrp* deserialNxsSyncGrp(void *data, uint32_t *size); - - virtual uint32_t sizeNxsSyncGrpStats(RsNxsSyncGrpStats* item); - virtual bool serialiseNxsSyncGrpStats(RsNxsSyncGrpStats *item, void *data, uint32_t *size); - virtual RsNxsSyncGrpStats* deserialNxsSyncGrpStats(void *data, uint32_t *size); - - /* for RS_PKT_SUBTYPE_SYNC_GRP_ITEM */ - - virtual uint32_t sizeNxsSyncGrpItem(RsNxsSyncGrpItem* item); - virtual bool serialiseNxsSyncGrpItem(RsNxsSyncGrpItem *item, void *data, uint32_t *size); - virtual RsNxsSyncGrpItem* deserialNxsSyncGrpItem(void *data, uint32_t *size); - - /* for RS_PKT_SUBTYPE_NXS_GRP */ - - virtual uint32_t sizeNxsGrp(RsNxsGrp* item); - virtual bool serialiseNxsGrp(RsNxsGrp *item, void *data, uint32_t *size); - virtual RsNxsGrp* deserialNxsGrp(void *data, uint32_t *size); - - /* for RS_PKT_SUBTYPE_SYNC_MSG */ - - virtual uint32_t sizeNxsSyncMsg(RsNxsSyncMsg* item); - virtual bool serialiseNxsSyncMsg(RsNxsSyncMsg *item, void *data, uint32_t *size); - virtual RsNxsSyncMsg* deserialNxsSyncMsg(void *data, uint32_t *size); - - /* RS_PKT_SUBTYPE_SYNC_MSG_ITEM */ - - virtual uint32_t sizeNxsSyncMsgItem(RsNxsSyncMsgItem* item); - virtual bool serialiseNxsSynMsgItem(RsNxsSyncMsgItem* item, void *data, uint32_t* size); - virtual RsNxsSyncMsgItem* deserialNxsSyncMsgItem(void *data, uint32_t *size); - - /* RS_PKT_SUBTYPE_NXS_MSG */ - - virtual uint32_t sizeNxsMsg(RsNxsMsg* item); - virtual bool serialiseNxsMsg(RsNxsMsg* item, void* data, uint32_t* size); - virtual RsNxsMsg* deserialNxsMsg(void *data, uint32_t *size); - - /* RS_PKT_SUBTYPE_NXS_TRANS */ - virtual uint32_t sizeNxsTrans(RsNxsTransac* item); - virtual bool serialiseNxsTrans(RsNxsTransac* item, void* data, uint32_t* size); - virtual RsNxsTransac* deserialNxsTrans(void* data, uint32_t *size); - - /* RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY */ - virtual uint32_t sizeNxsGroupPublishKeyItem(RsNxsGroupPublishKeyItem* item); - virtual bool serialiseNxsGroupPublishKeyItem(RsNxsGroupPublishKeyItem* item, void* data, uint32_t* size); - virtual RsNxsGroupPublishKeyItem* deserialNxsGroupPublishKeyItem(void* data, uint32_t *size); - - -private: - - const uint16_t SERVICE_TYPE; -}; - - -#endif // RSNXSITEMS_H +#ifndef RSNXSITEMS_H +#define RSNXSITEMS_H + +/* + * libretroshare/src/serialiser: rsnxssitems.h + * + * RetroShare Serialiser. + * + * Copyright 2012 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 +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvitem.h" +#include "serialiser/rstlvkeys.h" +#include "gxs/rsgxsdata.h" + +// These items have "flag type" numbers, but this is not used. + +const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM = 0x01; +const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM = 0x03; +const uint8_t RS_PKT_SUBTYPE_NXS_GRP_ITEM = 0x04; +const uint8_t RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM = 0x05; +const uint8_t RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM = 0x06; +const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM = 0x08; +const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM = 0x10; +const uint8_t RS_PKT_SUBTYPE_NXS_MSG_ITEM = 0x20; +const uint8_t RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM = 0x40; +const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM = 0x80; + +// possibility create second service to deal with this functionality + +const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_GRP = 0x0001; +const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_MSG = 0x0002; +const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_GRP = 0x0004; +const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_MSG = 0x0008; +const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010; + + +/*! + * Base class for Network exchange service + * Main purpose is for rtti based routing used in the + * serialisation and deserialisation of NXS packets + * + * Service type is set by plugin service + */ +class RsNxsItem : public RsItem +{ + +public: + RsNxsItem(uint16_t servtype, uint8_t subtype) + : RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0) + { + setPriorityLevel(QOS_PRIORITY_RS_GXS_NET); + return; + } + virtual ~RsNxsItem(){} + + virtual bool serialise(void *data,uint32_t& size) const = 0 ; + virtual uint32_t serial_size() const = 0 ; + virtual void clear() = 0; + virtual std::ostream &print(std::ostream &out, uint16_t indent = 0) = 0; + + bool serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) const; + + uint32_t transactionNumber; // set to zero if this is not a transaction item +}; + + +/*! + * Use to request grp list from peer + * Server may advise client peer to use sync file + * while serving his request. This results + */ +class RsNxsSyncGrpReqItem : public RsNxsItem +{ +public: + + static const uint8_t FLAG_USE_SYNC_HASH; + static const uint8_t FLAG_ONLY_CURRENT; // only send most current version of grps / ignores sync hash + + RsNxsSyncGrpReqItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM) { clear(); return;} + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const ; + + uint8_t flag; // advises whether to use sync hash + uint32_t createdSince; // how far back to sync data + uint32_t updateTS; // time of last group update + std::string syncHash; // use to determine if changes that have occured since last hash +}; + +/*! + * Use to request statistics about a particular group + */ +class RsNxsSyncGrpStatsItem : public RsNxsItem +{ +public: + + RsNxsSyncGrpStatsItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM) {} + + virtual void clear() {} + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const ; + + static const uint8_t GROUP_INFO_TYPE_REQUEST = 0x01; + static const uint8_t GROUP_INFO_TYPE_RESPONSE = 0x02; + + uint32_t request_type; // used to determine the type of request + RsGxsGroupId grpId; // id of the group + uint32_t number_of_posts; // number of posts in that group + uint32_t last_post_TS; // time_stamp of last post +}; + +/*! + * Use to request grp list from peer + * Server may advise client peer to use sync file + * while serving his request. This results + */ +class RsNxsGroupPublishKeyItem : public RsNxsItem +{ +public: + RsNxsGroupPublishKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM) { clear(); return;} + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + RsGxsGroupId grpId ; + RsTlvSecurityKey key ; +}; + + + +/*! + * This RsNxsItem is for use in enabling transactions + * in order to guaranttee a collection of item have been + * received + */ +class RsNxsTransacItem: public RsNxsItem { + +public: + + static const uint16_t FLAG_STATE_MASK = 0xff; + static const uint16_t FLAG_TYPE_MASK = 0xff00; + + /** transaction state **/ + static const uint16_t FLAG_BEGIN_P1; + static const uint16_t FLAG_BEGIN_P2; + static const uint16_t FLAG_END_SUCCESS; + static const uint16_t FLAG_CANCEL; + static const uint16_t FLAG_END_FAIL_NUM; + static const uint16_t FLAG_END_FAIL_TIMEOUT; + static const uint16_t FLAG_END_FAIL_FULL; + + + /** transaction type **/ + static const uint16_t FLAG_TYPE_GRP_LIST_RESP; + static const uint16_t FLAG_TYPE_MSG_LIST_RESP; + static const uint16_t FLAG_TYPE_GRP_LIST_REQ; + static const uint16_t FLAG_TYPE_MSG_LIST_REQ; + static const uint16_t FLAG_TYPE_GRPS; + static const uint16_t FLAG_TYPE_MSGS; + static const uint16_t FLAG_TYPE_ENCRYPTED_DATA; + + RsNxsTransacItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM) { clear(); return; } + virtual ~RsNxsTransacItem() { return ; } + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const ; + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + uint16_t transactFlag; + uint32_t nItems; + uint32_t updateTS; + + // not serialised + uint32_t timestamp; +}; + +/*! + * Use to send to peer list of grps + * held by server peer + */ +class RsNxsSyncGrpItem: public RsNxsItem +{ + +public: + + static const uint8_t FLAG_REQUEST; + static const uint8_t FLAG_RESPONSE; + static const uint8_t FLAG_USE_SYNC_HASH; + + RsNxsSyncGrpItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM) { clear(); return ; } + virtual ~RsNxsSyncGrpItem() { return; } + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + + uint8_t flag; // request or response + + uint32_t publishTs; // to compare to Ts of receiving peer's grp of same id + + /// grpId of grp held by sending peer + RsGxsGroupId grpId; + RsGxsId authorId; + +}; + +/*! + * Use to send to peer list of grps + * held by server peer + */ +class RsNxsSessionKeyItem : public RsNxsItem +{ + +public: + + RsNxsSessionKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM) { clear(); } + virtual ~RsNxsSessionKeyItem() {} + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + /// Session key encrypted for the whole group + /// + uint8_t iv[EVP_MAX_IV_LENGTH] ; // initialisation vector + std::map encrypted_session_keys; // encrypted session keys +}; +/*! + * Use to send to peer list of grps + * held by server peer + */ +class RsNxsEncryptedDataItem : public RsNxsItem +{ + +public: + + RsNxsEncryptedDataItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM),encrypted_data(servtype) + { + encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ; + clear(); + } + virtual ~RsNxsEncryptedDataItem() {} + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + /// grpId of grp held by sending peer + /// + RsTlvBinaryData encrypted_data ; +}; + + +/*! + * Contains serialised group items + * Each item corresponds to a group which needs to be + * deserialised + */ +class RsNxsGrp : public RsNxsItem +{ + +public: + + RsNxsGrp(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP_ITEM), grp(servtype), meta(servtype), + metaData(NULL) { clear(); + //std::cout << "\nGrp refcount++ : " << ++refcount << std::endl; + return; } + virtual ~RsNxsGrp() { if(metaData) delete metaData; + //std::cout << "\nGrp refcount-- : " << --refcount << std::endl; + } + + RsNxsGrp* clone() const; + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + RsGxsGroupId grpId; /// group Id, needed to complete version Id (ncvi) + static int refcount; + RsTlvBinaryData grp; /// actual group data + uint8_t pos; /// used for splitting up grp + uint8_t count; /// number of split up messages + + /*! + * This should contains all data + * which is not specific to the Gxs service data + */ + RsTlvBinaryData meta; + + // deserialised metaData, this is not serialised + RsGxsGrpMetaData* metaData; +}; + +/*! + * Use to request list of msg held by peer + * for a given group + */ +class RsNxsSyncMsgReqItem : public RsNxsItem +{ + +public: + +#ifdef UNUSED_CODE + static const uint8_t FLAG_USE_SYNC_HASH; +#endif + + RsNxsSyncMsgReqItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM) { clear(); return; } + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + RsGxsGroupId grpId; + uint8_t flag; + uint32_t createdSince; + uint32_t updateTS; // time of last update + std::string syncHash; +}; + +/*! + * Use to send list msgs for a group held by + * a peer + */ +class RsNxsSyncMsgItem : public RsNxsItem +{ +public: + + static const uint8_t FLAG_REQUEST; + static const uint8_t FLAG_RESPONSE; + static const uint8_t FLAG_USE_SYNC_HASH; + RsNxsSyncMsgItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM) { clear(); return; } + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + uint8_t flag; // response/req + RsGxsGroupId grpId; + RsGxsMessageId msgId; + RsGxsId authorId; + +}; + + +/*! + * Used to respond to a RsGrpMsgsReq + * with message items satisfying request + */ +class RsNxsMsg : public RsNxsItem +{ +public: + + RsNxsMsg(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_MSG_ITEM), meta(servtype), msg(servtype), + metaData(NULL) { + // std::cout << "\nrefcount++ : " << ++refcount << std::endl; + clear(); return; + } + virtual ~RsNxsMsg() + { + //std::cout << "\nrefcount-- : " << --refcount << std::endl; + if(metaData){ + //std::cout << "\ndeleted\n"; + delete metaData; + } + } + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + uint8_t pos; /// used for splitting up msg + uint8_t count; /// number of split up messages + RsGxsGroupId grpId; /// group id, forms part of version id + RsGxsMessageId msgId; /// msg id + static int refcount; + + /*! + * This should contains all the data + * which is not specific to the Gxs service data + */ + RsTlvBinaryData meta; + + /*! + * This contains Gxs specific data + * only client of API knows who to decode this + */ + RsTlvBinaryData msg; + + RsGxsMsgMetaData* metaData; + +}; + +/*! + * Used to request a search of user data + */ +class RsNxsSearchReqItem : public RsNxsItem +{ +public: + + RsNxsSearchReqItem(uint16_t servtype): RsNxsItem(servtype, RS_PKT_SUBTYPE_EXT_SEARCH_REQ), serviceSearchItem(servtype) { return; } + virtual ~RsNxsSearchReqItem() { return;} + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + virtual void clear() { return;} + virtual std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } + + uint8_t nHops; /// how many peers to jump to + uint32_t token; // search token + RsTlvBinaryData serviceSearchItem; // service aware of item class + uint32_t expiration; // expiration date +}; + + +/*! + * Used to respond to a RsGrpSearchReq + * with grpId/MsgIds that satisfy search request + */ +class RsNxsSearchResultMsgItem +{ +public: + + RsNxsSearchResultMsgItem() : context(0) { return;} + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + void clear() {} + std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } + + uint32_t token; // search token to be redeemed + RsTlvBinaryData context; // used by client service + std::string msgId; + std::string grpId; + RsTlvKeySignature idSign; + + uint32_t expiration; // expiration date +}; + +/*! + * Used to respond to a RsGrpSearchReq + * with grpId/MsgIds that satisfy search request + */ +class RsNxsSearchResultGrpItem +{ +public: + + RsNxsSearchResultGrpItem(); + + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; + + void clear() {} + std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } + + uint32_t token; // search token to be redeemed + + RsTlvBinaryData context; // used by client service + + std::string grpId; + RsTlvKeySignature adminSign; + + uint32_t expiration; // expiration date +}; + + +#ifndef UNUSED_CODE +class RsNxsDeleteMsg +{ +public: + + RsNxsDeleteMsg() { return; } + + std::string msgId; + std::string grpId; + RsTlvKeySignature deleteSign; // ( msgId + grpId + msg data ) sign //TODO: add warning not to place msgId+grpId in msg! + +}; + +class RsNxsDeleteGrp +{ +public: + + RsNxsDeleteGrp() { return;} + + std::string grpId; + RsTlvKeySignature idSign; + RsTlvKeySignature deleteSign; // (grpId + grp data) sign // TODO: add warning not to place grpId in msg +}; +#endif + + +class RsNxsSerialiser : public RsSerialType +{ +public: + + RsNxsSerialiser(uint16_t servtype) : + RsSerialType(RS_PKT_VERSION_SERVICE, servtype), SERVICE_TYPE(servtype) { return; } + + virtual ~RsNxsSerialiser() { return; } + + virtual uint32_t size(RsItem *item); + virtual bool serialise(RsItem *item, void *data, uint32_t *size); + virtual RsItem* deserialise(void *data, uint32_t *size); + +private: + RsNxsSyncGrpReqItem *deserialNxsSyncGrpReqItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */ + RsNxsSyncGrpItem *deserialNxsSyncGrpItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP_ITEM */ + RsNxsSyncMsgReqItem *deserialNxsSyncMsgReqItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_MSG */ + RsNxsSyncMsgItem *deserialNxsSyncMsgItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_MSG_ITEM */ + RsNxsGrp *deserialNxsGrpItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_NXS_GRP */ + RsNxsMsg *deserialNxsMsgItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_NXS_MSG */ + RsNxsTransacItem *deserialNxsTransacItem(void* data, uint32_t *size); /* RS_PKT_SUBTYPE_NXS_TRANS */ + RsNxsGroupPublishKeyItem *deserialNxsGroupPublishKeyItem(void* data, uint32_t *size); /* RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY */ + RsNxsSessionKeyItem *deserialNxsSessionKeyItem(void* data, uint32_t *size); /* RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM */ + RsNxsEncryptedDataItem *deserialNxsEncryptedDataItem(void* data, uint32_t *size); /* RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM */ + RsNxsSyncGrpStatsItem *deserialNxsSyncGrpStatsItem(void* data, uint32_t *size); /* RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM */ + + bool checkItemHeader(void *data, uint32_t *size, uint8_t subservice_type); + + const uint16_t SERVICE_TYPE; +}; + + +#endif // RSNXSITEMS_H diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h index cb58aa520..41dd344e5 100644 --- a/libretroshare/src/serialiser/rstlvbase.h +++ b/libretroshare/src/serialiser/rstlvbase.h @@ -176,18 +176,16 @@ const uint16_t TLV_TYPE_CERT_X509 = 0x0101; const uint16_t TLV_TYPE_CERT_OPENPGP = 0x0102; const uint16_t TLV_TYPE_KEY_EVP_PKEY = 0x0110; /* Used (Generic - Distrib) */ -const uint16_t TLV_TYPE_KEY_PRIV_RSA = 0x0111; /* not used yet */ -const uint16_t TLV_TYPE_KEY_PUB_RSA = 0x0112; /* not used yet */ +const uint16_t TLV_TYPE_KEY_PRIV_RSA = 0x0111; /* not used yet */ +const uint16_t TLV_TYPE_KEY_PUB_RSA = 0x0112; /* not used yet */ -const uint16_t TLV_TYPE_SIGN_RSA_SHA1 = 0x0120; /* Used (Distrib/Forums) */ - -const uint16_t TLV_TYPE_BIN_IMAGE = 0x0130; /* Used (Generic - Forums) */ - -const uint16_t TLV_TYPE_BIN_FILEDATA = 0x0140; /* Used - ACTIVE! */ +const uint16_t TLV_TYPE_SIGN_RSA_SHA1 = 0x0120; /* Used (Distrib/Forums) */ +const uint16_t TLV_TYPE_BIN_IMAGE = 0x0130; /* Used (Generic - Forums) */ +const uint16_t TLV_TYPE_BIN_FILEDATA = 0x0140; /* Used - ACTIVE! */ const uint16_t TLV_TYPE_BIN_SERIALISE = 0x0150; /* Used (Generic - Distrib) */ - -const uint16_t TLV_TYPE_BIN_GENERIC = 0x0160; /* Used (DSDV Data) */ +const uint16_t TLV_TYPE_BIN_GENERIC = 0x0160; /* Used (DSDV Data) */ +const uint16_t TLV_TYPE_BIN_ENCRYPTED = 0x0170; /* Encrypted data */ /**** Compound Types ****/ diff --git a/libretroshare/src/serialiser/rstlvbinary.cc b/libretroshare/src/serialiser/rstlvbinary.cc index 672f6c54b..5b601a234 100644 --- a/libretroshare/src/serialiser/rstlvbinary.cc +++ b/libretroshare/src/serialiser/rstlvbinary.cc @@ -37,10 +37,14 @@ /*!********************************** RsTlvFileBinaryData **********************************/ +RsTlvBinaryData::RsTlvBinaryData() + :tlvtype(0), bin_len(0), bin_data(NULL) +{ +} + RsTlvBinaryData::RsTlvBinaryData(uint16_t t) :tlvtype(t), bin_len(0), bin_data(NULL) { - return; } RsTlvBinaryData::RsTlvBinaryData(const RsTlvBinaryData &b) diff --git a/libretroshare/src/serialiser/rstlvbinary.h b/libretroshare/src/serialiser/rstlvbinary.h index ec3ddd3e3..addac7f46 100644 --- a/libretroshare/src/serialiser/rstlvbinary.h +++ b/libretroshare/src/serialiser/rstlvbinary.h @@ -35,25 +35,29 @@ class RsTlvBinaryData: public RsTlvItem { - public: - RsTlvBinaryData(uint16_t t); - RsTlvBinaryData(const RsTlvBinaryData& b); // as per rule of three - void operator=(const RsTlvBinaryData& b); // as per rule of three -virtual ~RsTlvBinaryData(); // as per rule of three -virtual uint32_t TlvSize() const; -virtual void TlvClear(); /*! Initialize fields to empty legal values ( "0", "", etc) */ -virtual void TlvShallowClear(); /*! Don't delete the binary data */ +public: + RsTlvBinaryData(); + RsTlvBinaryData(uint16_t t); + RsTlvBinaryData(const RsTlvBinaryData& b); // as per rule of three + void operator=(const RsTlvBinaryData& b); // as per rule of three + + virtual ~RsTlvBinaryData(); // as per rule of three + + virtual uint32_t TlvSize() const; + virtual void TlvClear(); /*! Initialize fields to empty legal values ( "0", "", etc) */ + virtual void TlvShallowClear(); /*! Don't delete the binary data */ - /// Serialise. -/*! Serialise Tlv to buffer(*data) of 'size' bytes starting at *offset */ -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; + /// Serialise. + /*! Serialise Tlv to buffer(*data) of 'size' bytes starting at *offset */ + virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -/// Deserialise. -/*! Deserialise Tlv buffer(*data) of 'size' bytes starting at *offset */ -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; /*! Error/Debug util function */ + /// Deserialise. + /*! Deserialise Tlv buffer(*data) of 'size' bytes starting at *offset */ + virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); + virtual std::ostream &print(std::ostream &out, uint16_t indent) const; /*! Error/Debug util function */ -bool setBinData(const void *data, uint32_t size); + // mallocs the necessary size, and copies data into the allocated buffer in bin_data + bool setBinData(const void *data, uint32_t size); uint16_t tlvtype; /// set/checked against TLV input uint32_t bin_len; /// size of malloc'ed data (not serialised) diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc index 017f9376d..460cdbaab 100644 --- a/libretroshare/src/services/p3gxscircles.cc +++ b/libretroshare/src/services/p3gxscircles.cc @@ -176,66 +176,72 @@ void p3GxsCircles::service_tick() void p3GxsCircles::notifyChanges(std::vector &changes) { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges()"; - std::cerr << std::endl; + std::cerr << "p3GxsCircles::notifyChanges()"; + std::cerr << std::endl; #endif - std::vector::iterator it; - for(it = changes.begin(); it != changes.end(); ++it) - { - RsGxsGroupChange *groupChange = dynamic_cast(*it); - RsGxsMsgChange *msgChange = dynamic_cast(*it); - if (msgChange && !msgChange->metaChange()) - { + std::vector::iterator it; + for(it = changes.begin(); it != changes.end(); ++it) + { + RsGxsGroupChange *groupChange = dynamic_cast(*it); + RsGxsMsgChange *msgChange = dynamic_cast(*it); + if (msgChange && !msgChange->metaChange()) + { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges() Found Message Change Notification"; - std::cerr << std::endl; + std::cerr << " Found Message Change Notification"; + std::cerr << std::endl; #endif - std::map > &msgChangeMap = msgChange->msgChangeMap; - std::map >::iterator mit; - for(mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit) - { + std::map > &msgChangeMap = msgChange->msgChangeMap; + std::map >::iterator mit; + for(mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit) + { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges() Msgs for Group: " << mit->first; - std::cerr << std::endl; + std::cerr << " Msgs for Group: " << mit->first; + std::cerr << std::endl; #endif - } - } + } + } - /* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */ - if (groupChange && !groupChange->metaChange()) - { + /* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */ + if (groupChange && !groupChange->metaChange()) + { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges() Found Group Change Notification"; - std::cerr << std::endl; + std::cerr << " Found Group Change Notification"; + std::cerr << std::endl; #endif - std::list &groupList = groupChange->mGrpIdList; - std::list::iterator git; - for(git = groupList.begin(); git != groupList.end(); ++git) - { + std::list &groupList = groupChange->mGrpIdList; + std::list::iterator git; + for(git = groupList.begin(); git != groupList.end(); ++git) + { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges() Incoming Group: " << *git; - std::cerr << std::endl; + std::cerr << " Incoming Group: " << *git << ". Forcing cache load." << std::endl; #endif - // for new circles we need to add them to the list. - // we don't know the type of this circle here - // original behavior was to add all ids to the external ids list - addCircleIdToList(RsGxsCircleId(*git), 0); - - // reset the cached circle data for this id - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - mCircleCache.erase(RsGxsCircleId(*git)); - } - } - } - } - RsGxsIfaceHelper::receiveChanges(changes); + // for new circles we need to add them to the list. + // we don't know the type of this circle here + // original behavior was to add all ids to the external ids list + addCircleIdToList(RsGxsCircleId(*git), 0); + // reset the cached circle data for this id + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + mCircleCache.erase(RsGxsCircleId(*git)); + } + } + } + if(groupChange) + for(std::list::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git) + { +#ifdef DEBUG_CIRCLES + std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl; +#endif + force_cache_reload(RsGxsCircleId(*git)) ; + } + } + RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements } /********************************************************************************/ @@ -263,8 +269,8 @@ bool p3GxsCircles:: getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails details.mCircleType = data.mCircleType; details.mIsExternal = data.mIsExternal; - details.mUnknownPeers = data.mUnknownPeers; - details.mAllowedPeers = data.mAllowedPeers; + details.mAllowedAnonPeers = data.mAllowedAnonPeers; + details.mAllowedSignedPeers = data.mAllowedSignedPeers; return true; } } @@ -341,16 +347,17 @@ bool p3GxsCircles::loadCircle(const RsGxsCircleId &circleId) return cache_request_load(circleId); } -int p3GxsCircles::canSend(const RsGxsCircleId &circleId, const RsPgpId &id) +int p3GxsCircles::canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool& should_encrypt) { RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ if (mCircleCache.is_cached(circleId)) { RsGxsCircleCache &data = mCircleCache.ref(circleId); + should_encrypt = (data.mCircleType == GXS_CIRCLE_TYPE_EXTERNAL); + if (data.isAllowedPeer(id)) - { return 1; - } + return 0; } return -1; @@ -371,7 +378,7 @@ int p3GxsCircles::canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) return -1; } -bool p3GxsCircles::recipients(const RsGxsCircleId &circleId, std::list &friendlist) +bool p3GxsCircles::recipients(const RsGxsCircleId &circleId, std::list& friendlist) { RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ if (mCircleCache.is_cached(circleId)) @@ -383,6 +390,34 @@ bool p3GxsCircles::recipients(const RsGxsCircleId &circleId, std::list return false; } +bool p3GxsCircles::isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) +{ + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + if (mCircleCache.is_cached(circleId)) + { + const RsGxsCircleCache &data = mCircleCache.ref(circleId); + return data.isAllowedPeer(id); + } + return false; +} + +bool p3GxsCircles::recipients(const RsGxsCircleId& circleId, std::list& gxs_ids) +{ + RsGxsCircleDetails details ; + + if(!getCircleDetails(circleId, details)) + return false; + + for(std::set::const_iterator it(details.mAllowedAnonPeers.begin());it!=details.mAllowedAnonPeers.end();++it) + gxs_ids.push_back(*it) ; + + for(std::map >::const_iterator it(details.mAllowedSignedPeers.begin());it!=details.mAllowedSignedPeers.end();++it) + for(std::set::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) + gxs_ids.push_back(*it2) ; + + return true; +} + /********************************************************************************/ /******************* Get/Set Data ******************************************/ /********************************************************************************/ @@ -495,6 +530,7 @@ RsGxsCircleCache::RsGxsCircleCache() mIsExternal = true; mUpdateTime = 0; mGroupStatus = 0; + mGroupSubscribeFlags = 0; return; } @@ -506,11 +542,12 @@ bool RsGxsCircleCache::loadBaseCircle(const RsGxsCircleGroup &circle) mCircleId = RsGxsCircleId(circle.mMeta.mGroupId); mCircleName = circle.mMeta.mGroupName; mUpdateTime = time(NULL); - mProcessedCircles.insert(mCircleId); +// mProcessedCircles.insert(mCircleId); mCircleType = circle.mMeta.mCircleType; mIsExternal = (mCircleType != GXS_CIRCLE_TYPE_LOCAL); mGroupStatus = circle.mMeta.mGroupStatus; + mGroupSubscribeFlags = circle.mMeta.mSubscribeFlags; #ifdef DEBUG_CIRCLES std::cerr << "RsGxsCircleCache::loadBaseCircle(" << mCircleId << ")"; @@ -534,20 +571,35 @@ bool RsGxsCircleCache::loadSubCircle(const RsGxsCircleCache &subcircle) return true; } -bool RsGxsCircleCache::getAllowedPeersList(std::list &friendlist) +bool RsGxsCircleCache::getAllowedPeersList(std::list &friendlist) const { - std::map >::iterator it; - for(it = mAllowedPeers.begin(); it != mAllowedPeers.end(); ++it) + std::map >::const_iterator it; + for(it = mAllowedSignedPeers.begin(); it != mAllowedSignedPeers.end(); ++it) { friendlist.push_back(it->first); } return true; } -bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) +bool RsGxsCircleCache::isAllowedPeer(const RsGxsId &id) const { - std::map >::iterator it = mAllowedPeers.find(id); - if (it != mAllowedPeers.end()) + if(mUnprocessedPeers.find(id) != mUnprocessedPeers.end()) + return true ; + + if(mAllowedAnonPeers.find(id) != mAllowedAnonPeers.end()) + return true ; + + for(std::map >::const_iterator it = mAllowedSignedPeers.begin();it!=mAllowedSignedPeers.end();++it) + if(it->second.find(id) != it->second.end()) + return true ; + + return false ; +} + +bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) const +{ + std::map >::const_iterator it = mAllowedSignedPeers.find(id); + if (it != mAllowedSignedPeers.end()) { return true; } @@ -557,8 +609,7 @@ bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) bool RsGxsCircleCache::addAllowedPeer(const RsPgpId &pgpId, const RsGxsId &gxsId) { /* created if doesn't exist */ - std::list &gxsList = mAllowedPeers[pgpId]; - gxsList.push_back(gxsId); + mAllowedSignedPeers[pgpId].insert(gxsId); return true; } @@ -566,7 +617,7 @@ bool RsGxsCircleCache::addAllowedPeer(const RsPgpId &pgpId, const RsGxsId &gxsId bool RsGxsCircleCache::addLocalFriend(const RsPgpId &pgpId) { /* empty list as no GxsID associated */ - std::list &gxsList = mAllowedPeers[pgpId]; + mAllowedSignedPeers.insert(std::make_pair(pgpId,std::set())); return true; } @@ -753,6 +804,33 @@ bool p3GxsCircles::cachetest_handlerequest(uint32_t token) /************************************************************************************/ // Complicated deal of loading Circles. +bool p3GxsCircles::force_cache_reload(const RsGxsCircleId& id) +{ +#ifdef DEBUG_CIRCLES + std::cerr << "p3GxsCircles::force_cache_reload(): Forcing cache reload of Circle ID " << id << std::endl; +#endif + + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + +#ifdef DEBUG_CIRCLES + std::cerr << " clearing from existing cache entries..." << std::endl; +#endif + + std::map::iterator it = mLoadingCache.find(id); + if (it != mLoadingCache.end()) + { + mLoadingCache.erase(it) ; +#ifdef DEBUG_CIRCLES + std::cerr << " removed item from currently loading cache entries..." << std::endl; +#endif + } + mCircleCache.erase(id) ; + } + cache_request_load(id) ; + + return true ; +} bool p3GxsCircles::cache_request_load(const RsGxsCircleId &id) { @@ -946,7 +1024,7 @@ bool p3GxsCircles::cache_load_for_token(uint32_t token) std::cerr << "p3GxsCircles::cache_load_for_token() Is Unknown -> UnknownPeer: " << *pit; std::cerr << std::endl; #endif - cache.mUnknownPeers.insert(*pit); + cache.mAllowedAnonPeers.insert(*pit); } } else @@ -1104,9 +1182,7 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) RsGxsCircleCache &cache = it->second; /* try reload Ids */ - std::set::const_iterator pit; - for(pit = cache.mUnprocessedPeers.begin(); - pit != cache.mUnprocessedPeers.end(); ++pit) + for(std::set::const_iterator pit = cache.mUnprocessedPeers.begin(); pit != cache.mUnprocessedPeers.end(); ++pit) { /* check cache */ if (mIdentities->haveKey(*pit)) @@ -1127,7 +1203,7 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) } else { - cache.mUnknownPeers.insert(*pit); + cache.mAllowedAnonPeers.insert(*pit); #ifdef DEBUG_CIRCLES std::cerr << "p3GxsCircles::cache_reloadids() UnknownPeer: "; @@ -1157,8 +1233,10 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) cache.mUnprocessedPeers.clear(); // If sub-circles are complete too. +#ifdef SUBSCIRCLES if (cache.mUnprocessedCircles.empty()) { +#endif #ifdef DEBUG_CIRCLES std::cerr << "p3GxsCircles::cache_reloadids() Adding to cache Id: "; std::cerr << circleId; @@ -1173,6 +1251,7 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) /* remove from loading queue */ mLoadingCache.erase(it); +#ifdef SUBSCIRCLES } else { @@ -1180,6 +1259,7 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) std::cerr << circleId; std::cerr << std::endl; } +#endif return true; } @@ -1189,17 +1269,14 @@ bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) bool p3GxsCircles::checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache) { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() : "; - std::cerr << cache.mCircleId; - std::cerr << std::endl; + std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() : "<< cache.mCircleId << std::endl; #endif /* if processed already - ignore */ if (!(cache.mGroupStatus & GXS_SERV::GXS_GRP_STATUS_UNPROCESSED)) { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() : Already Processed"; - std::cerr << std::endl; + std::cerr << " Already Processed" << std::endl; #endif return false; @@ -1209,50 +1286,90 @@ bool p3GxsCircles::checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache) if (!cache.mIsExternal) { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() : Personal Circle"; - std::cerr << std::endl; + std::cerr << " Personal Circle. Nothing to do." << std::endl; #endif return false; } /* if we appear in the group - then autosubscribe, and mark as processed */ + const RsPgpId& ownId = mPgpUtils->getPGPOwnId(); - std::map >::iterator it = cache.mAllowedPeers.find(ownId); - if (it != cache.mAllowedPeers.end()) + + std::map >::iterator it = cache.mAllowedSignedPeers.find(ownId); + bool am_I_allowed = it != cache.mAllowedSignedPeers.end() ; + + if(!am_I_allowed) { -#ifdef DEBUG_CIRCLES - /* we are part of this group - subscribe, clear unprocessed flag */ - std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() Found OwnId -> AutoSubscribe!"; - std::cerr << std::endl; -#endif + // also check if there's an unknown anonymous identity in the list that would belong to us + std::list own_gxs_ids ; + rsIdentity->getOwnIds(own_gxs_ids) ; - + for(std::list::const_iterator it(own_gxs_ids.begin());it!=own_gxs_ids.end();++it) + if(cache.mAllowedAnonPeers.end() != cache.mAllowedAnonPeers.find(*it)) + { + am_I_allowed = true ; +#ifdef DEBUG_CIRCLES + std::cerr << " found own GxsId " << *it << " as being in the circle" << std::endl; +#endif + break ; + } + } +#ifdef DEBUG_CIRCLES + else + std::cerr << " found own PGP id as signed to one of the circle's GxsIds" << std::endl; +#endif + + if(am_I_allowed) + { uint32_t token, token2; - RsGenExchange::subscribeToGroup(token, RsGxsGroupId(cache.mCircleId.toStdString()), true); - RsGenExchange::setGroupStatusFlags(token2, RsGxsGroupId(cache.mCircleId.toStdString()), 0, GXS_SERV::GXS_GRP_STATUS_UNPROCESSED); + + if(! (cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)) + { +#ifdef DEBUG_CIRCLES + /* we are part of this group - subscribe, clear unprocessed flag */ + std::cerr << " I'm allowed in this circle => AutoSubscribing!" << std::endl; +#endif + RsGenExchange::subscribeToGroup(token, RsGxsGroupId(cache.mCircleId), true); + } +#ifdef DEBUG_CIRCLES + else + std::cerr << " I'm allowed in this circle, and already subscribed." << std::endl; +#endif + + RsGenExchange::setGroupStatusFlags(token2, RsGxsGroupId(cache.mCircleId), 0, GXS_SERV::GXS_GRP_STATUS_UNPROCESSED); + cache.mGroupStatus ^= GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; + return true; } - else if (cache.mUnknownPeers.empty()) + else if (cache.mUnprocessedPeers.empty()) { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() Know All Peers -> Processed"; - std::cerr << std::endl; -#endif - /* we know all the peers - we are not part - we can flag as PROCESSED. */ - uint32_t token; + uint32_t token,token2; RsGenExchange::setGroupStatusFlags(token, RsGxsGroupId(cache.mCircleId.toStdString()), 0, GXS_SERV::GXS_GRP_STATUS_UNPROCESSED); + + if(cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { + RsGenExchange::subscribeToGroup(token2, RsGxsGroupId(cache.mCircleId), false); +#ifdef DEBUG_CIRCLES + std::cerr << " Not part of the group! Let's unsubscribe this circle of unfriendly Napoleons!" << std::endl; +#endif + } +#ifdef DEBUG_CIRCLES + else + std::cerr << " Not part of the group, and not subscribed either." << std::endl; +#endif + cache.mGroupStatus ^= GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; + + return true ; } else { #ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkCircleCacheForAutoSubscribe() Leaving Unprocessed"; - std::cerr << std::endl; + std::cerr << " Leaving Unprocessed" << std::endl; #endif - // Don't clear UNPROCESSED - as we might not know all the peers. // TODO - work out when we flag as PROCESSED. } diff --git a/libretroshare/src/services/p3gxscircles.h b/libretroshare/src/services/p3gxscircles.h index ca40af234..2ad9934b6 100644 --- a/libretroshare/src/services/p3gxscircles.h +++ b/libretroshare/src/services/p3gxscircles.h @@ -132,8 +132,9 @@ class RsGxsCircleCache bool loadBaseCircle(const RsGxsCircleGroup &circle); bool loadSubCircle(const RsGxsCircleCache &subcircle); - bool getAllowedPeersList(std::list &friendlist); - bool isAllowedPeer(const RsPgpId &id); + bool getAllowedPeersList(std::list &friendlist) const; + bool isAllowedPeer(const RsPgpId &id) const; + bool isAllowedPeer(const RsGxsId &id) const; bool addAllowedPeer(const RsPgpId &pgpid, const RsGxsId &gxsId); bool addLocalFriend(const RsPgpId &pgpid); @@ -144,14 +145,17 @@ class RsGxsCircleCache bool mIsExternal; uint32_t mGroupStatus; + uint32_t mGroupSubscribeFlags; time_t mUpdateTime; +#ifdef SUBSCIRCLES std::set mUnprocessedCircles; - std::set mUnprocessedPeers; - std::set mProcessedCircles; - std::set mUnknownPeers; - std::map > mAllowedPeers; +#endif + std::set mUnprocessedPeers; + + std::set mAllowedAnonPeers; + std::map > mAllowedSignedPeers; }; @@ -175,9 +179,11 @@ virtual RsServiceInfo getServiceInfo(); virtual bool isLoaded(const RsGxsCircleId &circleId); virtual bool loadCircle(const RsGxsCircleId &circleId); - virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id); + virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool &should_encrypt); virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id); - virtual bool recipients(const RsGxsCircleId &circleId, std::list &friendlist); + virtual bool recipients(const RsGxsCircleId &circleId, std::list &friendlist) ; + virtual bool recipients(const RsGxsCircleId &circleId, std::list &gxs_ids) ; + virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) ; virtual bool getGroupData(const uint32_t &token, std::vector &groups); @@ -219,6 +225,7 @@ virtual RsServiceInfo getServiceInfo(); bool cache_request_load(const RsGxsCircleId &id); bool cache_start_load(); + bool force_cache_reload(const RsGxsCircleId& id); bool cache_load_for_token(uint32_t token); bool cache_reloadids(const RsGxsCircleId &circleId); diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.cpp b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp index a212876b8..6e2a7766b 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.cpp +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp @@ -36,6 +36,7 @@ #define CIRCLEGROUP_CIRCLE_COL_GROUPNAME 0 #define CIRCLEGROUP_CIRCLE_COL_GROUPID 1 +#define CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS 2 #define CIRCLEGROUP_FRIEND_COL_NAME 0 #define CIRCLEGROUP_FRIEND_COL_ID 1 @@ -62,8 +63,8 @@ CirclesDialog::CirclesDialog(QWidget *parent) mStateHelper->addWidget(CIRCLESDIALOG_GROUPMETA, ui.pushButton_editCircle); mStateHelper->addWidget(CIRCLESDIALOG_GROUPMETA, ui.treeWidget_membership, UISTATE_ACTIVE_ENABLED); - mStateHelper->addWidget(CIRCLESDIALOG_GROUPMETA, ui.treeWidget_friends, UISTATE_ACTIVE_ENABLED); - mStateHelper->addWidget(CIRCLESDIALOG_GROUPMETA, ui.treeWidget_category, UISTATE_ACTIVE_ENABLED); +// mStateHelper->addWidget(CIRCLESDIALOG_GROUPMETA, ui.treeWidget_friends, UISTATE_ACTIVE_ENABLED); +// mStateHelper->addWidget(CIRCLESDIALOG_GROUPMETA, ui.treeWidget_category, UISTATE_ACTIVE_ENABLED); mStateHelper->setWidgetEnabled(ui.pushButton_editCircle, false); @@ -74,8 +75,8 @@ CirclesDialog::CirclesDialog(QWidget *parent) connect(ui.todoPushButton, SIGNAL(clicked()), this, SLOT(todo())); connect(ui.treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected())); - connect(ui.treeWidget_friends, SIGNAL(itemSelectionChanged()), this, SLOT(friend_selected())); - connect(ui.treeWidget_category, SIGNAL(itemSelectionChanged()), this, SLOT(category_selected())); +// connect(ui.treeWidget_friends, SIGNAL(itemSelectionChanged()), this, SLOT(friend_selected())); +// connect(ui.treeWidget_category, SIGNAL(itemSelectionChanged()), this, SLOT(category_selected())); /* Setup TokenQueue */ mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); @@ -84,8 +85,8 @@ CirclesDialog::CirclesDialog(QWidget *parent) QHeaderView * membership_header = ui.treeWidget_membership->header () ; membership_header->resizeSection ( CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 200 ); - QHeaderView * friends_header = ui.treeWidget_friends->header () ; - friends_header->resizeSection ( CIRCLEGROUP_FRIEND_COL_NAME, 200 ); +// QHeaderView * friends_header = ui.treeWidget_friends->header () ; +// friends_header->resizeSection ( CIRCLEGROUP_FRIEND_COL_NAME, 200 ); } @@ -135,8 +136,10 @@ void CirclesDialog::editExistingCircle() QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID); RsGxsGroupId id ( coltext.toStdString()); + uint32_t subscribe_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt(); + CreateCircleDialog dlg; - dlg.editExistingId(id); + dlg.editExistingId(id,true,!!(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) ; dlg.exec(); } @@ -154,6 +157,7 @@ void CirclesDialog::reloadAll() rsPeers->getGPGAcceptedList(friend_pgpIds); rsPeers->getGPGAllList(all_pgpIds); +#ifdef SUSPENDED_CODE /* clear tree */ ui.treeWidget_friends->clear(); @@ -198,6 +202,7 @@ void CirclesDialog::reloadAll() fofItem->addChild(item); } } +#endif } void set_item_background(QTreeWidgetItem *item, uint32_t type) @@ -310,7 +315,7 @@ void mark_circle_item(QTreeWidgetItem *item, const std::set &names) std::set::iterator it; for(it = names.begin(); it != names.end(); ++it) { - if (details.mAllowedPeers.end() != details.mAllowedPeers.find(*it)) + if (details.mAllowedSignedPeers.end() != details.mAllowedSignedPeers.find(*it)) { set_item_background(item, GREEN_BACKGROUND); std::cerr << "CirclesDialog mark_circle_item: found match: " << id; @@ -383,8 +388,7 @@ void CirclesDialog::circle_selected() { /* now mark all the members */ std::set members; - std::map >::iterator it; - for(it = details.mAllowedPeers.begin(); it != details.mAllowedPeers.end(); ++it) + for( std::map >::iterator it = details.mAllowedSignedPeers.begin(); it != details.mAllowedSignedPeers.end(); ++it) { members.insert(it->first); std::cerr << "Circle member: " << it->first; diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.ui b/retroshare-gui/src/gui/Circles/CirclesDialog.ui index 10ec16efd..762d507f9 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.ui +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.ui @@ -6,7 +6,7 @@ 0 0 - 746 + 920 568 @@ -14,16 +14,7 @@ - - 0 - - - 0 - - - 0 - - + 0 @@ -35,16 +26,7 @@ QFrame::Sunken - - 2 - - - 2 - - - 2 - - + 2 diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp b/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp index c12190584..2fc458752 100644 --- a/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp @@ -22,9 +22,11 @@ */ #include +#include #include #include "gui/Circles/CreateCircleDialog.h" +#include "gui/gxs/GxsIdDetails.h" #include #include @@ -33,6 +35,8 @@ #include +//#define DEBUG_CREATE_CIRCLE_DIALOG 1 + #define CREATECIRCLEDIALOG_CIRCLEINFO 2 #define CREATECIRCLEDIALOG_IDINFO 3 @@ -50,10 +54,6 @@ CreateCircleDialog::CreateCircleDialog() /* Setup Queue */ mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); mIdQueue = new TokenQueue(rsIdentity->getTokenService(), this); - - //QString text = pId.empty() ? tr("Start New Thread") : tr("Post Forum Message"); - //setWindowTitle(text); - //Settings->loadWidgetInformation(this); ui.headerFrame->setHeaderImage(QPixmap(":/images/circles/circles_64.png")); @@ -67,6 +67,9 @@ CreateCircleDialog::CreateCircleDialog() connect(ui.treeWidget_membership, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectedMember(QTreeWidgetItem*, QTreeWidgetItem*))); connect(ui.treeWidget_IdList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectedId(QTreeWidgetItem*, QTreeWidgetItem*))); + connect(ui.treeWidget_IdList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(IdListCustomPopupMenu(QPoint))); + connect(ui.treeWidget_membership, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(MembershipListCustomPopupMenu(QPoint))); + connect(ui.IdFilter, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); //connect(ui.toolButton_NewId, SIGNAL(clicked()), this, SLOT(createNewGxsId())); @@ -82,15 +85,21 @@ CreateCircleDialog::CreateCircleDialog() ui.addButton->setEnabled(false); ui.radioButton_ListAll->setChecked(true); - QObject::connect(ui.radioButton_ListAll, SIGNAL(toggled(bool)), this, SLOT(updateCircleGUI())) ; - QObject::connect(ui.radioButton_ListAllPGP, SIGNAL(toggled(bool)), this, SLOT(updateCircleGUI())) ; - QObject::connect(ui.radioButton_ListKnownPGP, SIGNAL(toggled(bool)), this, SLOT(updateCircleGUI())) ; + QObject::connect(ui.radioButton_ListAll, SIGNAL(toggled(bool)), this, SLOT(idTypeChanged())) ; + QObject::connect(ui.radioButton_ListAllPGP, SIGNAL(toggled(bool)), this, SLOT(idTypeChanged())) ; + QObject::connect(ui.radioButton_ListKnownPGP, SIGNAL(toggled(bool)), this, SLOT(idTypeChanged())) ; + QObject::connect(ui.radioButton_Public, SIGNAL(toggled(bool)), this, SLOT(updateCircleType(bool))) ; + QObject::connect(ui.radioButton_Self, SIGNAL(toggled(bool)), this, SLOT(updateCircleType(bool))) ; + QObject::connect(ui.radioButton_Restricted, SIGNAL(toggled(bool)), this, SLOT(updateCircleType(bool))) ; + + ui.radioButton_Public->setChecked(true) ; + mIsExistingCircle = false; mIsExternalCircle = true; mClearList = true; - ui.idChooser->loadIds(0,RsGxsId()); + //ui.idChooser->loadIds(0,RsGxsId()); ui.circleComboBox->loadCircles(GXS_CIRCLE_CHOOSER_EXTERNAL, RsGxsCircleId()); } @@ -100,16 +109,49 @@ CreateCircleDialog::~CreateCircleDialog() delete(mIdQueue); } -void CreateCircleDialog::editExistingId(const RsGxsGroupId &circleId, const bool &clearList /*= true*/) +void CreateCircleDialog::editExistingId(const RsGxsGroupId &circleId, const bool &clearList /*= true*/,bool readonly) { /* load this circle */ mIsExistingCircle = true; + mReadOnly=readonly; mClearList = clearList; - requestCircle(circleId); + if(readonly) + ui.headerFrame->setHeaderText(tr("Circle Details")); + else ui.headerFrame->setHeaderText(tr("Edit Circle")); + ui.radioButton_Public->setEnabled(!readonly) ; + ui.radioButton_Self->setEnabled(!readonly) ; + ui.radioButton_Restricted->setEnabled(!readonly) ; + ui.circleName->setReadOnly(readonly) ; + + if(readonly) + { + ui.circleAdminLabel->setVisible(true) ; + ui.idChooser->setVisible(false) ; + } + else + { + ui.circleAdminLabel->setVisible(false) ; + ui.idChooser->setVisible(true) ; + } + + ui.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Update")); + + ui.addButton->setEnabled(!readonly) ; + ui.removeButton->setEnabled(!readonly) ; + + if(readonly) + { + ui.buttonBox->setStandardButtons(QDialogButtonBox::Cancel); + ui.buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close")); + ui.peersSelection_GB->hide() ; + ui.addButton->hide() ; + ui.removeButton->hide() ; + } + requestCircle(circleId); } @@ -117,36 +159,61 @@ void CreateCircleDialog::editNewId(bool isExternal) { /* load this circle */ mIsExistingCircle = false; + mReadOnly = false ; /* setup personal or external circle */ if (isExternal) { setupForExternalCircle(); - ui.headerFrame->setHeaderText(tr("Create New External Circle")); + ui.headerFrame->setHeaderText(tr("Create New Circle")); + ui.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create")); } else { setupForPersonalCircle(); - ui.headerFrame->setHeaderText(tr("Create New Personal Circle")); + ui.headerFrame->setHeaderText(tr("Create New Circle")); } /* enable stuff that might be locked */ } +void CreateCircleDialog::updateCircleType(bool b) +{ + if(!b) + return ; // no need to change when b<-false + + //if(ui.radioButton_Self->isChecked()) + // setupForPersonalCircle() ; + //else + setupForExternalCircle() ; + + if(ui.radioButton_Restricted->isChecked()) + { + ui.circleComboBox->setEnabled(true) ; + ui.circleComboBox->show() ; + } + else + { + ui.circleComboBox->setEnabled(false) ; + ui.circleComboBox->hide() ; + } +} + void CreateCircleDialog::setupForPersonalCircle() { mIsExternalCircle = false; /* hide distribution line */ - ui.groupBox_title->setTitle(tr("Personal Circle Details")); + ui.groupBox_title->setTitle(tr("Circle Details")); ui.frame_PgpTypes->hide(); - ui.frame_Distribution->hide(); + //ui.frame_Distribution->hide(); ui.idChooserLabel->hide(); + ui.circleAdminLabel->hide(); ui.idChooser->hide(); //ui.toolButton_NewId->hide(); - getPgpIdentities(); + //getPgpIdentities(); } void CreateCircleDialog::setupForExternalCircle() @@ -154,10 +221,12 @@ void CreateCircleDialog::setupForExternalCircle() mIsExternalCircle = true; /* show distribution line */ - ui.groupBox_title->setTitle(tr("External Circle Details")); + ui.groupBox_title->setTitle(tr("Circle Details")); + ui.frame_PgpTypes->show(); ui.frame_Distribution->show(); ui.idChooserLabel->show(); + ui.circleAdminLabel->show(); ui.idChooser->show(); //ui.toolButton_NewId->show(); @@ -210,8 +279,10 @@ void CreateCircleDialog::addMember(const QString& keyId, const QString& idtype, for(int i = 0; i < count; ++i){ QTreeWidgetItem *item = tree->topLevelItem(i); if (keyId == item->text(RSCIRCLEID_COL_KEYID)) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::addMember() Already is a Member: " << keyId.toStdString(); std::cerr << std::endl; +#endif return; }//if (keyId == item->text(RSCIRCLEID_COL_KEYID)) }//for(int i = 0; i < count; ++i) @@ -220,6 +291,7 @@ void CreateCircleDialog::addMember(const QString& keyId, const QString& idtype, member->setText(RSCIRCLEID_COL_NICKNAME, nickname); member->setText(RSCIRCLEID_COL_KEYID, keyId); member->setText(RSCIRCLEID_COL_IDTYPE, idtype); + //member->setIcon(RSCIRCLEID_COL_NICKNAME, pixmap); tree->addTopLevelItem(member); } @@ -228,8 +300,8 @@ void CreateCircleDialog::addMember(const QString& keyId, const QString& idtype, void CreateCircleDialog::addCircle(const RsGxsCircleDetails &cirDetails) { typedef std::set::iterator itUnknownPeers; - for (itUnknownPeers it = cirDetails.mUnknownPeers.begin() - ; it != cirDetails.mUnknownPeers.end() + for (itUnknownPeers it = cirDetails.mAllowedAnonPeers.begin() + ; it != cirDetails.mAllowedAnonPeers.end() ; ++it) { RsGxsId gxs_id = *it; RsIdentityDetails gxs_details ; @@ -244,10 +316,9 @@ void CreateCircleDialog::addCircle(const RsGxsCircleDetails &cirDetails) }//if(!gxs_id.isNull() && rsIdentity->getIdDetails(gxs_id,gxs_details)) }//for (itUnknownPeers it = cirDetails.mUnknownPeers.begin() - typedef std::map >::const_iterator itAllowedPeers; - for (itAllowedPeers it = cirDetails.mAllowedPeers.begin() - ; it != cirDetails.mAllowedPeers.end() - ; ++it ) { + typedef std::map >::const_iterator itAllowedPeers; + for (itAllowedPeers it = cirDetails.mAllowedSignedPeers.begin() ; it != cirDetails.mAllowedSignedPeers.end() ; ++it ) + { RsPgpId gpg_id = it->first; RsPeerDetails details ; if(!gpg_id.isNull() && rsPeers->getGPGDetails(gpg_id,details)) { @@ -273,167 +344,259 @@ void CreateCircleDialog::removeMember() void CreateCircleDialog::createCircle() { - std::cerr << "CreateCircleDialog::createCircle()"; - std::cerr << std::endl; + if(mReadOnly) + { + close() ; + return ; + } + +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle()"; + std::cerr << std::endl; +#endif - QString name = ui.circleName->text(); + QString name = ui.circleName->text(); - if(name.isEmpty()) { - /* error message */ - QMessageBox::warning(this, tr("RetroShare"),tr("Please set a name for your Circle"), QMessageBox::Ok, QMessageBox::Ok); + if(name.isEmpty()) { + /* error message */ + QMessageBox::warning(this, tr("RetroShare"),tr("Please set a name for your Circle"), QMessageBox::Ok, QMessageBox::Ok); - return; //Don't add a empty Subject!! - }//if(name.isEmpty()) + return; //Don't add a empty Subject!! + }//if(name.isEmpty()) - RsGxsCircleGroup circle; + RsGxsCircleGroup circle = mCircleGroup; // init with loaded group - circle.mMeta.mGroupName = std::string(name.toUtf8()); + circle.mMeta.mGroupName = std::string(name.toUtf8()); + circle.mInvitedMembers.clear() ; + circle.mLocalFriends.clear() ; - RsGxsId authorId; - switch (ui.idChooser->getChosenId(authorId)) { - case GxsIdChooser::KnowId: - case GxsIdChooser::UnKnowId: - circle.mMeta.mAuthorId = authorId; - std::cerr << "CreateCircleDialog::createCircle() AuthorId: " << authorId; - std::cerr << std::endl; + RsGxsId authorId; + switch (ui.idChooser->getChosenId(authorId)) + { + case GxsIdChooser::KnowId: + case GxsIdChooser::UnKnowId: + circle.mMeta.mAuthorId = authorId; +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() AuthorId: " << authorId; + std::cerr << std::endl; +#endif - break; - case GxsIdChooser::NoId: - case GxsIdChooser::None: - default: - std::cerr << "CreateCircleDialog::createCircle() No AuthorId Chosen!"; - std::cerr << std::endl; - }//switch (ui.idChooser->getChosenId(authorId)) + break; + case GxsIdChooser::NoId: + case GxsIdChooser::None: + default: ; +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() No AuthorId Chosen!"; + std::cerr << std::endl; +#endif + } - /* copy Ids from GUI */ - QTreeWidget *tree = ui.treeWidget_membership; - int count = tree->topLevelItemCount(); - for(int i = 0; i < count; ++i) { - QTreeWidgetItem *item = tree->topLevelItem(i); - QString keyId = item->text(RSCIRCLEID_COL_KEYID); + /* copy Ids from GUI */ + QTreeWidget *tree = ui.treeWidget_membership; + int count = tree->topLevelItemCount(); + for(int i = 0; i < count; ++i) + { + QTreeWidgetItem *item = tree->topLevelItem(i); + QString keyId = item->text(RSCIRCLEID_COL_KEYID); - /* insert into circle */ - if (mIsExternalCircle) { - circle.mInvitedMembers.push_back(RsGxsId(keyId.toStdString())); - std::cerr << "CreateCircleDialog::createCircle() Inserting Member: " << keyId.toStdString(); - std::cerr << std::endl; - } else {//if (mIsExternalCircle) - circle.mLocalFriends.push_back(RsPgpId(keyId.toStdString())); - std::cerr << "CreateCircleDialog::createCircle() Inserting Friend: " << keyId.toStdString(); - std::cerr << std::endl; - }//else (mIsExternalCircle) + /* insert into circle */ + if (mIsExternalCircle) + { + RsGxsId key_id_gxs(keyId.toStdString()) ; - }//for(int i = 0; i < count; ++i) + if(key_id_gxs.isNull()) + { + std::cerr << "Error: Not a proper keyID: " << keyId.toStdString() << std::endl; + continue ; + } - if (mIsExistingCircle) { - std::cerr << "CreateCircleDialog::createCircle() Existing Circle TODO"; - std::cerr << std::endl; + circle.mInvitedMembers.insert(key_id_gxs) ; +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() Inserting Member: " << keyId.toStdString(); + std::cerr << std::endl; +#endif + } + else + { + RsPgpId key_id_pgp(keyId.toStdString()) ; - // cannot edit these yet. - QMessageBox::warning(this, tr("RetroShare"),tr("Cannot Edit Existing Circles Yet"), QMessageBox::Ok, QMessageBox::Ok); - return; - }//if (mIsExistingCircle) + if(key_id_pgp.isNull()) + { + std::cerr << "Error: Not a proper PGP keyID: " << keyId.toStdString() << std::endl; + continue ; + } - if (mIsExternalCircle) { - std::cerr << "CreateCircleDialog::createCircle() External Circle"; - std::cerr << std::endl; + circle.mLocalFriends.insert(key_id_pgp) ; +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() Inserting Friend: " << keyId.toStdString(); + std::cerr << std::endl; +#endif + } - // set distribution from GUI. - circle.mMeta.mCircleId.clear() ; - if (ui.radioButton_Public->isChecked()) { - std::cerr << "CreateCircleDialog::createCircle() Public Circle"; - std::cerr << std::endl; + } - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; + // if (mIsExistingCircle) + // { + // std::cerr << "CreateCircleDialog::createCircle() Existing Circle TODO"; + // std::cerr << std::endl; + // + // // cannot edit these yet. + // QMessageBox::warning(this, tr("RetroShare"),tr("Cannot Edit Existing Circles Yet"), QMessageBox::Ok, QMessageBox::Ok); + // return; + // } - } else if (ui.radioButton_Self->isChecked()) { - std::cerr << "CreateCircleDialog::createCircle() ExtSelfRef Circle"; - std::cerr << std::endl; + if (mIsExternalCircle) + { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() External Circle"; + std::cerr << std::endl; +#endif - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXT_SELF; - } else if (ui.radioButton_Restricted->isChecked()) { - std::cerr << "CreateCircleDialog::createCircle() External (Other) Circle"; - std::cerr << std::endl; + // set distribution from GUI. + circle.mMeta.mCircleId.clear() ; + if (ui.radioButton_Public->isChecked()) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() Public Circle"; + std::cerr << std::endl; +#endif - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXTERNAL; + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; - /* grab circle ID from chooser */ - RsGxsCircleId chosenId; - if (ui.circleComboBox->getChosenCircle(chosenId)) { - std::cerr << "CreateCircleDialog::createCircle() ChosenId: " << chosenId; - std::cerr << std::endl; + } else if (ui.radioButton_Self->isChecked()) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() ExtSelfRef Circle"; + std::cerr << std::endl; +#endif - circle.mMeta.mCircleId = chosenId; - } else {//if (ui.circleComboBox->getChosenCircle(chosenId)) - std::cerr << "CreateCircleDialog::createCircle() Error no Id Chosen"; - std::cerr << std::endl; + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXT_SELF; + } else if (ui.radioButton_Restricted->isChecked()) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() External (Other) Circle"; + std::cerr << std::endl; +#endif - QMessageBox::warning(this, tr("RetroShare"),tr("No Restriction Circle Selected"), QMessageBox::Ok, QMessageBox::Ok); - return; - }//else (ui.circleComboBox->getChosenCircle(chosenId)) - } else { //if (ui.radioButton_Public->isChecked()) - QMessageBox::warning(this, tr("RetroShare"),tr("No Circle Limitations Selected"), QMessageBox::Ok, QMessageBox::Ok); - return; - }//else (ui.radioButton_Public->isChecked()) - } else {//if (mIsExternalCircle) - std::cerr << "CreateCircleDialog::createCircle() Personal Circle"; - std::cerr << std::endl; + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXTERNAL; - // set personal distribution - circle.mMeta.mCircleId.clear() ; - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_LOCAL; - }//else (mIsExternalCircle) + /* grab circle ID from chooser */ + RsGxsCircleId chosenId; + if (ui.circleComboBox->getChosenCircle(chosenId)) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() ChosenId: " << chosenId; + std::cerr << std::endl; +#endif - std::cerr << "CreateCircleDialog::createCircle() : mCircleType: " << circle.mMeta.mCircleType; - std::cerr << std::endl; - std::cerr << "CreateCircleDialog::createCircle() : mCircleId: " << circle.mMeta.mCircleId; - std::cerr << std::endl; + circle.mMeta.mCircleId = chosenId; + } else {//if (ui.circleComboBox->getChosenCircle(chosenId)) +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() Error no Id Chosen"; + std::cerr << std::endl; +#endif - std::cerr << "CreateCircleDialog::createCircle() Checks and Balances Okay - calling service proper.."; - std::cerr << std::endl; + QMessageBox::warning(this, tr("RetroShare"),tr("No Restriction Circle Selected"), QMessageBox::Ok, QMessageBox::Ok); + return; + }//else (ui.circleComboBox->getChosenCircle(chosenId)) + } + else + { //if (ui.radioButton_Public->isChecked()) + QMessageBox::warning(this, tr("RetroShare"),tr("No Circle Limitations Selected"), QMessageBox::Ok, QMessageBox::Ok); + return; + }//else (ui.radioButton_Public->isChecked()) + } + else + {//if (mIsExternalCircle) +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() Personal Circle"; + std::cerr << std::endl; +#endif - uint32_t token; - rsGxsCircles->createGroup(token, circle); - close(); + // set personal distribution + circle.mMeta.mCircleId.clear() ; + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_LOCAL; + }//else (mIsExternalCircle) + + uint32_t token; + + if(mIsExistingCircle) + { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::updateCircle() : mCircleType: " << circle.mMeta.mCircleType << std::endl; + std::cerr << "CreateCircleDialog::updateCircle() : mCircleId: " << circle.mMeta.mCircleId << std::endl; + std::cerr << "CreateCircleDialog::updateCircle() : mGroupId: " << circle.mMeta.mGroupId << std::endl; + + std::cerr << "CreateCircleDialog::updateCircle() Checks and Balances Okay - calling service proper.."<< std::endl; +#endif + + rsGxsCircles->updateGroup(token, circle); + } + else + { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() : mCircleType: " << circle.mMeta.mCircleType << std::endl; + std::cerr << "CreateCircleDialog::createCircle() : mCircleId: " << circle.mMeta.mCircleId << std::endl; + + std::cerr << "CreateCircleDialog::createCircle() Checks and Balances Okay - calling service proper.."<< std::endl; +#endif + + rsGxsCircles->createGroup(token, circle); + } + + close(); } void CreateCircleDialog::updateCircleGUI() { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::updateCircleGUI()"; std::cerr << std::endl; +#endif ui.circleName->setText(QString::fromUtf8(mCircleGroup.mMeta.mGroupName.c_str())); bool isExternal = true; +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::updateCircleGUI() : CIRCLETYPE: " << mCircleGroup.mMeta.mCircleType; std::cerr << std::endl; +#endif - switch(mCircleGroup.mMeta.mCircleType) { + ui.radioButton_Public->setChecked(false); + ui.radioButton_Self->setChecked(false); + ui.radioButton_Restricted->setChecked(false); + + switch(mCircleGroup.mMeta.mCircleType) + { case GXS_CIRCLE_TYPE_LOCAL: +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::updateCircleGUI() : LOCAL CIRCLETYPE"; std::cerr << std::endl; +#endif isExternal = false; break; case GXS_CIRCLE_TYPE_PUBLIC: +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::updateCircleGUI() : PUBLIC CIRCLETYPE"; std::cerr << std::endl; +#endif ui.radioButton_Public->setChecked(true); break; case GXS_CIRCLE_TYPE_EXT_SELF: - std::cerr << "CreateCircleDialog::updateCircleGUI() : EXT_SELF CIRCLE (fallthrough)"; - std::cerr << std::endl; +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::updateCircleGUI() : EXT_SELF CIRCLE (fallthrough)"<< std::endl; +#endif case GXS_CIRCLE_TYPE_EXTERNAL: - std::cerr << "CreateCircleDialog::updateCircleGUI() : EXTERNAL CIRCLETYPE"; - std::cerr << std::endl; + +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::updateCircleGUI() : EXTERNAL CIRCLETYPE"<< std::endl; +#endif - if (mCircleGroup.mMeta.mCircleId.toStdString() == mCircleGroup.mMeta.mGroupId.toStdString()) { + if (RsGxsGroupId(mCircleGroup.mMeta.mCircleId) == mCircleGroup.mMeta.mGroupId) + ui.radioButton_Self->setChecked(true); + else ui.radioButton_Restricted->setChecked(true); - }//if (mCircleGroup.mMeta.mCircleId.toStdString() == mCircleGroup.mMeta.mGroupId.toStdString()) ui.circleComboBox->loadCircles(GXS_CIRCLE_CHOOSER_EXTERNAL, mCircleGroup.mMeta.mCircleId); @@ -442,17 +605,33 @@ void CreateCircleDialog::updateCircleGUI() default: std::cerr << "CreateCircleDialog::updateCircleGUI() INVALID mCircleType"; std::cerr << std::endl; - }//switch(mCircleGroup.mMeta.mCircleType) - - // set preferredId. - ui.idChooser->loadIds(0,mCircleGroup.mMeta.mAuthorId); + } /* setup personal or external circle */ - if (isExternal) { + if (isExternal) setupForExternalCircle(); - } else {//if (isExternal) + else setupForPersonalCircle(); - }//else (isExternal) + + // set preferredId. + std::cerr << "LoadCircle: setting author id to be " << mCircleGroup.mMeta.mAuthorId << std::endl; + //ui.idChooser->loadIds(0,mCircleGroup.mMeta.mAuthorId); + + if(mReadOnly) + { + ui.circleAdminLabel->setId(mCircleGroup.mMeta.mAuthorId) ; + ui.idChooser->setVisible(false) ; + } + else + { + std::set ids ; + ids.insert(mCircleGroup.mMeta.mAuthorId) ; + ui.idChooser->setDefaultId(mCircleGroup.mMeta.mAuthorId) ; + ui.idChooser->setChosenId(mCircleGroup.mMeta.mAuthorId) ; + ui.idChooser->setIdConstraintSet(ids) ; + ui.idChooser->setFlags(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NO_CREATE) ; + ui.circleAdminLabel->setVisible(false) ; + } } void CreateCircleDialog::requestCircle(const RsGxsGroupId &groupId) @@ -463,8 +642,10 @@ void CreateCircleDialog::requestCircle(const RsGxsGroupId &groupId) std::list groupIds; groupIds.push_back(groupId); +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::requestCircle() Requesting Group Summary(" << groupId << ")"; std::cerr << std::endl; +#endif uint32_t token; mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, CREATECIRCLEDIALOG_CIRCLEINFO); @@ -472,8 +653,10 @@ void CreateCircleDialog::requestCircle(const RsGxsGroupId &groupId) void CreateCircleDialog::loadCircle(uint32_t token) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::loadCircle(" << token << ")"; std::cerr << std::endl; +#endif QTreeWidget *tree = ui.treeWidget_membership; @@ -484,22 +667,23 @@ void CreateCircleDialog::loadCircle(uint32_t token) std::cerr << "CreateCircleDialog::loadCircle() Error getting GroupData"; std::cerr << std::endl; return; - }//if (!rsGxsCircles->getGroupData(token, groups)) + } if (groups.size() != 1) { std::cerr << "CreateCircleDialog::loadCircle() Error Group.size() != 1"; std::cerr << std::endl; return; - }//if (groups.size() != 1) + } - std::cerr << "CreateCircleDialog::loadCircle() LoadedGroup.meta: " << mCircleGroup.mMeta; - std::cerr << std::endl; - mCircleGroup = groups[0]; + +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::loadCircle() LoadedGroup.meta: " << mCircleGroup.mMeta << std::endl; +#endif updateCircleGUI(); } -void CreateCircleDialog::getPgpIdentities() +/*void CreateCircleDialog::getPgpIdentities() { std::cerr << "CreateCircleDialog::getPgpIdentities()"; std::cerr << std::endl; @@ -527,19 +711,13 @@ void CreateCircleDialog::getPgpIdentities() tree->addTopLevelItem(item); // Local Circle. - if (mIsExistingCircle) { - // check if its in the circle. - std::list::const_iterator it; - it = std::find(mCircleGroup.mLocalFriends.begin(), mCircleGroup.mLocalFriends.end(), details.gpg_id); - if (it != mCircleGroup.mLocalFriends.end()) { - /* found it */ + if (mIsExistingCircle) + if ( mCircleGroup.mLocalFriends.find(details.gpg_id) != mCircleGroup.mLocalFriends.end()) // check if its in the circle. addMember(keyId, idtype, nickname); - }//if (it != mCircleGroup.mLocalFriends.end()) - }//if (mIsExistingCircle) - }//for(it = ids.begin(); it != ids.end(); ++it) + } filterIds(); -} +}*/ void CreateCircleDialog::requestGxsIdentities() @@ -547,8 +725,10 @@ void CreateCircleDialog::requestGxsIdentities() RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::requestIdentities()"; std::cerr << std::endl; +#endif uint32_t token; mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, CREATECIRCLEDIALOG_IDINFO); @@ -556,8 +736,10 @@ void CreateCircleDialog::requestGxsIdentities() void CreateCircleDialog::loadIdentities(uint32_t token) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::loadIdentities(" << token << ")"; std::cerr << std::endl; +#endif QTreeWidget *tree = ui.treeWidget_IdList; @@ -574,68 +756,77 @@ void CreateCircleDialog::loadIdentities(uint32_t token) std::cerr << "CreateCircleDialog::insertIdentities() Error getting GroupData"; std::cerr << std::endl; return; - }//if (!rsIdentity->getGroupData(token, datavector)) + } - for(vit = datavector.begin(); vit != datavector.end(); ++vit) { - data = (*vit); + for(vit = datavector.begin(); vit != datavector.end(); ++vit) + { + data = (*vit); - /* do filtering */ - bool ok = false; - if (acceptAnonymous) { - ok = true; - } else if (acceptAllPGP) { - ok = data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID ; - } else if (data.mPgpKnown) { - ok = data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID ; - }//else if (data.mPgpKnown) + /* do filtering */ + bool ok = false; + if (acceptAnonymous) + ok = true; + else if (acceptAllPGP) + ok = data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID ; + else if (data.mPgpKnown) + ok = data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID ; - if (!ok) { - std::cerr << "CreateCircleDialog::insertIdentities() Skipping ID: " << data.mMeta.mGroupId; - std::cerr << std::endl; - continue; - }//if (!ok) + if (!ok) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::insertIdentities() Skipping ID: " << data.mMeta.mGroupId; + std::cerr << std::endl; +#endif + continue; + } - QString keyId = QString::fromStdString(data.mMeta.mGroupId.toStdString()); - QString nickname = QString::fromUtf8(data.mMeta.mGroupName.c_str()); - QString idtype = tr("Anon Id"); + QString keyId = QString::fromStdString(data.mMeta.mGroupId.toStdString()); + QString nickname = QString::fromUtf8(data.mMeta.mGroupName.c_str()); + QString idtype = tr("Anon Id"); + + QPixmap pixmap ; - if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) { - if (data.mPgpKnown) { - RsPeerDetails details; - rsPeers->getGPGDetails(data.mPgpId, details); - idtype = QString::fromUtf8(details.name.c_str()); - } else { - idtype = tr("PGP Linked Id"); - }//else (data.mPgpKnown) - }//if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + if(data.mImage.mSize == 0 || !pixmap.loadFromData(data.mImage.mData, data.mImage.mSize, "PNG")) + pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId))) ; - QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setText(RSCIRCLEID_COL_NICKNAME, nickname); - item->setText(RSCIRCLEID_COL_KEYID, keyId); - item->setText(RSCIRCLEID_COL_IDTYPE, idtype); - tree->addTopLevelItem(item); + if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + if (data.mPgpKnown) { + RsPeerDetails details; + rsPeers->getGPGDetails(data.mPgpId, details); + idtype = QString::fromUtf8(details.name.c_str()); + } + else + idtype = tr("PGP Linked Id"); + + } - // External Circle. - if (mIsExistingCircle) { - // check if its in the circle. - std::list::const_iterator it; + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(RSCIRCLEID_COL_NICKNAME, nickname); + item->setIcon(RSCIRCLEID_COL_NICKNAME, QIcon(pixmap)); + item->setText(RSCIRCLEID_COL_KEYID, keyId); + item->setText(RSCIRCLEID_COL_IDTYPE, idtype); + tree->addTopLevelItem(item); - // We use an explicit cast - // - it = std::find(mCircleGroup.mInvitedMembers.begin(), mCircleGroup.mInvitedMembers.end(), RsGxsId(data.mMeta.mGroupId)); + // External Circle. + if (mIsExistingCircle) + { + // check if its in the circle. - if (it != mCircleGroup.mInvitedMembers.end()) { - /* found it */ - addMember(keyId, idtype, nickname); - }//if (it != mCircleGroup.mInvitedMembers.end()) - }//if (mIsExistingCircle) - }//for(vit = datavector.begin(); vit != datavector.end(); ++vit) + // We use an explicit cast + // + + if ( mCircleGroup.mInvitedMembers.find(RsGxsId(data.mMeta.mGroupId)) != mCircleGroup.mInvitedMembers.end()) /* found it */ + addMember(keyId, idtype, nickname); + } + } } void CreateCircleDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::loadRequest() UserType: " << req.mUserType; std::cerr << std::endl; +#endif if (queue == mCircleQueue) { /* now switch on req */ @@ -647,8 +838,8 @@ void CreateCircleDialog::loadRequest(const TokenQueue *queue, const TokenRequest default: std::cerr << "CreateCircleDialog::loadRequest() UNKNOWN UserType "; std::cerr << std::endl; - }//switch(req.mUserType) - }//if (queue == mCircleQueue) + } + } if (queue == mIdQueue) { /* now switch on req */ @@ -660,10 +851,14 @@ void CreateCircleDialog::loadRequest(const TokenQueue *queue, const TokenRequest default: std::cerr << "CreateCircleDialog::loadRequest() UNKNOWN UserType "; std::cerr << std::endl; - }//switch(req.mUserType) - }//if (queue == mIdQueue) + } + } } +void CreateCircleDialog::idTypeChanged() +{ + requestGxsIdentities(); +} void CreateCircleDialog::filterChanged(const QString &text) { Q_UNUSED(text); @@ -678,10 +873,36 @@ void CreateCircleDialog::filterIds() ui.treeWidget_IdList->filterItems(filterColumn, text); } -void CreateCircleDialog::createNewGxsId() +void CreateCircleDialog::createNewGxsId() { IdEditDialog dlg(this); dlg.setupNewId(false); dlg.exec(); - ui.idChooser->setDefaultId(dlg.getLastIdName()); + //ui.idChooser->setDefaultId(dlg.getLastIdName()); } + +void CreateCircleDialog::IdListCustomPopupMenu( QPoint ) +{ + QMenu contextMnu( this ); + + QTreeWidgetItem *item = ui.treeWidget_IdList->currentItem(); + if (item) { + + contextMnu.addAction(QIcon(":/images/edit_add24.png"), tr("Add Member"), this, SLOT(addMember())); + + } + + contextMnu.exec(QCursor::pos()); +} + +void CreateCircleDialog::MembershipListCustomPopupMenu( QPoint ) +{ + QMenu contextMnu( this ); + + QTreeWidgetItem *item = ui.treeWidget_membership->currentItem(); + if (item && !mReadOnly) + contextMnu.addAction(QIcon(":/images/delete.png"), tr("Remove Member"), this, SLOT(removeMember())); + + contextMnu.exec(QCursor::pos()); +} + diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.h b/retroshare-gui/src/gui/Circles/CreateCircleDialog.h index fe08d0dab..2cb050c04 100644 --- a/retroshare-gui/src/gui/Circles/CreateCircleDialog.h +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.h @@ -40,23 +40,29 @@ public: ~CreateCircleDialog(); void editNewId(bool isExternal); - void editExistingId(const RsGxsGroupId &circleId, const bool &clearList = true); - void addMember(const QString &keyId, const QString &idtype, const QString &nickname ); + void editExistingId(const RsGxsGroupId &circleId, const bool &clearList = true, bool readonly=true); + void addMember(const QString &keyId, const QString &idtype, const QString &nickname); void addMember(const RsGxsIdGroup &idGroup); void addCircle(const RsGxsCircleDetails &cirDetails); virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); - + private slots: void addMember(); void removeMember(); + void updateCircleType(bool b); void selectedId(QTreeWidgetItem*, QTreeWidgetItem*); void selectedMember(QTreeWidgetItem*, QTreeWidgetItem*); void createCircle(); void filterChanged(const QString &text); void createNewGxsId(); + void idTypeChanged(); + + /** Create the context popup menu and it's submenus */ + void IdListCustomPopupMenu( QPoint point ); + void MembershipListCustomPopupMenu( QPoint point); private: @@ -67,13 +73,14 @@ private: bool mIsExistingCircle; bool mIsExternalCircle; + bool mReadOnly; void loadCircle(uint32_t token); void loadIdentities(uint32_t token); void requestCircle(const RsGxsGroupId &groupId); void requestGxsIdentities(); - void getPgpIdentities(); + //void getPgpIdentities(); void filterIds(); diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui b/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui index 377d00c90..23d2aac7a 100644 --- a/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui @@ -6,7 +6,7 @@ 0 0 - 681 + 881 515 @@ -44,11 +44,14 @@ - Circle Membership + Circle Members + + Qt::CustomContextMenu + true @@ -126,9 +129,9 @@ - + - Known Identities + Known People @@ -186,6 +189,9 @@ + + Qt::CustomContextMenu + true @@ -240,7 +246,11 @@ - + + + Circle name + + @@ -251,12 +261,23 @@ - Creator + Creator: - + + + [Circle Admin] + + + + + + + <html><head/><body><p>The creator of a circle does not need to be known. It is however useful for public circles so that people know to whom to send a request for membership.</p></body></html> + + @@ -290,6 +311,9 @@ + + <html><head/><body><p>Publicly distributed circles are visible to your friends, which will get to know the circle data (Creator, members, etc)</p></body></html> + Public @@ -297,6 +321,9 @@ + + <html><head/><body><p>Self-restricted circles (the very existance of the circle, and its actual content) are only visible to the members of these circles. In practice the circle uses itself to limit its own distribution. </p></body></html> + Self-Restricted @@ -304,6 +331,9 @@ + + <html><head/><body><p>Circles can be restricted to the members of another circle. Only the members of that second circle will be allowed to see the new circle and its content (list of members, etc).</p></body></html> + Restricted to: @@ -363,6 +393,11 @@ QComboBox
gui/gxs/GxsCircleChooser.h
+ + GxsIdLabel + QLabel +
gui/gxs/GxsIdLabel.h
+
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 66515534b..8b0c58fb9 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -21,6 +21,8 @@ * */ +#include + #include #include @@ -28,10 +30,12 @@ #include "ui_IdDialog.h" #include "IdEditDialog.h" #include "gui/gxs/GxsIdDetails.h" +#include "gui/gxs/RsGxsUpdateBroadcastBase.h" #include "gui/common/UIStateHelper.h" #include "gui/chat/ChatDialog.h" #include "gui/settings/rsharesettings.h" #include "gui/msgs/MessageComposer.h" +#include "gui/Circles/CreateCircleDialog.h" #include "gui/RetroShareLink.h" #include "util/QtVersion.h" @@ -52,6 +56,22 @@ #define IDDIALOG_REPLIST 3 #define IDDIALOG_REFRESH 4 +#define CIRCLEGROUP_CIRCLE_COL_GROUPNAME 0 +#define CIRCLEGROUP_CIRCLE_COL_GROUPID 1 +#define CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS 2 + +#define CIRCLEGROUP_FRIEND_COL_NAME 0 +#define CIRCLEGROUP_FRIEND_COL_ID 1 + +#define CLEAR_BACKGROUND 0 +#define GREEN_BACKGROUND 1 +#define BLUE_BACKGROUND 2 +#define RED_BACKGROUND 3 +#define GRAY_BACKGROUND 4 + +#define CIRCLESDIALOG_GROUPMETA 1 +#define CIRCLESDIALOG_GROUPDATA 2 + /**************************************************************** */ @@ -102,12 +122,21 @@ IdDialog::IdDialog(QWidget *parent) : mIdQueue = NULL; + // This is used to grab the broadcast of changes from p3GxsCircles, which is discarded by the current dialog, since it expects data for p3Identity only. + mCirclesBroadcastBase = new RsGxsUpdateBroadcastBase(rsGxsCircles, this); + connect(mCirclesBroadcastBase, SIGNAL(fillDisplay(bool)), this, SLOT(updateCirclesDisplay(bool))); + allItem = new QTreeWidgetItem(); allItem->setText(0, tr("All")); contactsItem = new QTreeWidgetItem(); contactsItem->setText(0, tr("Contacts")); + ui->treeWidget_membership->clear(); + + mExternalOtherCircleItem = NULL ; + mExternalSubCircleItem = NULL ; + mExternalAdminCircleItem = NULL ; /* Setup UI helper */ mStateHelper = new UIStateHelper(this); @@ -164,7 +193,9 @@ IdDialog::IdDialog(QWidget *parent) : connect(ui->inviteButton, SIGNAL(clicked()), this, SLOT(sendInvite())); + ui->avlabel->setPixmap(QPixmap(":/images/user/friends64.png")); + ui->headerTextLabel->setText(tr("People")); /* Initialize splitter */ @@ -177,8 +208,8 @@ IdDialog::IdDialog(QWidget *parent) : /* Add filter types */ ui->filterComboBox->addItem(tr("All"), RSID_FILTER_ALL); - ui->filterComboBox->addItem(tr("Owned by you"), RSID_FILTER_OWNED_BY_YOU); - ui->filterComboBox->addItem(tr("Linked to your node"), RSID_FILTER_YOURSELF); + ui->filterComboBox->addItem(tr("Owned by myself"), RSID_FILTER_OWNED_BY_YOU); + ui->filterComboBox->addItem(tr("Linked to my node"), RSID_FILTER_YOURSELF); ui->filterComboBox->addItem(tr("Linked to neighbor nodes"), RSID_FILTER_FRIENDS); ui->filterComboBox->addItem(tr("Linked to distant nodes"), RSID_FILTER_OTHERS); ui->filterComboBox->addItem(tr("Anonymous"), RSID_FILTER_PSEUDONYMS); @@ -188,6 +219,11 @@ IdDialog::IdDialog(QWidget *parent) : QTreeWidgetItem *headerItem = ui->idTreeWidget->headerItem(); QString headerText = headerItem->text(RSID_COL_NICKNAME); ui->filterLineEdit->addFilter(QIcon(), headerText, RSID_COL_NICKNAME, QString("%1 %2").arg(tr("Search"), headerText)); + + /* Set initial section sizes */ + QHeaderView * circlesheader = ui->treeWidget_membership->header () ; + circlesheader->resizeSection (CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 280); + ui->filterLineEdit->addFilter(QIcon(), tr("ID"), RSID_COL_KEYID, tr("Search ID")); /* Setup tree */ @@ -195,6 +231,7 @@ IdDialog::IdDialog(QWidget *parent) : ui->idTreeWidget->enableColumnCustomize(true); ui->idTreeWidget->setColumnCustomizable(RSID_COL_NICKNAME, false); + ui->idTreeWidget->setColumnHidden(RSID_COL_IDTYPE, true); ui->idTreeWidget->setColumnHidden(RSID_COL_KEYID, true); @@ -212,31 +249,451 @@ IdDialog::IdDialog(QWidget *parent) : mStateHelper->setActive(IDDIALOG_IDDETAILS, false); mStateHelper->setActive(IDDIALOG_REPLIST, false); - QString hlp_str = tr( "

  Identities

\ -

In this tab you can create/edit pseudo-anonymous identities. \ -

\ +

In this tab you can create/edit pseudo-anonymous identities.

\

Identities are used to securely identify your data: sign forum and channel posts,\ and receive feedback using Retroshare built-in email system, post comments \ after channel posts, etc.

\ -

\ - Identities can optionally be signed by your Retroshare node's certificate. \ - Signed identities are easier to trust but are easily linked to your node's IP address. \ -

\ -

\ - Anonymous identities allow you to anonymously interact with other users. They cannot be \ - spoofed, but noone can prove who really owns a given identity. \ -

\ - ") ; +

Identities can optionally be signed by your Retroshare node's certificate. \ + Signed identities are easier to trust but are easily linked to your node's IP address.

\ +

Anonymous identities allow you to anonymously interact with other users. They cannot be \ + spoofed, but noone can prove who really owns a given identity.

") ; registerHelpButton(ui->helpButton, hlp_str) ; // load settings processSettings(true); + // circles stuff + + connect(ui->pushButton_extCircle, SIGNAL(clicked()), this, SLOT(createExternalCircle())); + connect(ui->pushButton_editCircle, SIGNAL(clicked()), this, SLOT(showEditExistingCircle())); + connect(ui->treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected())); + connect(ui->treeWidget_membership, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CircleListCustomPopupMenu(QPoint))); + + + /* Setup TokenQueue */ + mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); + + requestCircleGroupMeta(); +} + +void IdDialog::updateCirclesDisplay(bool) +{ +#ifdef ID_DEBUG + std::cerr << "!!Updating circles display!" << std::endl; +#endif + requestCircleGroupMeta() ; } +/************************** Request / Response *************************/ +/*** Loading Main Index ***/ + +void IdDialog::requestCircleGroupMeta() +{ + mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, true); + +#ifdef ID_DEBUG + std::cerr << "CirclesDialog::requestGroupMeta()"; + std::cerr << std::endl; +#endif + + mCircleQueue->cancelActiveRequestTokens(CIRCLESDIALOG_GROUPMETA); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + + uint32_t token; + mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, CIRCLESDIALOG_GROUPMETA); +} + +void IdDialog::requestCircleGroupData(const RsGxsCircleId& circle_id) +{ + mStateHelper->setLoading(CIRCLESDIALOG_GROUPDATA, true); + +#ifdef ID_DEBUG + std::cerr << "CirclesDialog::requestGroupData()"; + std::cerr << std::endl; +#endif + + mCircleQueue->cancelActiveRequestTokens(CIRCLESDIALOG_GROUPDATA); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::list grps ; + grps.push_back(RsGxsGroupId(circle_id)); + + uint32_t token; + mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grps, CIRCLESDIALOG_GROUPDATA); +} + +void IdDialog::loadCircleGroupMeta(const uint32_t &token) +{ + mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, false); + +#ifdef ID_DEBUG + std::cerr << "CirclesDialog::loadCircleGroupMeta()"; + std::cerr << std::endl; +#endif + + std::list groupInfo; + std::list::iterator vit; + + if (!rsGxsCircles->getGroupSummary(token,groupInfo)) + { + std::cerr << "CirclesDialog::loadCircleGroupMeta() Error getting GroupMeta"; + std::cerr << std::endl; + mStateHelper->setActive(CIRCLESDIALOG_GROUPMETA, false); + return; + } + + mStateHelper->setActive(CIRCLESDIALOG_GROUPMETA, true); + + /* add the top level item */ + //QTreeWidgetItem *personalCirclesItem = new QTreeWidgetItem(); + //personalCirclesItem->setText(0, tr("Personal Circles")); + //ui->treeWidget_membership->addTopLevelItem(personalCirclesItem); + + if(!mExternalOtherCircleItem) + { + mExternalOtherCircleItem = new QTreeWidgetItem(); + mExternalOtherCircleItem->setText(0, tr("Other visible circles")); + + ui->treeWidget_membership->addTopLevelItem(mExternalOtherCircleItem); + } + + if(!mExternalSubCircleItem ) + { + mExternalSubCircleItem = new QTreeWidgetItem(); + mExternalSubCircleItem->setText(0, tr("Circles I belong to")); + ui->treeWidget_membership->addTopLevelItem(mExternalSubCircleItem); + } + + if(!mExternalAdminCircleItem) + { + mExternalAdminCircleItem = new QTreeWidgetItem(); + mExternalAdminCircleItem->setText(0, tr("Circles I admin")); + ui->treeWidget_membership->addTopLevelItem(mExternalAdminCircleItem); + } + + for(vit = groupInfo.begin(); vit != groupInfo.end();) + { +#ifdef ID_DEBUG + std::cerr << "CirclesDialog::loadCircleGroupMeta() GroupId: " << vit->mGroupId << " Group: " << vit->mGroupName << std::endl; +#endif + + QList clist = ui->treeWidget_membership->findItems( QString::fromStdString(vit->mGroupId.toStdString()), Qt::MatchExactly|Qt::MatchRecursive, CIRCLEGROUP_CIRCLE_COL_GROUPID); + + if(clist.empty()) + { + ++vit ; +#ifdef ID_DEBUG + std::cerr << " group not already in list." << std::endl; +#endif + continue ; + } + + if(clist.size() > 1) + { + std::cerr << " (EE) found " << clist.size() << " items in tree for group id " << vit->mGroupId << ": this is unexpected." << std::endl; + vit = groupInfo.erase(vit) ; + continue ; + } + QTreeWidgetItem *item = clist.front() ; + + bool subscribed = vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ; + bool admin = vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN ; + + if(admin && item->parent() != mExternalAdminCircleItem) + { + std::cerr << " (EE) weird. Existing group is not in admin sub-items although it is admin." << std::endl; + delete item ; + ++vit ; + continue ; + } + + if(subscribed && !admin && item->parent() != mExternalSubCircleItem) + { +#ifdef ID_DEBUG + std::cerr << " Existing group is not in subscribed items although it is subscribed. Removing." << std::endl; +#endif + delete item ; + ++vit ; + continue ; + } + if(!subscribed && !admin && item->parent() != mExternalOtherCircleItem) + { +#ifdef ID_DEBUG + std::cerr << " Existing group is not in subscribed items although it is subscribed. Removing." << std::endl; +#endif + delete item ; + ++vit ; + continue ; + } + if(item->text(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) != QString::fromUtf8(vit->mGroupName.c_str())) + { +#ifdef ID_DEBUG + std::cerr << " Existing group has a new name. Updating it in the tree." << std::endl; +#endif + item->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str())); + } + + // the item is at the right place. Just remove it from the list of items to add. +#ifdef ID_DEBUG + std::cerr << " item already in place. Removing from list." << std::endl; +#endif + vit = groupInfo.erase(vit) ; + } + + for(vit = groupInfo.begin(); vit != groupInfo.end(); ++vit) + { + if (vit->mCircleType == GXS_CIRCLE_TYPE_LOCAL) + { + std::cerr << "(WW) Local circle not added to tree widget. Needs to be implmeented." << std::endl; + continue ; + } + /* Add Widget, and request Pages */ + + QTreeWidgetItem *groupItem = new QTreeWidgetItem(); + groupItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str())); + groupItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, QString::fromStdString(vit->mGroupId.toStdString())); + groupItem->setData(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole, QVariant(vit->mSubscribeFlags)); + + if (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + { +#ifdef ID_DEBUG + std::cerr << " adding item for group " << vit->mGroupId << " to admin"<< std::endl; +#endif + mExternalAdminCircleItem->addChild(groupItem); + } + else if (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { +#ifdef ID_DEBUG + std::cerr << " adding item for group " << vit->mGroupId << " to subscribed"<< std::endl; +#endif + mExternalSubCircleItem->addChild(groupItem); + } + else + { +#ifdef ID_DEBUG + std::cerr << " adding item for group " << vit->mGroupId << " to others"<< std::endl; +#endif + mExternalOtherCircleItem->addChild(groupItem); + } + } +} + +static void mark_matching_tree(QTreeWidget *w, const std::set& members, int col) +{ + w->selectionModel()->clearSelection() ; + + for(std::set::const_iterator it(members.begin());it!=members.end();++it) + { + QList clist = w->findItems( QString::fromStdString((*it).toStdString()), Qt::MatchExactly|Qt::MatchRecursive, col); + + foreach(QTreeWidgetItem* item, clist) + item->setSelected(true) ; + } +} + +void IdDialog::loadCircleGroupData(const uint32_t& token) +{ +#ifdef ID_DEBUG + std::cerr << "Loading circle info" << std::endl; +#endif + + std::vector circle_grp_v ; + rsGxsCircles->getGroupData(token, circle_grp_v); + + if (circle_grp_v.empty()) + { + std::cerr << "(EE) unexpected empty result from getGroupData. Cannot process circle now!" << std::endl; + return ; + } + + if (circle_grp_v.size() != 1) + { + std::cerr << "(EE) very weird result from getGroupData. Should get exactly one circle" << std::endl; + return ; + } + + RsGxsCircleGroup cg = circle_grp_v.front(); + RsGxsCircleId requested_cid(cg.mMeta.mGroupId) ; + + QTreeWidgetItem *item = ui->treeWidget_membership->currentItem(); + + if ((!item) || (!item->parent())) + return; + + QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID); + RsGxsCircleId id ( coltext.toStdString()) ; + + if(requested_cid != id) + { + std::cerr << "(WW) not the same circle. Dropping request." << std::endl; + return ; + } + + /* now mark all the members */ + + std::set members = cg.mInvitedMembers; + + mark_matching_tree(ui->idTreeWidget, members, RSID_COL_KEYID) ; + + mStateHelper->setLoading(CIRCLESDIALOG_GROUPDATA, false); +} + +void IdDialog::createExternalCircle() +{ + CreateCircleDialog dlg; + dlg.editNewId(true); + dlg.exec(); + + requestCircleGroupMeta(); // update GUI +} +void IdDialog::showEditExistingCircle() +{ + QTreeWidgetItem *item = ui->treeWidget_membership->currentItem(); + if ((!item) || (!item->parent())) + { + return; + } + + uint32_t subscribe_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt(); + + QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID); + RsGxsGroupId id ( coltext.toStdString()); + + CreateCircleDialog dlg; + + dlg.editExistingId(id,true,!(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) ; + dlg.exec(); + + requestCircleGroupMeta(); // update GUI +} + +void IdDialog::CircleListCustomPopupMenu( QPoint ) +{ + // (cyril) Removed this because we have a edit button already. +#ifdef SUSPENDED + QMenu contextMnu( this ); + + QTreeWidgetItem *item = ui->treeWidget_membership->currentItem(); + if (item) { + + contextMnu.addAction(QIcon(IMAGE_EDIT), tr("Edit Circle"), this, SLOT(editExistingCircle())); + + } + + contextMnu.exec(QCursor::pos()); +#endif +} + +static void set_item_background(QTreeWidgetItem *item, uint32_t type) +{ + QBrush brush; + switch(type) + { + default: + case CLEAR_BACKGROUND: + brush = QBrush(Qt::white); + break; + case GREEN_BACKGROUND: + brush = QBrush(Qt::green); + break; + case BLUE_BACKGROUND: + brush = QBrush(Qt::blue); + break; + case RED_BACKGROUND: + brush = QBrush(Qt::red); + break; + case GRAY_BACKGROUND: + brush = QBrush(Qt::gray); + break; + } + item->setBackground (0, brush); +} + +static void update_children_background(QTreeWidgetItem *item, uint32_t type) +{ + int count = item->childCount(); + for(int i = 0; i < count; ++i) + { + QTreeWidgetItem *child = item->child(i); + + if (child->childCount() > 0) + { + update_children_background(child, type); + } + set_item_background(child, type); + } +} + +#ifdef SUSPENDED +static void set_tree_background(QTreeWidget *tree, uint32_t type) +{ + std::cerr << "CirclesDialog set_tree_background()"; + std::cerr << std::endl; + + /* grab all toplevel */ + int count = tree->topLevelItemCount(); + for(int i = 0; i < count; ++i) + { + QTreeWidgetItem *item = tree->topLevelItem(i); + /* resursively clear child backgrounds */ + update_children_background(item, type); + set_item_background(item, type); + } +} + +static void check_mark_item(QTreeWidgetItem *item, const std::set &names, uint32_t col, uint32_t type) +{ + QString coltext = item->text(col); + RsPgpId colstr ( coltext.toStdString()); + if (names.end() != names.find(colstr)) + { + set_item_background(item, type); + std::cerr << "CirclesDialog check_mark_item: found match: " << colstr; + std::cerr << std::endl; + } +} +#endif +void IdDialog::circle_selected() +{ + QTreeWidgetItem *item = ui->treeWidget_membership->currentItem(); + +#ifdef ID_DEBUG + std::cerr << "CirclesDialog::circle_selected() valid circle chosen"; + std::cerr << std::endl; +#endif + + if ((!item) || (!item->parent())) + { + mStateHelper->setWidgetEnabled(ui->pushButton_editCircle, false); + ui->pushButton_editCircle->setText(tr("Show details")) ; + ui->pushButton_editCircle->setEnabled(false) ; + mark_matching_tree(ui->idTreeWidget, std::set(), RSID_COL_KEYID) ; + return; + } + + uint32_t subscribe_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt(); + ui->pushButton_editCircle->setEnabled(true) ; + + if(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + ui->pushButton_editCircle->setText(tr("Edit circle")) ; + else + ui->pushButton_editCircle->setText(tr("Show details")) ; + + //set_item_background(item, BLUE_BACKGROUND); + + QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID); + RsGxsCircleId id ( coltext.toStdString()) ; + + requestCircleGroupData(id) ; +} + IdDialog::~IdDialog() { // save settings @@ -246,6 +703,24 @@ IdDialog::~IdDialog() delete(mIdQueue); } +static QString getHumanReadableDuration(uint32_t seconds) +{ + if(seconds < 60) + return QString(QObject::tr("%1 seconds ago")).arg(seconds) ; + else if(seconds < 120) + return QString(QObject::tr("%1 minute ago")).arg(seconds/60) ; + else if(seconds < 3600) + return QString(QObject::tr("%1 minutes ago")).arg(seconds/60) ; + else if(seconds < 7200) + return QString(QObject::tr("%1 hour ago")).arg(seconds/3600) ; + else if(seconds < 24*3600) + return QString(QObject::tr("%1 hours ago")).arg(seconds/3600) ; + else if(seconds < 2*24*3600) + return QString(QObject::tr("%1 day ago")).arg(seconds/86400) ; + else + return QString(QObject::tr("%1 days ago")).arg(seconds/86400) ; +} + void IdDialog::processSettings(bool load) { Settings->beginGroup("IdDialog"); @@ -304,24 +779,6 @@ void IdDialog::updateSelection() } } -static QString getHumanReadableDuration(uint32_t seconds) -{ - if(seconds < 60) - return QString(QObject::tr("%1 seconds ago")).arg(seconds) ; - else if(seconds < 120) - return QString(QObject::tr("%1 minute ago")).arg(seconds/60) ; - else if(seconds < 3600) - return QString(QObject::tr("%1 minutes ago")).arg(seconds/60) ; - else if(seconds < 7200) - return QString(QObject::tr("%1 hour ago")).arg(seconds/3600) ; - else if(seconds < 24*3600) - return QString(QObject::tr("%1 hours ago")).arg(seconds/3600) ; - else if(seconds < 2*24*3600) - return QString(QObject::tr("%1 day ago")).arg(seconds/86400) ; - else - return QString(QObject::tr("%1 days ago")).arg(seconds/86400) ; -} - void IdDialog::requestIdList() { //Disable by default, will be enable by insertIdDetails() @@ -394,9 +851,12 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, item->setText(RSID_COL_NICKNAME, QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE)); item->setText(RSID_COL_KEYID, QString::fromStdString(data.mMeta.mGroupId.toStdString())); + + //time_t now = time(NULL) ; + //item->setText(RSID_COL_LASTUSED, getHumanReadableDuration(now - data.mLastUsageTS)) ; item->setData(RSID_COL_KEYID, Qt::UserRole,QVariant(item_flags)) ; - + item->setTextAlignment(RSID_COL_VOTES, Qt::AlignRight); item->setData(RSID_COL_VOTES,Qt::DisplayRole, QString::number(info.mOverallReputationScore - 1.0f,'f',3)); @@ -579,7 +1039,6 @@ void IdDialog::requestIdDetails() mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, IDDIALOG_IDDETAILS); } - void IdDialog::insertIdDetails(uint32_t token) { mStateHelper->setLoading(IDDIALOG_IDDETAILS, false); @@ -635,7 +1094,9 @@ void IdDialog::insertIdDetails(uint32_t token) #ifdef ID_DEBUG std::cerr << "Setting header frame image : " << pix.width() << " x " << pix.height() << std::endl; #endif + ui->avlabel->setPixmap(pixmap); + ui->avatarLabel->setPixmap(pixmap); if (data.mPgpKnown) @@ -816,6 +1277,7 @@ void IdDialog::updateDisplay(bool complete) return; } + requestCircleGroupMeta(); std::list grpIds; getAllGrpIds(grpIds); @@ -915,36 +1377,64 @@ void IdDialog::insertRepList(uint32_t token) mStateHelper->setActive(IDDIALOG_REPLIST, true); } -void IdDialog::loadRequest(const TokenQueue * /*queue*/, const TokenRequest &req) +void IdDialog::loadRequest(const TokenQueue * queue, const TokenRequest &req) { #ifdef ID_DEBUG std::cerr << "IdDialog::loadRequest() UserType: " << req.mUserType; std::cerr << std::endl; #endif - switch(req.mUserType) - { - case IDDIALOG_IDLIST: - insertIdList(req.mToken); - break; + if(queue == mIdQueue) + { + switch(req.mUserType) + { + case IDDIALOG_IDLIST: + insertIdList(req.mToken); + break; - case IDDIALOG_IDDETAILS: - insertIdDetails(req.mToken); - break; + case IDDIALOG_IDDETAILS: + insertIdDetails(req.mToken); + break; - case IDDIALOG_REPLIST: - insertRepList(req.mToken); - break; + case IDDIALOG_REPLIST: + insertRepList(req.mToken); + break; - case IDDIALOG_REFRESH: -// replaced by RsGxsUpdateBroadcastPage -// updateDisplay(true); - break; - default: - std::cerr << "IdDialog::loadRequest() ERROR"; - std::cerr << std::endl; - break; - } + case IDDIALOG_REFRESH: + // replaced by RsGxsUpdateBroadcastPage + // updateDisplay(true); + break; + default: + std::cerr << "IdDialog::loadRequest() ERROR"; + std::cerr << std::endl; + break; + } + } + + if(queue == mCircleQueue) + { +#ifdef ID_DEBUG + std::cerr << "CirclesDialog::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; +#endif + + /* now switch on req */ + switch(req.mUserType) + { + case CIRCLESDIALOG_GROUPMETA: + loadCircleGroupMeta(req.mToken); + break; + + case CIRCLESDIALOG_GROUPDATA: + loadCircleGroupData(req.mToken); + break; + + default: + std::cerr << "CirclesDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } } void IdDialog::IdListCustomPopupMenu( QPoint ) @@ -981,7 +1471,9 @@ void IdDialog::IdListCustomPopupMenu( QPoint ) if(item_flags & RSID_FILTER_OWNED_BY_YOU) one_item_owned_by_you = true ; +#ifdef ID_DEBUG std::cerr << " item flags = " << item_flags << std::endl; +#endif RsGxsId keyId((*it)->text(RSID_COL_KEYID).toStdString()); RsReputations::ReputationInfo info ; diff --git a/retroshare-gui/src/gui/Identity/IdDialog.h b/retroshare-gui/src/gui/Identity/IdDialog.h index be27ebaed..9a13fa690 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.h +++ b/retroshare-gui/src/gui/Identity/IdDialog.h @@ -55,8 +55,18 @@ public: protected: virtual void updateDisplay(bool complete); - + + void loadCircleGroupMeta(const uint32_t &token); + void loadCircleGroupData(const uint32_t &token); + + void requestCircleGroupMeta(); + void requestCircleGroupData(const RsGxsCircleId& circle_id); + private slots: + void createExternalCircle(); + void showEditExistingCircle(); + void updateCirclesDisplay(bool); + void filterComboBoxChanged(); void filterChanged(const QString &text); @@ -74,6 +84,9 @@ private slots: /** Create the context popup menu and it's submenus */ void IdListCustomPopupMenu( QPoint point ); + void CircleListCustomPopupMenu(QPoint point) ; + void circle_selected() ; + void addtoContacts(); void removefromContacts(); @@ -104,10 +117,16 @@ private: private: TokenQueue *mIdQueue; + TokenQueue *mCircleQueue; + UIStateHelper *mStateHelper; QTreeWidgetItem *contactsItem; QTreeWidgetItem *allItem; + QTreeWidgetItem *mExternalSubCircleItem; + QTreeWidgetItem *mExternalOtherCircleItem; + QTreeWidgetItem *mExternalAdminCircleItem; + RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ; RsGxsGroupId mId; diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index 302dd98eb..921dc7891 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -6,8 +6,8 @@ 0 0 - 745 - 640 + 1475 + 1134 @@ -19,14 +19,8 @@ - - - 0 - - - 0 - - + + @@ -62,7 +56,7 @@ - :/images/user/friends24.png + :/images/user/friends24.png true @@ -102,7 +96,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -116,7 +110,7 @@
- + Qt::Horizontal @@ -159,7 +153,7 @@ New ID - + :/images/identity/identity_create_32.png:/images/identity/identity_create_32.png @@ -235,225 +229,345 @@
- - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 12 - - - - - - 64 - 64 - + + + 0 + + + + Person + + + + + + + + QFrame::StyledPanel - - - 64 - 64 - - - - - - - - - - true + + QFrame::Raised + + + 12 + + + + + + 64 + 64 + + + + + 64 + 64 + + + + + + + + + + true + + + + + + + People + + + + - - - - People + + + + Identity info + + + + + 6 + + + 6 + + + + + Identity ID : + + + + + + + Identity name : + + + + + + + Owner node ID : + + + + + + + true + + + true + + + + + + + true + + + true + + + + + + + true + + + true + + + + + + + Owner node name : + + + + + + + true + + + true + + + + + + + Type: + + + + + + + + + + Last used: + + + + + + + + + + + + + + + 0 + 0 + + + + + 128 + 128 + + + + + 128 + 128 + + + + QFrame::Box + + + QFrame::Sunken + + + Your Avatar + + + true + + + Qt::AlignCenter + + + + + + + Send Invite + + + + + + + Qt::Vertical + + + + 20 + 2 + + + + + + + - - - - - - - Identity info - - - - - - 6 + + + + + 0 + 0 + - - 6 + + Reputation - - - - Identity ID : - - - - - - - Identity name : - - - - - - - Owner node ID : - - - - - - - true - - - true - - - - - - - true - - - true - - - - - - - true - - - true - - - - - - - Owner node name : - - - - - - - true - - - true - - - - - - - Type: - - - - - - - - - - Last used: - - - - - - - + + + + + 6 + + + + + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> + + + true + + + + + + + Your opinion: + + + + + + + Neighbor nodes: + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the average of your friend's opinions. If not, your own opinion gives the score.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -0.6, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a higher reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 30 days). </p> +<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + 0 + + + + Negative + + + + ../../../../../trunk/retroshare-gui/src/gui/icons/yellow_biohazard64.png../../../../../trunk/retroshare-gui/src/gui/icons/yellow_biohazard64.png + + + + + Neutral + + + + + Positive + + + + + + + + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> + + + true + + + + + + + + 75 + true + + + + Overall: + + + + + + + - - - - - - - 0 - 0 - - - - - 128 - 128 - - - - - 128 - 128 - - - - QFrame::Box - - - QFrame::Sunken - - - Your Avatar - - - true - - - Qt::AlignCenter - - - - - - - Send Invite - - - - - - - Qt::Vertical - - - - 20 - 2 - - - - - - - - + + Qt::Vertical + + QSizePolicy::Expanding + 20 @@ -463,137 +577,84 @@ - - - - - - - 0 - 0 - - - - Reputation - - + + + + + + Circles + + + + - - - 6 + + + Create Circle - - - - <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - - - true - - - - - - - Your opinion: - - - - - - - Neighbor nodes: - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the average of your friend's opinions. If not, your own opinion gives the score.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -0.6, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a higher reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 30 days). </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - 0 - - - - Negative - - - - ../icons/yellow_biohazard64.png../icons/yellow_biohazard64.png - - - - - Neutral - - - - - Positive - - - - - - - - <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - - - true - - - - - - - - 75 - true - - - - Overall: - - - - + + + + + + Edit Circle + + + + + + + Qt::Horizontal + + + + 40 + 20 + + +
- - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 40 - - - - - + + + + + Qt::CustomContextMenu + + + true + + + + Name + + + + + IDs + + + + + Public Circles + + + + + Personal Circles + + + + + + - + :/images/edit_16.png:/images/edit_16.png @@ -605,7 +666,7 @@ p, li { white-space: pre-wrap; } - + :/images/delete.png:/images/delete.png @@ -614,7 +675,7 @@ p, li { white-space: pre-wrap; } - + :/images/toaster/chat.png:/images/toaster/chat.png @@ -651,7 +712,7 @@ p, li { white-space: pre-wrap; } idTreeWidget - + diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index c7dfa813d..4a2a9d448 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -95,9 +95,9 @@ #include "gui/gxschannels/GxsChannelDialog.h" #include "gui/gxsforums/GxsForumsDialog.h" #include "gui/Identity/IdDialog.h" -#ifdef RS_USE_CIRCLES -#include "gui/Circles/CirclesDialog.h" -#endif +//#ifdef RS_USE_CIRCLES +//#include "gui/Circles/CirclesDialog.h" +//#endif #ifdef RS_USE_WIKI #include "gui/WikiPoos/WikiDialog.h" #endif @@ -359,7 +359,7 @@ void MainWindow::initStackedPage() addPage(newsFeed = new NewsFeed(ui->stackPages), grp, ¬ify); addPage(friendsDialog = new FriendsDialog(ui->stackPages), grp, ¬ify); -#ifdef RS_USE_CIRCLES +#ifdef RS_USE_NEW_PEOPLE_DIALOG PeopleDialog *peopleDialog = NULL; addPage(peopleDialog = new PeopleDialog(ui->stackPages), grp, ¬ify); #endif @@ -367,10 +367,10 @@ void MainWindow::initStackedPage() IdDialog *idDialog = NULL; addPage(idDialog = new IdDialog(ui->stackPages), grp, ¬ify); -#ifdef RS_USE_CIRCLES - CirclesDialog *circlesDialog = NULL; - addPage(circlesDialog = new CirclesDialog(ui->stackPages), grp, ¬ify); -#endif +//#ifdef RS_USE_CIRCLES +// CirclesDialog *circlesDialog = NULL; +// addPage(circlesDialog = new CirclesDialog(ui->stackPages), grp, ¬ify); +//#endif addPage(transfersDialog = new TransfersDialog(ui->stackPages), grp, ¬ify); addPage(chatLobbyDialog = new ChatLobbyWidget(ui->stackPages), grp, ¬ify); diff --git a/retroshare-gui/src/gui/People/CircleWidget.cpp b/retroshare-gui/src/gui/People/CircleWidget.cpp index 0bf89a906..7a4058da0 100644 --- a/retroshare-gui/src/gui/People/CircleWidget.cpp +++ b/retroshare-gui/src/gui/People/CircleWidget.cpp @@ -54,8 +54,8 @@ void CircleWidget::updateData(const RsGroupMetaData& gxs_group_info if (_circle_details != details) { _circle_details=details; typedef std::set::iterator itUnknownPeers; - for (itUnknownPeers it = _circle_details.mUnknownPeers.begin() - ; it != _circle_details.mUnknownPeers.end() + for (itUnknownPeers it = _circle_details.mAllowedAnonPeers.begin() + ; it != _circle_details.mAllowedAnonPeers.end() ; ++it) { RsGxsId gxs_id = *it; if(!gxs_id.isNull()) { @@ -63,15 +63,14 @@ void CircleWidget::updateData(const RsGroupMetaData& gxs_group_info }//if(!gxs_id.isNull()) }//for (itUnknownPeers it = _circle_details.mUnknownPeers.begin() - typedef std::map >::const_iterator itAllowedPeers; - for (itAllowedPeers it = _circle_details.mAllowedPeers.begin() - ; it != _circle_details.mAllowedPeers.end() - ; ++it ) { + typedef std::map >::const_iterator itAllowedPeers; + for (itAllowedPeers it = _circle_details.mAllowedSignedPeers.begin() ; it != _circle_details.mAllowedSignedPeers.end() ; ++it ) + { RsPgpId pgp_id = it->first; emit askForPGPIdentityWidget(pgp_id); - std::list gxs_id_list = it->second; - typedef std::list::const_iterator itGxsId; + std::set gxs_id_list = it->second; + typedef std::set::const_iterator itGxsId; for (itGxsId curs=gxs_id_list.begin() ; curs != gxs_id_list.end() ; ++curs) { diff --git a/retroshare-gui/src/gui/People/IdentityWidget.cpp b/retroshare-gui/src/gui/People/IdentityWidget.cpp index 045f2f22f..515cf4c6f 100644 --- a/retroshare-gui/src/gui/People/IdentityWidget.cpp +++ b/retroshare-gui/src/gui/People/IdentityWidget.cpp @@ -1,202 +1,210 @@ -#include "gui/People/IdentityWidget.h" -#include "ui_IdentityWidget.h" - -#include "gui/common/AvatarDefs.h" -#include - -#include -#include -#include - -IdentityWidget::IdentityWidget(QString name/*=QString()*/, QWidget *parent/*=0*/) : - FlowLayoutItem(name, parent), - ui(new Ui::IdentityWidget) -{ - ui->setupUi(this); - _haveGXSId = false; - _havePGPDetail = false; - - m_myName = name; - ui->labelName->setText(m_myName); - ui->labelName->setToolTip(m_myName); - QFont font = ui->labelName->font(); - font.setItalic(false); - ui->labelName->setFont(font); - - _keyId=""; - ui->labelKeyId->setText(_keyId); - ui->labelKeyId->setToolTip(_keyId); - ui->labelKeyId->setVisible(false); - - ui->labelGXSId->setText(_keyId); - ui->labelGXSId->setToolTip(_keyId); - ui->labelGXSId->setVisible(false); - - ui->pbAdd->setVisible(false); - QObject::connect(ui->pbAdd, SIGNAL(clicked()), this, SLOT(pbAdd_clicked())); - - _scene = new QGraphicsScene(this); - ui->graphicsView->setScene(_scene); - - //To grab events - ui->graphicsView->setEnabled(false); - - ui->graphicsView->setAlignment(Qt::AlignLeft | Qt::AlignTop); - - setIsCurrent(false); - setIsSelected(false); - setAcceptDrops(true); -} - -IdentityWidget::~IdentityWidget() -{ - delete _scene; - delete ui; -} - -void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info) -{ - //if (_group_info != gxs_group_info) { - _group_info = gxs_group_info; - _haveGXSId = true; - - m_myName = QString::fromUtf8(_group_info.mMeta.mGroupName.c_str()); - ui->labelName->setText(m_myName); - if (_havePGPDetail) { - ui->labelName->setToolTip(tr("GXS name:").append(" "+m_myName).append("\n") - .append(tr("PGP name:").append(" "+_nickname))); - } else {//if (m_myName != _nickname) - ui->labelName->setToolTip(tr("GXS name:").append(" "+m_myName)); - }//else (m_myName != _nickname) - - - _gxsId = QString::fromStdString(_group_info.mMeta.mGroupId.toStdString()); - ui->labelGXSId->setText(_gxsId); - ui->labelGXSId->setToolTip(tr("GXS id:").append(" "+_gxsId)); - - if (!_havePGPDetail) { - QFont font = ui->labelName->font(); - font.setItalic(false); - ui->labelName->setFont(font); - - _keyId=QString::fromStdString(_group_info.mMeta.mGroupId.toStdString()); - ui->labelKeyId->setText(_keyId); - ui->labelKeyId->setToolTip(tr("GXS id:").append(" "+_keyId)); - ui->labelKeyId->setVisible(false); - - /// (TODO) Get real ident icon - QImage image = GxsIdDetails::makeDefaultIcon(RsGxsId(_group_info.mMeta.mGroupId)); - if (_avatar != image) { - _avatar = image; - _scene->clear(); - _scene->addPixmap(QPixmap::fromImage(image.scaled(ui->graphicsView->width(),ui->graphicsView->height()))); - emit imageUpdated(); - }//if (_avatar != image) - }//if (!_havePGPDetail) - - //}//if (_group_info != gxs_group_info) -} - -void IdentityWidget::updateData(const RsPeerDetails &pgp_details) -{ - //if (_details != pgp_details) { - _details = pgp_details; - _havePGPDetail = true; - - _nickname = QString::fromUtf8(_details.name.c_str()); - if (!_haveGXSId) m_myName = _nickname; - ui->labelName->setText(m_myName); - if (_haveGXSId) { - ui->labelName->setToolTip(tr("GXS name:").append(" "+m_myName).append("\n") - .append(tr("PGP name:").append(" "+_nickname))); - } else {//if (m_myName != _nickname) - ui->labelName->setToolTip(tr("PGP name:").append(" "+_nickname)); - }//else (m_myName != _nickname) - - QFont font = ui->labelName->font(); - font.setItalic(true); - ui->labelName->setFont(font); - - _keyId = QString::fromStdString(_details.gpg_id.toStdString()); - ui->labelKeyId->setText(_keyId); - ui->labelKeyId->setToolTip(tr("PGP id:").append(" "+_keyId)); - - QPixmap avatar; - AvatarDefs::getAvatarFromGpgId(_details.gpg_id.toStdString(), avatar); - if (_avatar != avatar.toImage()) { - _avatar = avatar.toImage(); - _scene->clear(); - _scene->addPixmap(avatar.scaled(ui->graphicsView->width(),ui->graphicsView->height())); - emit imageUpdated(); - }//if (_avatar != avatar.toImage()) - - //}//if (_details != gpg_details) -} - -void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info, const RsPeerDetails &pgp_details) -{ - updateData(gxs_group_info); - updateData(pgp_details); -} - -QSize IdentityWidget::sizeHint() -{ - QSize size; - size.setHeight(ui->graphicsView->size().height() + ui->labelName->size().height()); - size.setWidth(ui->graphicsView->size().width() > ui->labelName->size().width() - ?ui->graphicsView->size().width() : ui->labelName->size().width()); - return size; -} - -const QPixmap IdentityWidget::getImage() -{ -#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) - return ui->graphicsView->grab(); - //return this->grab(); //QT5 -#else - return QPixmap::grabWidget(ui->graphicsView); - //return QPixmap::grabWidget(this); -#endif -} - -const QPixmap IdentityWidget::getDragImage() -{ -#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) - return ui->graphicsView->grab(); - //return this->grab(); //QT5 -#else - return QPixmap::grabWidget(ui->graphicsView); - //return QPixmap::grabWidget(this); -#endif -} - -void IdentityWidget::setIsSelected(bool value) -{ - m_isSelected=value; - QFont font=ui->labelName->font(); - font.setBold(value); - ui->labelName->setFont(font); -} -/* -bool IdentityWidget::isSelected() -{ - return m_isSelected; -}*/ - -void IdentityWidget::setIsCurrent(bool value) -{ - m_isCurrent=value; - ui->labelKeyId->setVisible(value); - ui->labelGXSId->setVisible(value && (_haveGXSId && _havePGPDetail)); - ui->pbAdd->setVisible(value); -} -/* -bool IdentityWidget::isCurrent() -{ - return m_isCurrent; -}*/ - -void IdentityWidget::pbAdd_clicked() -{ - emit addButtonClicked(); -} +#include "gui/People/IdentityWidget.h" +#include "ui_IdentityWidget.h" + +#include "gui/common/AvatarDefs.h" +#include + +#include +#include +#include + +IdentityWidget::IdentityWidget(QString name/*=QString()*/, QWidget *parent/*=0*/) : + FlowLayoutItem(name, parent), + ui(new Ui::IdentityWidget) +{ + ui->setupUi(this); + _haveGXSId = false; + _havePGPDetail = false; + + m_myName = name; + ui->labelName->setText(m_myName); + ui->labelName->setToolTip(m_myName); + QFont font = ui->labelName->font(); + font.setItalic(false); + ui->labelName->setFont(font); + + _keyId=""; + ui->labelKeyId->setText(_keyId); + ui->labelKeyId->setToolTip(_keyId); + ui->labelKeyId->setVisible(false); + + ui->labelGXSId->setText(_keyId); + ui->labelGXSId->setToolTip(_keyId); + ui->labelGXSId->setVisible(false); + + ui->pbAdd->setVisible(false); + QObject::connect(ui->pbAdd, SIGNAL(clicked()), this, SLOT(pbAdd_clicked())); + + _scene = new QGraphicsScene(this); + ui->graphicsView->setScene(_scene); + + //To grab events + ui->graphicsView->setEnabled(false); + + ui->graphicsView->setAlignment(Qt::AlignLeft | Qt::AlignTop); + + setIsCurrent(false); + setIsSelected(false); + setAcceptDrops(true); +} + +IdentityWidget::~IdentityWidget() +{ + delete _scene; + delete ui; +} + +void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info) +{ + //if (_group_info != gxs_group_info) { + _group_info = gxs_group_info; + _haveGXSId = true; + + m_myName = QString::fromUtf8(_group_info.mMeta.mGroupName.c_str()); + ui->labelName->setText(m_myName); + if (_havePGPDetail) { + ui->labelName->setToolTip(tr("GXS name:").append(" "+m_myName).append("\n") + .append(tr("PGP name:").append(" "+_nickname))); + } else {//if (m_myName != _nickname) + ui->labelName->setToolTip(tr("GXS name:").append(" "+m_myName)); + }//else (m_myName != _nickname) + + + _gxsId = QString::fromStdString(_group_info.mMeta.mGroupId.toStdString()); + ui->labelGXSId->setText(_gxsId); + ui->labelGXSId->setToolTip(tr("GXS id:").append(" "+_gxsId)); + + if (!_havePGPDetail) { + QFont font = ui->labelName->font(); + font.setItalic(false); + ui->labelName->setFont(font); + + _keyId=QString::fromStdString(_group_info.mMeta.mGroupId.toStdString()); + ui->labelKeyId->setText(_keyId); + ui->labelKeyId->setToolTip(tr("GXS id:").append(" "+_keyId)); + ui->labelKeyId->setVisible(false); + + /// (TODO) Get real ident icon + QImage image; + + if(_group_info.mImage.mSize > 0 && image.loadFromData(_group_info.mImage.mData, _group_info.mImage.mSize, "PNG")) + image = image; + else + image = GxsIdDetails::makeDefaultIcon(RsGxsId(_group_info.mMeta.mGroupId)); + + if (_avatar != image) { + _avatar = image; + _scene->clear(); + _scene->addPixmap(QPixmap::fromImage(image.scaled(ui->graphicsView->width(),ui->graphicsView->height()))); + emit imageUpdated(); + }//if (_avatar != image) + }//if (!_havePGPDetail) + + //}//if (_group_info != gxs_group_info) +} + +void IdentityWidget::updateData(const RsPeerDetails &pgp_details) +{ + //if (_details != pgp_details) { + _details = pgp_details; + _havePGPDetail = true; + + _nickname = QString::fromUtf8(_details.name.c_str()); + if (!_haveGXSId) m_myName = _nickname; + ui->labelName->setText(m_myName); + if (_haveGXSId) { + ui->labelName->setToolTip(tr("GXS name:").append(" "+m_myName).append("\n") + .append(tr("PGP name:").append(" "+_nickname))); + } else {//if (m_myName != _nickname) + ui->labelName->setToolTip(tr("PGP name:").append(" "+_nickname)); + }//else (m_myName != _nickname) + + QFont font = ui->labelName->font(); + font.setItalic(true); + ui->labelName->setFont(font); + + _keyId = QString::fromStdString(_details.gpg_id.toStdString()); + ui->labelKeyId->setText(_keyId); + ui->labelKeyId->setToolTip(tr("PGP id:").append(" "+_keyId)); + + QPixmap avatar; + /*AvatarDefs::getAvatarFromGpgId(_details.gpg_id, avatar); + if (_avatar != avatar.toImage()) { + _avatar = avatar.toImage(); + _scene->clear(); + _scene->addPixmap(avatar.scaled(ui->graphicsView->width(),ui->graphicsView->height())); + emit imageUpdated(); + }*///if (_avatar != avatar.toImage()) + + + //}//if (_details != gpg_details) +} + +void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info, const RsPeerDetails &pgp_details) +{ + updateData(gxs_group_info); + updateData(pgp_details); +} + +QSize IdentityWidget::sizeHint() +{ + QSize size; + size.setHeight(ui->graphicsView->size().height() + ui->labelName->size().height()); + size.setWidth(ui->graphicsView->size().width() > ui->labelName->size().width() + ?ui->graphicsView->size().width() : ui->labelName->size().width()); + return size; +} + +const QPixmap IdentityWidget::getImage() +{ +#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) + return ui->graphicsView->grab(); + //return this->grab(); //QT5 +#else + return QPixmap::grabWidget(ui->graphicsView); + //return QPixmap::grabWidget(this); +#endif +} + +const QPixmap IdentityWidget::getDragImage() +{ +#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) + return ui->graphicsView->grab(); + //return this->grab(); //QT5 +#else + return QPixmap::grabWidget(ui->graphicsView); + //return QPixmap::grabWidget(this); +#endif +} + +void IdentityWidget::setIsSelected(bool value) +{ + m_isSelected=value; + QFont font=ui->labelName->font(); + font.setBold(value); + ui->labelName->setFont(font); +} +/* +bool IdentityWidget::isSelected() +{ + return m_isSelected; +}*/ + +void IdentityWidget::setIsCurrent(bool value) +{ + m_isCurrent=value; + ui->labelKeyId->setVisible(value); + ui->labelGXSId->setVisible(value && (_haveGXSId && _havePGPDetail)); + ui->pbAdd->setVisible(value); +} +/* +bool IdentityWidget::isCurrent() +{ + return m_isCurrent; +}*/ + +void IdentityWidget::pbAdd_clicked() +{ + emit addButtonClicked(); +} + diff --git a/retroshare-gui/src/gui/People/IdentityWidget.ui b/retroshare-gui/src/gui/People/IdentityWidget.ui index 27a6a6610..9a9ed0e90 100644 --- a/retroshare-gui/src/gui/People/IdentityWidget.ui +++ b/retroshare-gui/src/gui/People/IdentityWidget.ui @@ -1,144 +1,146 @@ - - - IdentityWidget - - - - 0 - 0 - 102 - 158 - - - - - 0 - - - 1 - - - - - - 100 - 100 - - - - - 100 - 100 - - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - - 0.000000000000000 - 0.000000000000000 - 100.000000000000000 - 100.000000000000000 - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - 0 - 15 - - - - - 100 - 16777215 - - - - Name - - - true - - - Qt::AlignCenter - - - - - - - - 0 - 15 - - - - - 100 - 16777215 - - - - KeyId - - - Qt::AlignCenter - - - - - - - - 0 - 15 - - - - - 100 - 16777215 - - - - GXSId - - - Qt::AlignCenter - - - - - - - Add - - - - - - - - - ElidedLabel - QLabel -
gui/common/ElidedLabel.h
- 1 -
-
- -
+ + + IdentityWidget + + + + 0 + 0 + 102 + 170 + + + + + 0 + + + 1 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + + 0.000000000000000 + 0.000000000000000 + 100.000000000000000 + 100.000000000000000 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + 0 + 15 + + + + + 100 + 16777215 + + + + Name + + + true + + + Qt::AlignCenter + + + + + + + + 0 + 15 + + + + + 100 + 16777215 + + + + KeyId + + + Qt::AlignCenter + + + + + + + + 0 + 15 + + + + + 100 + 16777215 + + + + GXSId + + + Qt::AlignCenter + + + + + + + Add + + + + + + + + ElidedLabel + QLabel +
gui/common/ElidedLabel.h
+ 1 +
+
+ + + + +
diff --git a/retroshare-gui/src/gui/People/PeopleDialog.cpp b/retroshare-gui/src/gui/People/PeopleDialog.cpp index 6740bef66..a2c383361 100644 --- a/retroshare-gui/src/gui/People/PeopleDialog.cpp +++ b/retroshare-gui/src/gui/People/PeopleDialog.cpp @@ -26,11 +26,16 @@ #include "gui/Circles/CreateCircleDialog.h" #include "gui/common/FlowLayout.h" #include "gui/settings/rsharesettings.h" +#include "gui/msgs/MessageComposer.h" +#include "gui/gxs/GxsIdDetails.h" +#include "gui/Identity/IdDetailsDialog.h" #include "retroshare/rspeers.h" #include "retroshare/rsidentity.h" #include "retroshare/rsgxscircles.h" #include "retroshare/rsgxsflags.h" +#include "retroshare/rsmsgs.h" +#include "retroshare/rsids.h" #include #include @@ -55,6 +60,9 @@ PeopleDialog::PeopleDialog(QWidget *parent) /* Setup TokenQueue */ mIdentityQueue = new TokenQueue(rsIdentity->getTokenService(), this); mCirclesQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); + + + tabWidget->removeTab(1); //need erase QtCreator Layout first(for Win) delete idExternal->layout(); @@ -74,11 +82,11 @@ PeopleDialog::PeopleDialog(QWidget *parent) {//First Get Item created in Qt Designer for Internal int count = idInternal->children().count(); - for (int curs = 0; curs < count; ++curs){ + for (int curs = 0; curs < count; ++curs){ QObject *obj = idInternal->children().at(curs); - QWidget *wid = qobject_cast(obj); + QWidget *wid = qobject_cast(obj); if (wid) _flowLayoutInt->addWidget(wid); - }//for (int curs = 0; curs < count; ++curs) + }//for (int curs = 0; curs < count; ++curs) }//End First Get Item created in Qt Designer for Internal pictureFlowWidgetExternal->setAcceptDrops(true); @@ -417,6 +425,45 @@ void PeopleDialog::iw_AddButtonClickedExt() action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())); }//for( itCurs =_ext_circles_widgets.begin(); + + std::list own_identities ; + rsIdentity->getOwnIds(own_identities) ; + + if(own_identities.size() <= 1) + { + QAction *action = contextMnu.addAction(QIcon(":/images/chat_24.png"), tr("Chat with this person"), this, SLOT(chatIdentity())); + + if(own_identities.empty()) + action->setEnabled(false) ; + else + action->setData(QString::fromStdString((own_identities.front()).toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())) ; + } + else + { + QMenu *mnu = contextMnu.addMenu(QIcon(":/images/chat_24.png"),tr("Chat with this person as...")) ; + + for(std::list::const_iterator it=own_identities.begin();it!=own_identities.end();++it) + { + RsIdentityDetails idd ; + rsIdentity->getIdDetails(*it,idd) ; + + QPixmap pixmap ; + + if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG")) + pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ; + + QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity())); + action->setData(QString::fromStdString((*it).toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())) ; + } + } + + QAction *actionsendmsg = contextMnu.addAction(QIcon(":/images/mail_new.png"), tr("Send message to this person"), this, SLOT(sendMessage())); + actionsendmsg->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())); + + contextMnu.addSeparator(); + + QAction *actionDetails = contextMnu.addAction(QIcon(":/images/info16.png"), tr("Person details"), this, SLOT(personDetails())); + actionDetails->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())); contextMnu.exec(QCursor::pos()); }//if (dest) @@ -469,7 +516,7 @@ void PeopleDialog::addToCircleExt() dlg.addMember(idWidget->groupInfo()); }//if((itFound=_gxs_identity_widgets.find(gxs_id)) != _gxs_identity_widgets.end()) - dlg.editExistingId(circle->groupInfo().mGroupId, false); + dlg.editExistingId(circle->groupInfo().mGroupId, false,false); dlg.exec(); }//if((itFound=_ext_circles_widgets.find(groupId)) != _ext_circles_widgets.end()) }//if (action) @@ -498,12 +545,79 @@ void PeopleDialog::addToCircleInt() dlg.addMember(idWidget->keyId(), idWidget->idtype(), idWidget->nickname()); }//if((itFound=_pgp_identity_widgets.find(pgp_id)) != _pgp_identity_widgets.end()) - dlg.editExistingId(circle->groupInfo().mGroupId, false); + dlg.editExistingId(circle->groupInfo().mGroupId, false,false); dlg.exec(); }//if((itFound=_ext_circles_widgets.find(groupId)) != _ext_circles_widgets.end()) }//if (action) } +void PeopleDialog::chatIdentity() +{ + QAction *action = + qobject_cast(QObject::sender()); + if (action) { + QString data = action->data().toString(); + QStringList idList = data.split(";"); + + RsGxsId from_gxs_id = RsGxsId(idList.at(0).toStdString()); + RsGxsId gxs_id = RsGxsId(idList.at(1).toStdString()); + + uint32_t error_code ; + + DistantChatPeerId dpid ; + + if(!rsMsgs->initiateDistantChatConnexion(RsGxsId(gxs_id), from_gxs_id, dpid,error_code)) + QMessageBox::information(NULL, tr("Distant chat cannot work"), QString("%1 %2: %3").arg(tr("Distant chat refused with this person.")).arg(tr("Error code")).arg(error_code)) ; + + } +} + +void PeopleDialog::sendMessage() +{ + QAction *action = + qobject_cast(QObject::sender()); + if (action) { + QString data = action->data().toString(); + + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + RsGxsId gxs_id = RsGxsId(data.toStdString());; + + nMsgDialog->addRecipient(MessageComposer::TO, RsGxsId(gxs_id)); + nMsgDialog->show(); + nMsgDialog->activateWindow(); + + /* window will destroy itself! */ + + } + +} + +void PeopleDialog::personDetails() +{ + QAction *action = + qobject_cast(QObject::sender()); + if (action) { + QString data = action->data().toString(); + + RsGxsId gxs_id = RsGxsId(data.toStdString()); + + if (RsGxsGroupId(gxs_id).isNull()) { + return; + } + + IdDetailsDialog *dialog = new IdDetailsDialog(RsGxsGroupId(gxs_id)); + dialog->show(); + + /* Dialog will destroy itself */ + + } + +} + void PeopleDialog::cw_askForGXSIdentityWidget(RsGxsId gxs_id) { CircleWidget *dest = @@ -607,7 +721,7 @@ void PeopleDialog::fl_flowLayoutItemDroppedExt(QListflListItem if (bCreateNewCircle){ dlg.editNewId(true); } else {//if (bCreateNewCircle) - dlg.editExistingId(cirDest->groupInfo().mGroupId, false); + dlg.editExistingId(cirDest->groupInfo().mGroupId, false,false); }//else (bCreateNewCircle) dlg.exec(); @@ -667,7 +781,7 @@ void PeopleDialog::fl_flowLayoutItemDroppedInt(QListflListItem if (bCreateNewCircle){ dlg.editNewId(false); } else {//if (bCreateNewCircle) - dlg.editExistingId(cirDest->groupInfo().mGroupId, false); + dlg.editExistingId(cirDest->groupInfo().mGroupId, false,false); }//else (bCreateNewCircle) dlg.exec(); @@ -768,7 +882,7 @@ void PeopleDialog::pf_dropEventOccursExt(QDropEvent *event) QWidget *wid = qobject_cast(event->source());//QT5 return QObject - FlowLayout *layout = NULL; + FlowLayout *layout; if (wid) layout = qobject_cast(wid->layout()); if (layout) { @@ -808,7 +922,7 @@ void PeopleDialog::pf_dropEventOccursExt(QDropEvent *event) if (bCreateNewCircle){ dlg.editNewId(true); } else {//if (bCreateNewCircle) - dlg.editExistingId(cirDest->groupInfo().mGroupId, false); + dlg.editExistingId(cirDest->groupInfo().mGroupId, false,false); }//else (bCreateNewCircle) dlg.exec(); @@ -858,7 +972,7 @@ void PeopleDialog::pf_dropEventOccursInt(QDropEvent *event) QWidget *wid = qobject_cast(event->source());//QT5 return QObject - FlowLayout *layout = NULL; + FlowLayout *layout; if (wid) layout = qobject_cast(wid->layout()); if (layout) { @@ -898,7 +1012,7 @@ void PeopleDialog::pf_dropEventOccursInt(QDropEvent *event) if (bCreateNewCircle){ dlg.editNewId(false); } else {//if (bCreateNewCircle) - dlg.editExistingId(cirDest->groupInfo().mGroupId, false); + dlg.editExistingId(cirDest->groupInfo().mGroupId, false,false); }//else (bCreateNewCircle) dlg.exec(); diff --git a/retroshare-gui/src/gui/People/PeopleDialog.h b/retroshare-gui/src/gui/People/PeopleDialog.h index 977abf30b..dfb26f2d3 100644 --- a/retroshare-gui/src/gui/People/PeopleDialog.h +++ b/retroshare-gui/src/gui/People/PeopleDialog.h @@ -1,105 +1,109 @@ -/* - * Retroshare Identity. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#pragma once - -#include - -#include - -#include "gui/People/CircleWidget.h" -#include "gui/People/IdentityWidget.h" -#include "gui/gxs/RsGxsUpdateBroadcastPage.h" -#include "util/TokenQueue.h" - -#include "ui_PeopleDialog.h" - -#define IMAGE_IDENTITY ":/icons/friends_128.png" - -class PeopleDialog : public RsGxsUpdateBroadcastPage, public Ui::PeopleDialog, public TokenResponse -{ - Q_OBJECT - - public: - static const uint32_t PD_IDLIST ; - static const uint32_t PD_IDDETAILS ; - static const uint32_t PD_REFRESH ; - static const uint32_t PD_CIRCLES ; - - PeopleDialog(QWidget *parent = 0); - ~PeopleDialog(); - - virtual QIcon iconPixmap() const { return QIcon(IMAGE_IDENTITY) ; } //MainPage - virtual QString pageName() const { return tr("People") ; } //MainPage - virtual QString helpText() const { return ""; } //MainPage - - void loadRequest(const TokenQueue * /*queue*/, const TokenRequest &req) ; - - void requestIdList() ; - void requestCirclesList() ; - - void insertIdList(uint32_t token) ; - void insertCircles(uint32_t token) ; - - protected: - // Derives from RsGxsUpdateBroadcastPage - virtual void updateDisplay(bool complete); - //End RsGxsUpdateBroadcastPage - -private slots: - void iw_AddButtonClickedExt(); - void iw_AddButtonClickedInt(); - void addToCircleExt(); - void addToCircleInt(); - void cw_askForGXSIdentityWidget(RsGxsId gxs_id); - void cw_askForPGPIdentityWidget(RsPgpId pgp_id); - void cw_imageUpdatedExt(); - void cw_imageUpdatedInt(); - void fl_flowLayoutItemDroppedExt(QList flListItem, bool &bAccept); - void fl_flowLayoutItemDroppedInt(QList flListItem, bool &bAccept); - void pf_centerIndexChanged(int index); - void pf_mouseMoveOverSlideEvent(QMouseEvent* event, int slideIndex); - void pf_dragEnterEventOccurs(QDragEnterEvent *event); - void pf_dragMoveEventOccurs(QDragMoveEvent *event); - void pf_dropEventOccursExt(QDropEvent *event); - void pf_dropEventOccursInt(QDropEvent *event); - -private: - void reloadAll(); - void populatePictureFlowExt(); - void populatePictureFlowInt(); - - TokenQueue *mIdentityQueue; - TokenQueue *mCirclesQueue; - - FlowLayout *_flowLayoutExt; - std::map _gxs_identity_widgets ; - std::map _ext_circles_widgets ; - QList _extListCir; - - FlowLayout *_flowLayoutInt; - std::map _pgp_identity_widgets ; - std::map _int_circles_widgets ; - QList _intListCir; -}; - +/* + * Retroshare Identity. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#pragma once + +#include + +#include + +#include "gui/People/CircleWidget.h" +#include "gui/People/IdentityWidget.h" +#include "gui/gxs/RsGxsUpdateBroadcastPage.h" +#include "util/TokenQueue.h" + +#include "ui_PeopleDialog.h" + +#define IMAGE_IDENTITY ":/icons/friends_128.png" + +class PeopleDialog : public RsGxsUpdateBroadcastPage, public Ui::PeopleDialog, public TokenResponse +{ + Q_OBJECT + + public: + static const uint32_t PD_IDLIST ; + static const uint32_t PD_IDDETAILS ; + static const uint32_t PD_REFRESH ; + static const uint32_t PD_CIRCLES ; + + PeopleDialog(QWidget *parent = 0); + ~PeopleDialog(); + + virtual QIcon iconPixmap() const { return QIcon(IMAGE_IDENTITY) ; } //MainPage + virtual QString pageName() const { return tr("People") ; } //MainPage + virtual QString helpText() const { return ""; } //MainPage + + void loadRequest(const TokenQueue * /*queue*/, const TokenRequest &req) ; + + void requestIdList() ; + void requestCirclesList() ; + + void insertIdList(uint32_t token) ; + void insertCircles(uint32_t token) ; + + protected: + // Derives from RsGxsUpdateBroadcastPage + virtual void updateDisplay(bool complete); + //End RsGxsUpdateBroadcastPage + +private slots: + void iw_AddButtonClickedExt(); + void iw_AddButtonClickedInt(); + void addToCircleExt(); + void addToCircleInt(); + void cw_askForGXSIdentityWidget(RsGxsId gxs_id); + void cw_askForPGPIdentityWidget(RsPgpId pgp_id); + void cw_imageUpdatedExt(); + void cw_imageUpdatedInt(); + void fl_flowLayoutItemDroppedExt(QList flListItem, bool &bAccept); + void fl_flowLayoutItemDroppedInt(QList flListItem, bool &bAccept); + void pf_centerIndexChanged(int index); + void pf_mouseMoveOverSlideEvent(QMouseEvent* event, int slideIndex); + void pf_dragEnterEventOccurs(QDragEnterEvent *event); + void pf_dragMoveEventOccurs(QDragMoveEvent *event); + void pf_dropEventOccursExt(QDropEvent *event); + void pf_dropEventOccursInt(QDropEvent *event); + + void chatIdentity(); + void sendMessage(); + void personDetails(); + +private: + void reloadAll(); + void populatePictureFlowExt(); + void populatePictureFlowInt(); + + TokenQueue *mIdentityQueue; + TokenQueue *mCirclesQueue; + + FlowLayout *_flowLayoutExt; + std::map _gxs_identity_widgets ; + std::map _ext_circles_widgets ; + QList _extListCir; + + FlowLayout *_flowLayoutInt; + std::map _pgp_identity_widgets ; + std::map _int_circles_widgets ; + QList _intListCir; +}; + diff --git a/retroshare-gui/src/gui/People/PeopleDialog.ui b/retroshare-gui/src/gui/People/PeopleDialog.ui index 514217d1f..bf5b7239f 100644 --- a/retroshare-gui/src/gui/People/PeopleDialog.ui +++ b/retroshare-gui/src/gui/People/PeopleDialog.ui @@ -1,265 +1,259 @@ - - - PeopleDialog - - - - 0 - 0 - 727 - 524 - - - - - 0 - 0 - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::Box - - - QFrame::Sunken - - - - 2 - - - - - - 0 - 0 - - - - - 24 - 24 - - - - - - - :/images/identity/identities_32.png - - - true - - - - - - - People - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - - - - - 0 - 0 - - - - External - - - - - - Qt::Vertical - - - - - 0 - 250 - - - - true - - - - - 0 - 0 - 685 - 248 - - - - - - - - - - - - 0 - 0 - - - - Drag your circles or people to each other. - - - Qt::AlignCenter - - - - - - - true - - - - - - - - - - - - - 0 - 0 - - - - Internal - - - - - - Qt::Vertical - - - - - 0 - 250 - - - - true - - - - - 0 - 0 - 685 - 248 - - - - - - - - - - - - 0 - 0 - - - - Drag your circles or people to each other. - - - Qt::AlignCenter - - - - - - - true - - - - - - - - - - - - - - - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
- - PictureFlow - QWidget -
gui/common/PictureFlow.h
- 1 -
- - FlowLayoutWidget - QWidget -
gui/common/FlowLayout.h
- 1 -
-
- - - - -
+ + + PeopleDialog + + + + 0 + 0 + 727 + 524 + + + + + 0 + 0 + + + + + + + + 0 + + + + + QFrame::Box + + + QFrame::Sunken + + + + 2 + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + + + :/images/identity/identities_32.png + + + true + + + + + + + People + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + true + + + 1 + + + + + 0 + 0 + + + + People + + + + + + Qt::Vertical + + + + + 0 + 250 + + + + true + + + + + 0 + 0 + 701 + 248 + + + + + + + + + + + + 0 + 0 + + + + Drag your circles or people to each other. + + + Qt::AlignCenter + + + + + + + true + + + + + + + + + + + + + 0 + 0 + + + + Internal + + + + + + Qt::Vertical + + + + + 0 + 250 + + + + true + + + + + 0 + 0 + 701 + 248 + + + + + + + + + + + + 0 + 0 + + + + Drag your circles or people to each other. + + + Qt::AlignCenter + + + + + + + true + + + + + + + + + + + + + + + + StyledLabel + QLabel +
gui/common/StyledLabel.h
+
+ + PictureFlow + QWidget +
gui/common/PictureFlow.h
+ 1 +
+ + FlowLayoutWidget + QWidget +
gui/common/FlowLayout.h
+ 1 +
+
+ + + + +
diff --git a/retroshare-gui/src/gui/common/PictureFlow.cpp b/retroshare-gui/src/gui/common/PictureFlow.cpp index 4f6287ea2..9087ad3a5 100644 --- a/retroshare-gui/src/gui/common/PictureFlow.cpp +++ b/retroshare-gui/src/gui/common/PictureFlow.cpp @@ -293,8 +293,9 @@ PictureFlowState::PictureFlowState(): PictureFlowState::~PictureFlowState() { - for(int i = 0; i < (int)slideImages.count(); ++i) - delete slideImages[i]; + for(uint i=0;isize(); @@ -687,7 +689,7 @@ QImage* PictureFlowSoftwareRenderer::surface(int slideIndex) bool empty = img ? img->isNull() : true; if(empty) { surfaceCache.remove(key); - imageHash.remove(slideIndex); + delete imageHash.take(slideIndex); if(!blankSurface) { int sw = state->slideWidth; int sh = state->slideHeight; @@ -723,29 +725,28 @@ QImage* PictureFlowSoftwareRenderer::surface(int slideIndex) return blankSurface; }//if(empty) +#ifdef PICTUREFLOW_QT2 + if(img == imageHash[slideIndex]) +#endif +#ifdef PICTUREFLOW_QT3 + bool exist = imageHash.find(slideIndex) != imageHash.end(); + if(exist) + if(img == imageHash.find(slideIndex).data()) +#endif #ifdef PICTUREFLOW_QT4 bool exist = imageHash.contains(slideIndex); if(exist) if(img == imageHash.find(slideIndex).value()) #endif -#ifdef PICTUREFLOW_QT3 - bool exist = imageHash.find(slideIndex) != imageHash.end(); - if(exist) - if(img == imageHash.find(slideIndex).data()) -#endif -#ifdef PICTUREFLOW_QT2 - if(img == imageHash[slideIndex]) -#endif - if(surfaceCache.contains(key)) - return surfaceCache[key]; + if(surfaceCache.contains(key)) + return surfaceCache[key]; - QImage* sr = prepareSurface(img, state->slideWidth, state->slideHeight, bgcolor, state->reflectionEffect); - QImage *sr_copy = new QImage(*sr) ; + QImage* sr = prepareSurface(img, state->slideWidth, state->slideHeight, bgcolor, state->reflectionEffect); - surfaceCache.insert(key, sr); // this takes ownership on sr. So we can't use it afterwards + surfaceCache.insert(key, sr); // QCache takes ownership on sr. And delete it when removed. imageHash.insert(slideIndex, img); - return sr_copy; + return sr; } // Renders a slide to offscreen buffer. Returns a rect of the rendered area. @@ -756,7 +757,7 @@ QRect PictureFlowSoftwareRenderer::renderSlide(const SlideInfo &slide, int col1, if(!blend) return QRect(); - QImage* src = surface(slide.slideIndex); + QImage* src = surface(slide.slideIndex); // src is owned by surfaceCache(QCache) don't delete it. if(!src) return QRect(); @@ -787,11 +788,8 @@ QRect PictureFlowSoftwareRenderer::renderSlide(const SlideInfo &slide, int col1, PFreal dist = distance * PFREAL_ONE; int xi = qMax((PFreal)0, ((w*PFREAL_ONE/2) + fdiv(xs*h, dist+ys)) >> PFREAL_SHIFT); - if(xi >= w) - { - delete src ; - return rect; - } + if(xi >= w) + return rect; bool flag = false; rect.setLeft(xi); @@ -860,8 +858,7 @@ QRect PictureFlowSoftwareRenderer::renderSlide(const SlideInfo &slide, int col1, }//for(int x = qMax(xi, col1); x <= col2; ++x) rect.setTop(0); - rect.setBottom(h-1); - delete src ; + rect.setBottom(h-1); return rect; } @@ -1107,11 +1104,10 @@ void PictureFlow::setCenterIndex(int index) void PictureFlow::clear() { - int c = d->state->slideImages.count(); - for(int i = 0; i < c; ++i) - delete d->state->slideImages[i]; - d->state->slideImages.resize(0); - + for(uint i=0;istate->slideImages.size();++i) + delete d->state->slideImages[i] ; + d->state->slideImages.clear() ; + d->state->reset(); triggerRender(); } diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp index 353f509c0..2eb3dd72c 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp @@ -103,7 +103,7 @@ void GxsGroupDialog::init() connect(ui.addLogoButton, SIGNAL(clicked() ), this , SLOT(addGroupLogo())); ui.typePublic->setChecked(true); - ui.typePublic_3->setChecked(true); + ui.distributionValueLabel->setText(tr("Public")); updateCircleOptions(); connect(ui.typePublic, SIGNAL(clicked()), this , SLOT(updateCircleOptions())); @@ -218,23 +218,25 @@ void GxsGroupDialog::setupDefaults() if (mDefaultsFlags & GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC) { ui.typePublic->setChecked(true); - ui.typePublic_3->setChecked(true); + ui.distributionValueLabel->setText(tr("Public")); + ui.distributionCircleComboBox->setVisible(false) ; } else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_DISTRIB_GROUP) { ui.typeGroup->setChecked(true); - ui.typeGroup_3->setChecked(true); + ui.distributionValueLabel->setText(tr("Restricted to circle:")); + ui.distributionCircleComboBox->setVisible(true) ; } else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_DISTRIB_LOCAL) { ui.typeLocal->setChecked(true); - ui.typeLocal_3->setChecked(true); + ui.distributionValueLabel->setText(tr("Limited to your friends")); + ui.distributionCircleComboBox->setVisible(false) ; } else { // default ui.typePublic->setChecked(true); - ui.typePublic_3->setChecked(true); } } @@ -285,31 +287,36 @@ void GxsGroupDialog::setupDefaults() if (mDefaultsFlags & GXS_GROUP_DEFAULTS_COMMENTS_YES) { ui.comments_allowed->setChecked(true); - ui.comments_allowed_3->setChecked(true); + ui.commentsValueLabel->setText(tr("Allowed")); } else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_COMMENTS_NO) { ui.comments_no->setChecked(true); - ui.comments_no_3->setChecked(true); + ui.commentsValueLabel->setText(tr("Disallowed")); } else { // default ui.comments_no->setChecked(true); - ui.comments_no_3->setChecked(true); + ui.commentsValueLabel->setText(tr("Allowed")); } } ui.antiSpam_trackMessages->setChecked((bool)(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_TRACK)); ui.antiSpam_signedIds->setChecked((bool)(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_FAVOR_PGP)); - ui.antiSpam_trackMessages_2->setChecked((bool)(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_TRACK)); - ui.antiSpam_signedIds_2->setChecked((bool)(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_FAVOR_PGP)); + + QString antispam_string ; + if(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_TRACK) antispam_string += tr("Message tracking") ; + if(mDefaultsFlags & GXS_GROUP_DEFAULTS_ANTISPAM_FAVOR_PGP) antispam_string += (antispam_string.isNull()?"":" and ")+tr("PGP signature required") ; + + ui.antiSpamValueLabel->setText(antispam_string) ; #ifndef RS_USE_CIRCLES ui.typeGroup->setEnabled(false); - ui.typeLocal->setEnabled(false); ui.typeGroup_3->setEnabled(false); ui.typeLocal_3->setEnabled(false); #endif + ui.typeLocal->setEnabled(false); // for now, since local circles not fully tested. + ui.typeLocal->setToolTip(tr("This feature is not yet available, but it will be available very soon!")); // for now, since local circles not fully tested. } void GxsGroupDialog::setupVisibility() @@ -322,10 +329,12 @@ void GxsGroupDialog::setupVisibility() ui.groupDesc->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DESCRIPTION); ui.distribGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DISTRIBUTION); - ui.distribGroupBox_2->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DISTRIBUTION); + ui.distributionLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DISTRIBUTION); + ui.distributionValueLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DISTRIBUTION); ui.spamProtection_GB->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ANTI_SPAM); - ui.spamProtection_GB_2->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ANTI_SPAM); + ui.antiSpamLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ANTI_SPAM); + ui.antiSpamValueLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ANTI_SPAM); ui.publishGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_PUBLISHSIGN); @@ -334,8 +343,9 @@ void GxsGroupDialog::setupVisibility() ui.personalGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_PERSONALSIGN); ui.commentGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_COMMENTS); - ui.commentGroupBox_2->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_COMMENTS); - ui.commentslabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_COMMENTS); + ui.commentsLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_COMMENTS); + ui.commentsValueLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_COMMENTS); + //ui.commentslabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_COMMENTS); ui.extraFrame->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_EXTRA); } @@ -363,10 +373,10 @@ void GxsGroupDialog::setupReadonly() ui.idChooser->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_PERSONALSIGN)); - ui.distribGroupBox_2->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_DISTRIBUTION)); - ui.commentGroupBox_2->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_COMMENTS)); + //ui.distribGroupBox_2->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_DISTRIBUTION)); + //ui.commentGroupBox_2->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_COMMENTS)); ui.spamProtection_GB->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_ANTI_SPAM)); - ui.spamProtection_GB_2->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_ANTI_SPAM)); + //ui.spamProtection_GB_2->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_ANTI_SPAM)); ui.extraFrame->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_EXTRA)); #ifndef UNFINISHED @@ -417,9 +427,8 @@ void GxsGroupDialog::updateFromExistingMeta(const QString &description) break; case MODE_SHOW:{ ui.headerFrame->setHeaderText(QString::fromUtf8(mGrpMeta.mGroupName.c_str())); - if (mPicture.isNull()) - return; - ui.headerFrame->setHeaderImage(mPicture); + if (!mPicture.isNull()) + ui.headerFrame->setHeaderImage(mPicture); } break; case MODE_EDIT:{ @@ -428,21 +437,27 @@ void GxsGroupDialog::updateFromExistingMeta(const QString &description) } /* set description */ ui.groupDesc->setPlainText(description); + QString distribution_string = "[Unknown]"; switch(mGrpMeta.mCircleType) { case GXS_CIRCLE_TYPE_YOUREYESONLY: ui.typeLocal->setChecked(true); - ui.typeLocal_3->setChecked(true); + distribution_string = tr("Your friends only") ; ui.localComboBox->loadCircles(GXS_CIRCLE_CHOOSER_PERSONAL, mGrpMeta.mInternalCircle); + ui.distributionCircleComboBox->setVisible(true) ; + ui.distributionCircleComboBox->loadCircles(GXS_CIRCLE_CHOOSER_PERSONAL, mGrpMeta.mInternalCircle); break; case GXS_CIRCLE_TYPE_PUBLIC: ui.typePublic->setChecked(true); - ui.typePublic_3->setChecked(true); + distribution_string = tr("Public") ; + ui.distributionCircleComboBox->setVisible(false) ; break; case GXS_CIRCLE_TYPE_EXTERNAL: ui.typeGroup->setChecked(true); - ui.typeGroup_3->setChecked(true); + distribution_string = tr("Restricted to circle:") ; + ui.distributionCircleComboBox->setVisible(true) ; + ui.distributionCircleComboBox->loadCircles(GXS_CIRCLE_CHOOSER_EXTERNAL, mGrpMeta.mCircleId); ui.circleComboBox->loadCircles(GXS_CIRCLE_CHOOSER_EXTERNAL, mGrpMeta.mCircleId); break; default: @@ -450,6 +465,7 @@ void GxsGroupDialog::updateFromExistingMeta(const QString &description) std::cerr << std::endl; break; } + ui.distributionValueLabel->setText(distribution_string) ; ui.idChooser->loadIds(0, mGrpMeta.mAuthorId); @@ -642,8 +658,14 @@ void GxsGroupDialog::setGroupSignFlags(uint32_t signFlags) ui.antiSpam_trackMessages ->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); ui.antiSpam_signedIds ->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); - ui.antiSpam_trackMessages_2->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); - ui.antiSpam_signedIds_2 ->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); + + QString antispam_string ; + if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) antispam_string += tr("Message tracking") ; + if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) antispam_string += (antispam_string.isNull()?"":" and ")+tr("PGP signature required") ; + + ui.antiSpamValueLabel->setText(antispam_string) ; + //ui.antiSpam_trackMessages_2->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); + //ui.antiSpam_signedIds_2 ->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); //ui.SignEdIds->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); //ui.trackmessagesradioButton->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); @@ -651,13 +673,15 @@ void GxsGroupDialog::setGroupSignFlags(uint32_t signFlags) if ((signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD) && (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN)) { + // (cyril) very weird piece of code. Need to clear this up. + ui.comments_allowed->setChecked(true); - ui.comments_allowed_3->setChecked(true); + ui.commentsValueLabel->setText("Allowed") ; } else { ui.comments_no->setChecked(true); - ui.comments_no_3->setChecked(true); + ui.commentsValueLabel->setText("Allowed") ; } } diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui index 4e2cb03bd..0c6d5074f 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui @@ -7,31 +7,22 @@ 0 0 928 - 400 + 769
Create New - - 0 - - - 0 - - - 0 - - - 0 - 6 0 + + 0 + @@ -44,7 +35,7 @@ QFrame::Raised - 0 + 1 @@ -57,16 +48,7 @@ 0 - - 4 - - - 4 - - - 4 - - + 4 @@ -130,16 +112,7 @@ 9 - - 3 - - - 3 - - - 3 - - + 3 @@ -239,16 +212,7 @@ - - 0 - - - 0 - - - 0 - - + 0 @@ -635,188 +599,12 @@ - - - - Description - - - - - - true - - - - - - Info - - - - - - 0 - 0 - - - - - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - - 0 - 0 - - - - Restricted to Group - - - - :/images/user/agt_forum24.png:/images/user/agt_forum24.png - - - - 16 - 16 - - - - - - - - - 0 - 0 - - - - Public - - - - :/images/network.png:/images/network.png - - - - 16 - 16 - - - - - - - - - 0 - 0 - - - - Only For Your Friends - - - - :/images/user/friends24.png:/images/user/friends24.png - - - - 16 - 16 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - 6 - - - 6 - - - 6 - - - 6 - - - 6 - - - - - Comments allowed - - - - - - - Comments not allowed - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - + @@ -824,48 +612,13 @@ - + true - - - - true - - - - - - - true - - - - - - - true - - - - - - - ID - - - - - - - Last Post - - - @@ -873,11 +626,8 @@ - - - - - + + true @@ -890,20 +640,27 @@ - - + + - Comments + + + + true - - + + - Type + Last Post - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + true @@ -914,66 +671,97 @@ - + GxsIdLabel - - + + - Anti spam + ID - - - - + + + + true + + + + + + + Comments: + + + + + + + TextLabel + + + + + + + + + TextLabel + + + + + + + + 0 + 0 + + + + + + + + + + Distribution: + + + + + + + Anti Spam: + + + + + + + TextLabel + + + + + + + + + + Description + + + + + + true - - - 6 - - - 6 - - - 6 - - - 6 - - - - - PGP-signed ids - - - - - - - Track of Posts - - - - - - - Qt::Horizontal - - - - 718 - 20 - - - - - diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp index f0f6708b5..ea54de337 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp @@ -60,6 +60,7 @@ GxsIdChooser::GxsIdChooser(QWidget *parent) setSizeAdjustPolicy(QComboBox::AdjustToContents); mFirstLoad = true; + mAllowedCount = 0 ; mDefaultId.clear() ; @@ -99,6 +100,13 @@ void GxsIdChooser::showEvent(QShowEvent *event) QComboBox::showEvent(event); } +void GxsIdChooser::setIdConstraintSet(const std::set& s) +{ + mConstraintIdsSet = s ; + + updateDisplay(true); + update(); // Qt flush +} void GxsIdChooser::loadIds(uint32_t chooserFlags, const RsGxsId &defId) { mFlags = chooserFlags; @@ -118,6 +126,7 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail if (!chooser) { return; } + // this prevents the objects that depend on what's in the combo-box to activate and // perform any change.Only user-changes should cause this. @@ -167,30 +176,69 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail //std::cerr << " - disabling ID - entry = " << index << std::endl; chooser->setEntryEnabled(index,false) ; } - std::cerr << std::endl; - + + if(!chooser->isInConstraintSet(details.mId)) + chooser->setEntryEnabled(index,false) ; + chooser->model()->sort(0); chooser->blockSignals(false) ; } +bool GxsIdChooser::isInConstraintSet(const RsGxsId& id) const +{ + if(mConstraintIdsSet.empty()) // special case: empty set means no constraint + return true ; + + return mConstraintIdsSet.find(id) != mConstraintIdsSet.end() ; +} void GxsIdChooser::setEntryEnabled(int indx,bool enabled) { - bool disable = !enabled ; + removeItem(indx) ; - QSortFilterProxyModel* model = qobject_cast(QComboBox::model()); - //QStandardItem* item = model->item(index); +#ifdef TO_REMOVE +// bool disable = !enabled ; +// +// QSortFilterProxyModel* model = qobject_cast(QComboBox::model()); +// //QStandardItem* item = model->item(index); +// +// QModelIndex ii = model->index(indx,0); +// +// // visually disable by greying out - works only if combobox has been painted already and palette returns the wanted color +// //model->setFlags(ii,disable ? (model->flags(ii) & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)) : (Qt::ItemIsSelectable|Qt::ItemIsEnabled)); +// +// uint32_t v = enabled?(1|32):(0); +// +// std::cerr << "GxsIdChooser::setEnabledEntry: i=" << indx << ", v=" << v << std::endl; +// +// // clear item data in order to use default color +// //model->setData(ii,disable ? (QComboBox::palette().color(QPalette::Disabled, QPalette::Text)) : QVariant(), Qt::TextColorRole); +// model->setData(ii,QVariant(v),Qt::UserRole-1) ; +// +// std::cerr << "model data after operation: " << model->data(ii,Qt::UserRole-1).toUInt() << std::endl; +#endif +} + +uint32_t GxsIdChooser::countEnabledEntries() const +{ + return count() ; - QModelIndex ii = model->index(indx,0); - - // visually disable by greying out - works only if combobox has been painted already and palette returns the wanted color - //model->setFlags(ii,disable ? (model->flags(ii) & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)) : (Qt::ItemIsSelectable|Qt::ItemIsEnabled)); - - uint32_t v = enabled?(1|32):(0); - - // clear item data in order to use default color - //model->setData(ii,disable ? (QComboBox::palette().color(QPalette::Disabled, QPalette::Text)) : QVariant(), Qt::TextColorRole); - model->setData(ii,QVariant(v),Qt::UserRole-1) ; +#ifdef TO_REMOVE +// uint32_t res = 0 ; +// QSortFilterProxyModel* model = qobject_cast(QComboBox::model()); +// +// for(uint32_t i=0;irowCount();++i) +// { +// QModelIndex ii = model->index(i,0); +// uint32_t v = model->data(ii,Qt::UserRole-1).toUInt() ; +// +// std::cerr << "GxsIdChooser::countEnabledEntries(): i=" << i << ", v=" << v << std::endl; +// if(v > 0) +// ++res ; +// } +// +// return res ; +#endif } void GxsIdChooser::loadPrivateIds() @@ -238,8 +286,7 @@ void GxsIdChooser::loadPrivateIds() } for (std::list::iterator it = ids.begin(); it != ids.end(); ++it) { - /* add to Chooser */ - GxsIdDetails::process(*it, loadPrivateIdsCallback, this); + GxsIdDetails::process(*it, loadPrivateIdsCallback, this); /* add to Chooser */ } if (mFirstLoad) { diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.h b/retroshare-gui/src/gui/gxs/GxsIdChooser.h index 98c33a052..8e339508d 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.h +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.h @@ -58,7 +58,12 @@ public: bool setChosenId(const RsGxsId &gxsId); ChosenId_Ret getChosenId(RsGxsId &gxsId); - void setEntryEnabled(int index, bool enabled); + void setEntryEnabled(int index, bool enabled); + + void setIdConstraintSet(const std::set& s) ; + bool isInConstraintSet(const RsGxsId& id) const ; + + uint32_t countEnabledEntries() const ; signals: // emitted after first load of own ids void idsLoaded(); @@ -79,7 +84,9 @@ private: uint32_t mFlags; RsGxsId mDefaultId; bool mFirstLoad; + uint32_t mAllowedCount ; + std::set mConstraintIdsSet ; // leave empty if all allowed RsGxsUpdateBroadcastBase *mBase; }; diff --git a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp index a3af87db4..6898ce228 100644 --- a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp @@ -28,6 +28,7 @@ #include #include +#include #include "gui/settings/rsharesettings.h" #include "gui/RetroShareLink.h" @@ -43,6 +44,7 @@ #define CREATEGXSFORUMMSG_FORUMINFO 1 #define CREATEGXSFORUMMSG_PARENTMSG 2 +#define CREATEGXSFORUMMSG_CIRCLENFO 3 //#define ENABLE_GENERATE @@ -57,6 +59,7 @@ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessage /* Setup Queue */ mForumQueue = new TokenQueue(rsGxsForums->getTokenService(), this); + mCirclesQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); /* Setup UI helper */ mStateHelper = new UIStateHelper(this); @@ -100,6 +103,7 @@ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessage mParentMsgLoaded = false; mForumMetaLoaded = false; + mForumCircleLoaded = false; newMsg(); @@ -112,6 +116,7 @@ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessage CreateGxsForumMsg::~CreateGxsForumMsg() { delete(mForumQueue); + delete(mCirclesQueue); } void CreateGxsForumMsg::newMsg() @@ -121,7 +126,8 @@ void CreateGxsForumMsg::newMsg() mForumMetaLoaded = false; /* fill in the available OwnIds for signing */ - std::cerr << "Initing ID chooser. Sign flags = " << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; + + //std::cerr << "Initing ID chooser. Sign flags = " << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, RsGxsId()); @@ -143,8 +149,7 @@ void CreateGxsForumMsg::newMsg() std::list groupIds; groupIds.push_back(mForumId); - std::cerr << "ForumsV2Dialog::newMsg() Requesting Group Summary(" << mForumId << ")"; - std::cerr << std::endl; + //std::cerr << "ForumsV2Dialog::newMsg() Requesting Group Summary(" << mForumId << ")"<< std::endl; uint32_t token; mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEGXSFORUMMSG_FORUMINFO); @@ -163,8 +168,8 @@ void CreateGxsForumMsg::newMsg() std::vector &vect = msgIds[mForumId]; vect.push_back(mParentId); - std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")"; - std::cerr << std::endl; + //std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")"; + //std::cerr << std::endl; uint32_t token; mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_PARENTMSG); @@ -178,8 +183,8 @@ void CreateGxsForumMsg::loadFormInformation() mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true); mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false); } else { - std::cerr << "CreateGxsForumMsg::loadMsgInformation() ParentMsg not Loaded Yet"; - std::cerr << std::endl; + //std::cerr << "CreateGxsForumMsg::loadMsgInformation() ParentMsg not Loaded Yet"; + //std::cerr << std::endl; mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, false); @@ -194,18 +199,18 @@ void CreateGxsForumMsg::loadFormInformation() mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, true); mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, false); } else { - std::cerr << "CreateGxsForumMsg::loadMsgInformation() ForumMeta not Loaded Yet"; - std::cerr << std::endl; + //std::cerr << "CreateGxsForumMsg::loadMsgInformation() ForumMeta not Loaded Yet"; + //std::cerr << std::endl; mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); return; } - std::cerr << "CreateGxsForumMsg::loadMsgInformation() Data Available!"; - std::cerr << std::endl; + //std::cerr << "CreateGxsForumMsg::loadMsgInformation() Data Available!"; + //std::cerr << std::endl; - std::cerr << "CreateGxsForumMsg::loadMsgInformation() using signFlags=" << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; + //std::cerr << "CreateGxsForumMsg::loadMsgInformation() using signFlags=" << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; if(mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ui.idChooser->setFlags(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NON_ANONYMOUS) ; @@ -297,39 +302,39 @@ void CreateGxsForumMsg::createMsg() if (ui.signBox->isChecked()) { RsGxsId authorId; switch (ui.idChooser->getChosenId(authorId)) { - case GxsIdChooser::KnowId: - case GxsIdChooser::UnKnowId: + case GxsIdChooser::KnowId: + case GxsIdChooser::UnKnowId: msg.mMeta.mAuthorId = authorId; - std::cerr << "CreateGxsForumMsg::createMsg() AuthorId: " << authorId; - std::cerr << std::endl; + //std::cerr << "CreateGxsForumMsg::createMsg() AuthorId: " << authorId; + //std::cerr << std::endl; break; - case GxsIdChooser::None: - { - // This is ONLY for the case where no id exists yet - // If an id exists, the chooser would not return None - IdEditDialog dlg(this); - dlg.setupNewId(false); - dlg.exec(); - // fetch new id, we will then see if the identity creation was successful - std::list own_ids; - if(!rsIdentity->getOwnIds(own_ids) || own_ids.size() != 1) - return; - // we have only a single id, so we can use the first one - authorId = own_ids.front(); - break; - } - case GxsIdChooser::NoId: - default: + case GxsIdChooser::None: + { + // This is ONLY for the case where no id exists yet + // If an id exists, the chooser would not return None + IdEditDialog dlg(this); + dlg.setupNewId(false); + dlg.exec(); + // fetch new id, we will then see if the identity creation was successful + std::list own_ids; + if(!rsIdentity->getOwnIds(own_ids) || own_ids.size() != 1) + return; + // we have only a single id, so we can use the first one + authorId = own_ids.front(); + break; + } + case GxsIdChooser::NoId: + default: std::cerr << "CreateGxsForumMsg::createMsg() ERROR GETTING AuthorId!"; std::cerr << std::endl; - QMessageBox::warning(this, tr("RetroShare"),tr("Congrats, you found a bug!")+" "+QString(__FILE__)+":"+QString(__LINE__), QMessageBox::Ok, QMessageBox::Ok); + QMessageBox::warning(this, tr("RetroShare"),tr("Congrats, you found a bug!")+" "+QString(__FILE__)+":"+QString(__LINE__), QMessageBox::Ok, QMessageBox::Ok); return; }//switch (ui.idChooser->getChosenId(authorId)) } else { - std::cerr << "CreateGxsForumMsg::createMsg() No Signature (for now :)"; - std::cerr << std::endl; + //std::cerr << "CreateGxsForumMsg::createMsg() No Signature (for now :)"; + //std::cerr << std::endl; QMessageBox::warning(this, tr("RetroShare"),tr("Please choose Signing Id, it is required"), QMessageBox::Ok, QMessageBox::Ok); return; }//if (ui.signBox->isChecked()) @@ -408,7 +413,7 @@ void CreateGxsForumMsg::addFile() void CreateGxsForumMsg::fileHashingFinished(QList hashedFiles) { - std::cerr << "CreateGxsForumMsg::fileHashingFinished() started." << std::endl; + //std::cerr << "CreateGxsForumMsg::fileHashingFinished() started." << std::endl; QString mesgString; @@ -431,35 +436,88 @@ void CreateGxsForumMsg::fileHashingFinished(QList hashedFiles) void CreateGxsForumMsg::loadForumInfo(const uint32_t &token) { - std::cerr << "CreateGxsForumMsg::loadForumInfo()"; - std::cerr << std::endl; + //std::cerr << "CreateGxsForumMsg::loadForumInfo()"; + //std::cerr << std::endl; - std::list groupInfo; - rsGxsForums->getGroupSummary(token, groupInfo); + std::list groupInfo; + rsGxsForums->getGroupSummary(token, groupInfo); - if (groupInfo.size() == 1) - { - RsGroupMetaData fi = groupInfo.front(); + if (groupInfo.size() == 1) + { + RsGroupMetaData fi = groupInfo.front(); - mForumMeta = fi; - mForumMetaLoaded = true; + mForumMeta = fi; + mForumMetaLoaded = true; - loadFormInformation(); - } - else - { - std::cerr << "CreateGxsForumMsg::loadForumInfo() ERROR INVALID Number of Forums"; - std::cerr << std::endl; + if(!fi.mCircleId.isNull()) + { + //std::cerr << "Circle ID is not null: " << fi.mCircleId << ": loading circle info to add constraint to the GXS ID chooser." << std::endl; - mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); - mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, false); - } + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::list groupIds; + groupIds.push_back(RsGxsGroupId(fi.mCircleId)); + uint32_t _token; + + mCirclesQueue->requestGroupInfo(_token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, CREATEGXSFORUMMSG_CIRCLENFO); + } + + loadFormInformation(); + } + else + { + std::cerr << "CreateGxsForumMsg::loadForumInfo() ERROR INVALID Number of Forums"; + std::cerr << std::endl; + + mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); + mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, false); + } +} +void CreateGxsForumMsg::loadForumCircleInfo(const uint32_t& token) +{ + //std::cerr << "Loading forum circle info" << std::endl; + + std::vector circle_grp_v ; + rsGxsCircles->getGroupData(token, circle_grp_v); + + if (circle_grp_v.empty()) + { + std::cerr << "(EE) unexpected empty result from getGroupData. Cannot process circle now!" << std::endl; + return ; + } + + if (circle_grp_v.size() != 1) + { + std::cerr << "(EE) very weird result from getGroupData. Should get exactly one circle" << std::endl; + return ; + } + + RsGxsCircleGroup cg = circle_grp_v.front(); + + mForumCircleData = cg; + mForumCircleLoaded = true; + + //std::cerr << "Loaded content of circle " << cg.mMeta.mGroupId << std::endl; + + //for(std::set::const_iterator it(cg.mInvitedMembers.begin());it!=cg.mInvitedMembers.end();++it) + // std::cerr << " added constraint to circle element " << *it << std::endl; + + ui.idChooser->setIdConstraintSet(cg.mInvitedMembers) ; + ui.idChooser->setFlags(IDCHOOSER_NO_CREATE | ui.idChooser->flags()) ; // since there's a circle involved, no ID creation can be needed + + RsGxsId tmpid ; + if(ui.idChooser->countEnabledEntries() == 0) + { + QMessageBox::information(NULL,tr("No compatible ID for this forum"),tr("None of your identities is allowed to post in this forum. This could be due to the forum being limited to a circle that contains none of your identities, or forum flags requiring a PGP-signed identity.")) ; + close() ; + } } void CreateGxsForumMsg::loadParentMsg(const uint32_t &token) { - std::cerr << "CreateGxsForumMsg::loadParentMsg()"; - std::cerr << std::endl; + //std::cerr << "CreateGxsForumMsg::loadParentMsg()"; + //std::cerr << std::endl; // Only grab one.... ignore more (shouldn't be any). std::vector msgs; @@ -486,8 +544,8 @@ void CreateGxsForumMsg::loadParentMsg(const uint32_t &token) void CreateGxsForumMsg::loadRequest(const TokenQueue *queue, const TokenRequest &req) { - std::cerr << "CreateGxsForum::loadRequest() UserType: " << req.mUserType; - std::cerr << std::endl; + //std::cerr << "CreateGxsForum::loadRequest() UserType: " << req.mUserType; + //std::cerr << std::endl; if (queue == mForumQueue) { @@ -501,10 +559,23 @@ void CreateGxsForumMsg::loadRequest(const TokenQueue *queue, const TokenRequest loadParentMsg(req.mToken); break; default: - std::cerr << "CreateGxsForum::loadRequest() UNKNOWN UserType "; + std::cerr << "CreateGxsForumMsg::loadRequest() UNKNOWN UserType " << req.mUserType << " for token request in mForumQueue"; std::cerr << std::endl; } } + + if(queue == mCirclesQueue) + { + switch(req.mUserType) + { + case CREATEGXSFORUMMSG_CIRCLENFO: + loadForumCircleInfo(req.mToken) ; + break ; + default: + std::cerr << "CreateGxsForumMsg::loadRequest() UNKNOWN UserType " << req.mUserType << " for token request in mCirclesQueue"; + std::cerr << std::endl; + } + } } void CreateGxsForumMsg::insertPastedText(QString msg) diff --git a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h index cde7f4d77..ae06b0b0c 100644 --- a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h @@ -27,6 +27,7 @@ #include "util/TokenQueue.h" #include +#include class UIStateHelper; @@ -54,22 +55,28 @@ private slots: protected: void closeEvent (QCloseEvent * event); - + private: void loadFormInformation(); void loadForumInfo(const uint32_t &token); void loadParentMsg(const uint32_t &token); + void loadForumCircleInfo(const uint32_t &token); RsGxsGroupId mForumId; + RsGxsCircleId mCircleId ; RsGxsMessageId mParentId; bool mParentMsgLoaded; bool mForumMetaLoaded; + bool mForumCircleLoaded ; RsGxsForumMsg mParentMsg; RsGroupMetaData mForumMeta; + RsGxsCircleGroup mForumCircleData ; TokenQueue *mForumQueue; + TokenQueue *mCirclesQueue; + UIStateHelper *mStateHelper; /** Qt Designer generated object */ diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index b561a119b..4386b9fd7 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -31,6 +31,7 @@ CONFIG += gxsforums CONFIG += gxschannels CONFIG += posted CONFIG += gxsgui +CONFIG += gxscircles # Other Disabled Bits. #CONFIG += framecatcher @@ -1175,6 +1176,7 @@ identities { gxscircles { DEFINES += RS_USE_CIRCLES +# DEFINES += RS_USE_NEW_PEOPLE_DIALOG HEADERS += \ gui/Circles/CirclesDialog.h \ diff --git a/retroshare-gui/src/util/RsGxsUpdateBroadcast.cpp b/retroshare-gui/src/util/RsGxsUpdateBroadcast.cpp index 8df24bc21..cbda167cb 100644 --- a/retroshare-gui/src/util/RsGxsUpdateBroadcast.cpp +++ b/retroshare-gui/src/util/RsGxsUpdateBroadcast.cpp @@ -5,6 +5,8 @@ #include +//#define DEBUG_GXS_BROADCAST 1 + // previously gxs allowed only one event consumer to poll for changes // this required a single broadcast instance per service // now the update notify works through rsnotify and notifyqt @@ -43,8 +45,28 @@ RsGxsUpdateBroadcast *RsGxsUpdateBroadcast::get(RsGxsIfaceHelper *ifaceImpl) void RsGxsUpdateBroadcast::onChangesReceived(const RsGxsChanges& changes) { +#ifdef DEBUG_GXS_BROADCAST + std::cerr << "onChangesReceived()" << std::endl; + + { + std::cerr << "Received changes for service " << (void*)changes.mService << ", expecting service " << (void*)mIfaceImpl->getTokenService() << std::endl; + std::cerr << " changes content: " << std::endl; + for(std::list::const_iterator it(changes.mGrps.begin());it!=changes.mGrps.end();++it) std::cerr << " grp id: " << *it << std::endl; + for(std::list::const_iterator it(changes.mGrpsMeta.begin());it!=changes.mGrpsMeta.end();++it) std::cerr << " grp meta: " << *it << std::endl; + for(std::map >::const_iterator it(changes.mMsgs.begin());it!=changes.mMsgs.end();++it) + for(uint32_t i=0;isecond.size();++i) + std::cerr << " grp id: " << it->first << ". Msg ID " << it->second[i] << std::endl; + for(std::map >::const_iterator it(changes.mMsgsMeta.begin());it!=changes.mMsgsMeta.end();++it) + for(uint32_t i=0;isecond.size();++i) + std::cerr << " grp id: " << it->first << ". Msg Meta " << it->second[i] << std::endl; + } +#endif if(changes.mService != mIfaceImpl->getTokenService()) + { + // std::cerr << "(EE) Incorrect service. Dropping." << std::endl; + return; + } if (!changes.mMsgs.empty() || !changes.mMsgsMeta.empty()) { diff --git a/tests/unittests/libretroshare/gxs/common/data_support.cc b/tests/unittests/libretroshare/gxs/common/data_support.cc index 5800b99b9..4691d9ec3 100644 --- a/tests/unittests/libretroshare/gxs/common/data_support.cc +++ b/tests/unittests/libretroshare/gxs/common/data_support.cc @@ -176,21 +176,21 @@ RsSerialType* init_item(RsNxsMsg& nxm) return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); } -RsSerialType* init_item(RsNxsSyncGrp& rsg) +RsSerialType* init_item(RsNxsSyncGrpReqItem& rsg) { rsg.clear(); - rsg.flag = RsNxsSyncGrp::FLAG_USE_SYNC_HASH; + rsg.flag = RsNxsSyncGrpItem::FLAG_USE_SYNC_HASH; rsg.createdSince = rand()%2423; randString(3124,rsg.syncHash); return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); } -RsSerialType* init_item(RsNxsSyncMsg& rsgm) +RsSerialType* init_item(RsNxsSyncMsgReqItem& rsgm) { rsgm.clear(); - rsgm.flag = RsNxsSyncMsg::FLAG_USE_SYNC_HASH; + rsgm.flag = RsNxsSyncMsgItem::FLAG_USE_SYNC_HASH; rsgm.createdSince = rand()%24232; rsgm.transactionNumber = rand()%23; init_random(rsgm.grpId) ; @@ -223,7 +223,7 @@ RsSerialType* init_item(RsNxsSyncMsgItem& rsgml) return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); } -RsSerialType* init_item(RsNxsTransac& rstx){ +RsSerialType* init_item(RsNxsTransacItem &rstx){ rstx.clear(); @@ -236,7 +236,7 @@ RsSerialType* init_item(RsNxsTransac& rstx){ } -bool operator==(const RsNxsSyncGrp& l, const RsNxsSyncGrp& r) +bool operator==(const RsNxsSyncGrpReqItem& l, const RsNxsSyncGrpReqItem& r) { if(l.syncHash != r.syncHash) return false; @@ -247,7 +247,7 @@ bool operator==(const RsNxsSyncGrp& l, const RsNxsSyncGrp& r) return true; } -bool operator==(const RsNxsSyncMsg& l, const RsNxsSyncMsg& r) +bool operator==(const RsNxsSyncMsgReqItem& l, const RsNxsSyncMsgReqItem& r) { if(l.flag != r.flag) return false; @@ -279,7 +279,7 @@ bool operator==(const RsNxsSyncMsgItem& l, const RsNxsSyncMsgItem& r) return true; } -bool operator==(const RsNxsTransac& l, const RsNxsTransac& r){ +bool operator==(const RsNxsTransacItem& l, const RsNxsTransacItem& r){ if(l.transactFlag != r.transactFlag) return false; if(l.transactionNumber != r.transactionNumber) return false; diff --git a/tests/unittests/libretroshare/gxs/common/data_support.h b/tests/unittests/libretroshare/gxs/common/data_support.h index 384c6cbb9..ae9919428 100644 --- a/tests/unittests/libretroshare/gxs/common/data_support.h +++ b/tests/unittests/libretroshare/gxs/common/data_support.h @@ -9,11 +9,11 @@ bool operator==(const RsNxsGrp&, const RsNxsGrp&); bool operator==(const RsNxsMsg&, const RsNxsMsg&); bool operator==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r); bool operator==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r); -bool operator==(const RsNxsSyncGrp& l, const RsNxsSyncGrp& r); -bool operator==(const RsNxsSyncMsg& l, const RsNxsSyncMsg& r); bool operator==(const RsNxsSyncGrpItem& l, const RsNxsSyncGrpItem& r); bool operator==(const RsNxsSyncMsgItem& l, const RsNxsSyncMsgItem& r); -bool operator==(const RsNxsTransac& l, const RsNxsTransac& r); +bool operator==(const RsNxsSyncGrpItem& l, const RsNxsSyncGrpItem& r); +bool operator==(const RsNxsSyncMsgItem& l, const RsNxsSyncMsgItem& r); +bool operator==(const RsNxsTransacItem& l, const RsNxsTransacItem& r); //void init_item(RsNxsGrp& nxg); //void init_item(RsNxsMsg& nxm); @@ -23,11 +23,11 @@ void init_item(RsGxsMsgMetaData* metaMsg); RsSerialType* init_item(RsNxsGrp& nxg); RsSerialType* init_item(RsNxsMsg& nxm); -RsSerialType* init_item(RsNxsSyncGrp& rsg); -RsSerialType* init_item(RsNxsSyncMsg& rsgm); +RsSerialType* init_item(RsNxsSyncGrpReqItem &rsg); +RsSerialType* init_item(RsNxsSyncMsgReqItem &rsgm); RsSerialType* init_item(RsNxsSyncGrpItem& rsgl); RsSerialType* init_item(RsNxsSyncMsgItem& rsgml); -RsSerialType* init_item(RsNxsTransac& rstx); +RsSerialType* init_item(RsNxsTransacItem& rstx); template void copy_all_but(T& ex, const std::list& s, std::list& d) diff --git a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc index ec772a4a1..85ab0a510 100644 --- a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc +++ b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc @@ -24,7 +24,7 @@ bool rs_nxs_test::RsNxsSimpleDummyCircles::loadCircle( } int rs_nxs_test::RsNxsSimpleDummyCircles::canSend(const RsGxsCircleId& circleId, - const RsPgpId& id) { + const RsPgpId& id, bool &should_encrypt) { return true; } @@ -33,11 +33,20 @@ int rs_nxs_test::RsNxsSimpleDummyCircles::canReceive( return true; } +bool rs_nxs_test::RsNxsSimpleDummyCircles::isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) +{ + return true ; +} + bool rs_nxs_test::RsNxsSimpleDummyCircles::recipients( const RsGxsCircleId& circleId, std::list& friendlist) { return true; } +bool rs_nxs_test::RsNxsSimpleDummyCircles::recipients( + const RsGxsCircleId& circleId, std::list& friendlist) { + return true; +} rs_nxs_test::RsNxsSimpleDummyReputation::RsNxsSimpleDummyReputation( RepMap& repMap, bool cached) { } @@ -76,8 +85,7 @@ bool rs_nxs_test::RsNxsDelayedDummyCircles::loadCircle( return allowed(circleId); } -int rs_nxs_test::RsNxsDelayedDummyCircles::canSend( - const RsGxsCircleId& circleId, const RsPgpId& id) { +int rs_nxs_test::RsNxsDelayedDummyCircles::canSend(const RsGxsCircleId& circleId, const RsPgpId& id, bool &should_encrypt) { return allowed(circleId); } diff --git a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h index 38f9f599b..45e79ee31 100644 --- a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h +++ b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h @@ -39,10 +39,13 @@ namespace rs_nxs_test bool isLoaded(const RsGxsCircleId &circleId); bool loadCircle(const RsGxsCircleId &circleId); - int canSend(const RsGxsCircleId &circleId, const RsPgpId &id); + int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt); int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id); bool recipients(const RsGxsCircleId &circleId, std::list &friendlist); + virtual bool recipients(const RsGxsCircleId &circleId, std::list& idlist) ; + virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) ; + virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) { return true ; } }; /*! @@ -66,10 +69,13 @@ namespace rs_nxs_test bool isLoaded(const RsGxsCircleId &circleId); bool loadCircle(const RsGxsCircleId &circleId); - int canSend(const RsGxsCircleId &circleId, const RsPgpId &id); + int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt); int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id); bool recipients(const RsGxsCircleId &circleId, std::list &friendlist); + virtual bool recipients(const RsGxsCircleId &circleId, std::list& idlist) { return true ;} + virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsId& id) { return allowed(circleId) ; } + virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) { return true ; } private: bool allowed(const RsGxsCircleId& circleId); diff --git a/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc b/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc index 65b6375c4..1e46f17d6 100644 --- a/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc +++ b/tests/unittests/libretroshare/gxs/nxs_test/nxstesthub.cc @@ -81,6 +81,7 @@ rs_nxs_test::NxsTestHub::NxsTestHub(NxsTestScenario::pointer testScenario) mTestScenario->getServiceInfo(), mTestScenario->getDummyReputations(*cit), mTestScenario->getDummyCircles(*cit), + NULL, mTestScenario->getDummyPgpUtils(), true ) diff --git a/tests/unittests/libretroshare/serialiser/rsnxsitems_test.cc b/tests/unittests/libretroshare/serialiser/rsnxsitems_test.cc index 5786289d0..e40e53ea7 100644 --- a/tests/unittests/libretroshare/serialiser/rsnxsitems_test.cc +++ b/tests/unittests/libretroshare/serialiser/rsnxsitems_test.cc @@ -12,9 +12,9 @@ TEST(libretroshare_serialiser, RsNxsItem) { test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); + test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); + test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); + test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); } diff --git a/tests/unittests/libretroshare/services/gxs/GxsPeerNode.cc b/tests/unittests/libretroshare/services/gxs/GxsPeerNode.cc index 27563a9d0..24846a206 100644 --- a/tests/unittests/libretroshare/services/gxs/GxsPeerNode.cc +++ b/tests/unittests/libretroshare/services/gxs/GxsPeerNode.cc @@ -67,7 +67,7 @@ GxsPeerNode::GxsPeerNode(const RsPeerId &ownId, const std::list &frien mGxsIdNs = new RsGxsNetService( RS_SERVICE_GXS_TYPE_GXSID, mGxsIdDs, nxsMgr, mGxsIdService, mGxsIdService->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, mPgpAuxUtils, false); // don't synchronise group automatic (need explicit group request) @@ -81,7 +81,7 @@ GxsPeerNode::GxsPeerNode(const RsPeerId &ownId, const std::list &frien #endif (RS_SERVICE_GXS_TYPE_GXSCIRCLE, mGxsCirclesDs, nxsMgr, mGxsCircles, mGxsCircles->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,NULL, mPgpAuxUtils); } else @@ -107,7 +107,7 @@ GxsPeerNode::GxsPeerNode(const RsPeerId &ownId, const std::list &frien #endif (RS_SERVICE_GXS_TYPE_TEST, mTestDs, nxsMgr, mTestService, mTestService->getServiceInfo(), - mGxsIdService, mGxsCircles, + mGxsIdService, mGxsCircles,mGxsIdService, mPgpAuxUtils); if (mUseIdentityService) diff --git a/tests/unittests/libretroshare/services/gxs/nxsbasic_test.cc b/tests/unittests/libretroshare/services/gxs/nxsbasic_test.cc index 3b6ca3d29..1b4aec879 100644 --- a/tests/unittests/libretroshare/services/gxs/nxsbasic_test.cc +++ b/tests/unittests/libretroshare/services/gxs/nxsbasic_test.cc @@ -54,7 +54,7 @@ TEST(libretroshare_services, DISABLED_GXS_nxs_basic) std::cerr << "Sending in SyncGrp"; std::cerr << std::endl; - RsNxsSyncGrp *syncGrp = new RsNxsSyncGrp(RS_SERVICE_GXS_TYPE_TEST); + RsNxsSyncGrpItem *syncGrp = new RsNxsSyncGrpItem(RS_SERVICE_GXS_TYPE_TEST); syncGrp->flag = 0; //RsNxsSyncGrp::FLAG_USE_SYNC_HASH; syncGrp->PeerId(friendId); tester.sendPacket(syncGrp); @@ -69,7 +69,7 @@ TEST(libretroshare_services, DISABLED_GXS_nxs_basic) std::cerr << "Recved in SyncGrp"; std::cerr << std::endl; - RsNxsSyncGrp *grp = dynamic_cast(item); + RsNxsSyncGrpItem *grp = dynamic_cast(item); ASSERT_TRUE(grp); delete grp; @@ -134,7 +134,7 @@ TEST(libretroshare_services, DISABLED_GXS_nxs_basic2) std::cerr << "Created Groups."; std::cerr << std::endl; - RsNxsSyncGrp *syncGrp = new RsNxsSyncGrp(RS_SERVICE_GXS_TYPE_TEST); + RsNxsSyncGrpItem *syncGrp= new RsNxsSyncGrpItem(RS_SERVICE_GXS_TYPE_TEST); syncGrp->flag = 0; //RsNxsSyncGrp::FLAG_USE_SYNC_HASH; syncGrp->PeerId(friendId); tester.sendPacket(syncGrp); @@ -159,8 +159,8 @@ TEST(libretroshare_services, DISABLED_GXS_nxs_basic2) item->print(std::cerr); // ignore NxsSyncGrp. - RsNxsSyncGrp *grp = dynamic_cast(item); - RsNxsTransac *trans = dynamic_cast(item); + RsNxsSyncGrpItem *grp = dynamic_cast(item); + RsNxsTransacItem *trans = dynamic_cast(item); if (grp) { std::cerr << "Recved in SyncGrp - ignoring"; diff --git a/tests/unittests/libretroshare/services/gxs/nxspair_tests.cc b/tests/unittests/libretroshare/services/gxs/nxspair_tests.cc index 772309114..e8f4b932d 100644 --- a/tests/unittests/libretroshare/services/gxs/nxspair_tests.cc +++ b/tests/unittests/libretroshare/services/gxs/nxspair_tests.cc @@ -41,7 +41,7 @@ TEST(libretroshare_services, DISABLED_GxsNxsPairExchange1) dropFilter.setUseSource(true); dropFilter.addSource(p2); { - RsNxsSyncGrp *syncGrp = new RsNxsSyncGrp(RS_SERVICE_GXS_TYPE_TEST); + RsNxsSyncGrpItem *syncGrp = new RsNxsSyncGrpItem(RS_SERVICE_GXS_TYPE_TEST); dropFilter.setUseFullTypes(true); dropFilter.addFullType(syncGrp->PacketId()); } @@ -111,7 +111,7 @@ TEST(libretroshare_services, DISABLED_GxsNxsPairExchange2) dropFilter.setUseSource(true); dropFilter.addSource(p2); { - RsNxsSyncGrp *syncGrp = new RsNxsSyncGrp(RS_SERVICE_GXS_TYPE_TEST); + RsNxsSyncGrpItem *syncGrp = new RsNxsSyncGrpItem(RS_SERVICE_GXS_TYPE_TEST); dropFilter.setUseFullTypes(true); dropFilter.addFullType(syncGrp->PacketId()); }