From c19a02c5663e226b6dd9f685c0f27af61c422942 Mon Sep 17 00:00:00 2001 From: defnax Date: Sun, 11 Feb 2024 12:05:30 +0100 Subject: [PATCH 01/23] file upload stats (lib) --- src/ft/ftserver.cc | 32 ++++++++++++++++++++++++++++++++ src/ft/ftserver.h | 6 ++++++ src/retroshare/rsfiles.h | 20 ++++++++++++-------- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/ft/ftserver.cc b/src/ft/ftserver.cc index 29615c982..32d19f823 100644 --- a/src/ft/ftserver.cc +++ b/src/ft/ftserver.cc @@ -1335,6 +1335,15 @@ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t offset += chunk; tosend -= chunk; } + std::map::iterator it = cumulative_uploaded.find(hash) ; + if(it != cumulative_uploaded.end()) + { + it->second += chunksize; + } + else + { + cumulative_uploaded.insert(std::make_pair(hash,(uint64_t)chunksize)) ; + } /* clean up data */ free(data); @@ -2385,3 +2394,26 @@ std::error_condition ftServer::parseFilesLink( if(tft) collection = *tft; return ec; } + +uint64_t ftServer::getCumulativeUpload(RsFileHash hash) +{ + RS_STACK_MUTEX(srvMutex); + std::map::iterator it = cumulative_uploaded.find(hash) ; + if(it != cumulative_uploaded.end()) + return it->second; + return 0; +} + +uint64_t ftServer::getCumulativeUploadAll() +{ + RS_STACK_MUTEX(srvMutex); + uint64_t all = 0; + for(std::map::iterator it(cumulative_uploaded.begin()); it!=cumulative_uploaded.end(); ++it) + all += it->second; + return all; +} + +uint64_t ftServer::getCumulativeUploadNum() +{ + return cumulative_uploaded.size(); +} diff --git a/src/ft/ftserver.h b/src/ft/ftserver.h index 16e1641cb..56c706784 100644 --- a/src/ft/ftserver.h +++ b/src/ft/ftserver.h @@ -364,6 +364,10 @@ public: bool encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item); bool decryptItem(const RsTurtleGenericDataItem *encrypted_item, const RsFileHash& hash, RsTurtleGenericTunnelItem *&decrypted_item); + virtual uint64_t getCumulativeUpload(RsFileHash hash); + virtual uint64_t getCumulativeUploadAll(); + virtual uint64_t getCumulativeUploadNum(); + /*************** Internal Transfer Fns *************************/ virtual int tick(); @@ -422,6 +426,8 @@ private: std::map mEncryptedPeerIds ; // This map holds the hash to be used with each peer id std::map > mUploadLimitMap ; + std::map cumulative_uploaded; + /** Store search callbacks with timeout*/ RS_DEPRECATED std::map< diff --git a/src/retroshare/rsfiles.h b/src/retroshare/rsfiles.h index f8aa9b401..680eb9eda 100644 --- a/src/retroshare/rsfiles.h +++ b/src/retroshare/rsfiles.h @@ -180,14 +180,14 @@ const TransferRequestFlags RS_FILE_REQ_NO_SEARCH ( 0x02000000 ); // di // | RS_FILE_HINTS_NETWORK_WIDE_GROUPS | RS_FILE_HINTS_BROWSABLE_GROUPS ; enum class RsSharedDirectoriesEventCode: uint8_t { - UNKNOWN = 0x00, - STARTING_DIRECTORY_SWEEP = 0x01, // (void) - HASHING_FILE = 0x02, // mMessage: full path and hashing speed of the file being hashed - DIRECTORY_SWEEP_ENDED = 0x03, // (void) - SAVING_FILE_INDEX = 0x04, // (void) - EXTRA_LIST_FILE_ADDED = 0x05, // (void) - EXTRA_LIST_FILE_REMOVED = 0x06, // (void) - SHARED_DIRS_LIST_CHANGED = 0x07, // (void) + UNKNOWN = 0x00, + STARTING_DIRECTORY_SWEEP = 0x01, // (void) + HASHING_FILE = 0x02, // mMessage: full path and hashing speed of the file being hashed + DIRECTORY_SWEEP_ENDED = 0x03, // (void) + SAVING_FILE_INDEX = 0x04, // (void) + EXTRA_LIST_FILE_ADDED = 0x05, // (void) + EXTRA_LIST_FILE_REMOVED = 0x06, // (void) + SHARED_DIRS_LIST_CHANGED = 0x07, // (void) }; enum class RsFileTransferEventCode: uint8_t { @@ -1114,5 +1114,9 @@ public: virtual bool ignoreDuplicates() = 0; virtual void setIgnoreDuplicates(bool ignore) = 0; + virtual uint64_t getCumulativeUpload(RsFileHash hash) = 0; + virtual uint64_t getCumulativeUploadAll() = 0; + virtual uint64_t getCumulativeUploadNum() = 0; + virtual ~RsFiles() = default; }; From 2acdec11ab386974bc0ef567e3a1b1e922553b38 Mon Sep 17 00:00:00 2001 From: David Bears Date: Sun, 12 Oct 2025 20:17:03 -0400 Subject: [PATCH 02/23] fix group flags when changing an identity's anonymous status --- src/services/p3idservice.cc | 103 ++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/src/services/p3idservice.cc b/src/services/p3idservice.cc index 6ac9a76d1..62f74391e 100644 --- a/src/services/p3idservice.cc +++ b/src/services/p3idservice.cc @@ -59,7 +59,7 @@ #define GXSID_MAX_CACHE_SIZE 15000 -// unused keys are deleted according to some heuristic that should favor known keys, signed keys etc. +// unused keys are deleted according to some heuristic that should favor known keys, signed keys etc. static const rstime_t MAX_KEEP_KEYS_BANNED_DEFAULT = 2 * 86400 ; // get rid of banned ids after 1 days. That gives a chance to un-ban someone before he gets definitely kicked out @@ -285,19 +285,19 @@ bool p3IdService::setAsRegularContact(const RsGxsId& id,bool b) { RsStackMutex stack(mIdMtx); std::set::iterator it = mContacts.find(id) ; - + if(b && (it == mContacts.end())) { mContacts.insert(id) ; slowIndicateConfigChanged() ; } - + if( (!b) &&(it != mContacts.end())) { mContacts.erase(it) ; slowIndicateConfigChanged() ; } - + return true ; } @@ -1112,6 +1112,7 @@ bool p3IdService::updateIdentity( const RsGxsId& id, const std::string& name, co group.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC ; group.mImage = avatar; + group.mMeta.mGroupFlags = 0; if(!pseudonimous) { #warning csoler 2020-01-21: Backward compatibility issue to fix here in v0.7.0 @@ -2865,7 +2866,7 @@ bool p3IdService::cache_store(const RsGxsIdGroupItem *item) { #ifdef DEBUG_IDS std::cerr << "p3IdService::cache_store() Found Admin Key" << std::endl; -#endif +#endif fullkey = kit->second; full_key_ok = true; } @@ -3179,7 +3180,7 @@ bool p3IdService::cache_update_if_cached(const RsGxsId &id, std::string serviceS RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ RsGxsIdCache updated_data; - + if(mKeyCache.fetch(id, updated_data)) { #ifdef DEBUG_IDS @@ -3188,7 +3189,7 @@ bool p3IdService::cache_update_if_cached(const RsGxsId &id, std::string serviceS #endif // DEBUG_IDS updated_data.updateServiceString(serviceString); - + mKeyCache.store(id, updated_data); } @@ -3207,15 +3208,15 @@ bool p3IdService::cache_request_ownids() std::cerr << std::endl; #endif // DEBUG_IDS - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; //opts.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; uint32_t token = 0; - + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHEOWNIDS); + GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHEOWNIDS); return true; } @@ -3319,13 +3320,13 @@ bool p3IdService::cachetest_getlist() std::cerr << std::endl; #endif // DEBUG_IDS - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; + uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; uint32_t token = 0; - + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHETEST); + GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHETEST); // Schedule Next Event. RsTickEvent::schedule_in(GXSID_EVENT_CACHETEST, CACHETEST_PERIOD); @@ -3501,7 +3502,7 @@ void p3IdService::CacheArbitrationDone(uint32_t mode) * * Info to be stored in GroupServiceString + Cache. * - * Actually - it must be a Signature here - otherwise, you could + * Actually - it must be a Signature here - otherwise, you could * put in a hash from someone else! * * Don't think that we need to match very often - maybe once a day? @@ -3763,10 +3764,10 @@ bool p3IdService::pgphash_handlerequest(uint32_t token) #endif // DEBUG_IDS // We need full data - for access to Hash & Signature. - // Perhaps we will change this to an initial pass through Meta, + // Perhaps we will change this to an initial pass through Meta, // and use this to discard lots of things. - // Even better - we can set flags in the Meta Data, (IdType), + // Even better - we can set flags in the Meta Data, (IdType), // And use GXS to filter out all the AnonIds, and only have to process // Proper Ids. @@ -3822,7 +3823,7 @@ bool p3IdService::pgphash_handlerequest(uint32_t token) continue; } - /* Have a linear attempt policy - + /* Have a linear attempt policy - * if zero checks - try now. * if 1 check, at least a day. * if 2 checks: 2days, etc. @@ -3935,7 +3936,7 @@ bool p3IdService::pgphash_process() CacheArbitrationDone(BG_PGPHASH); return true; } - + SSGxsIdGroup ssdata; ssdata.load(pg.mMeta.mServiceString); // attempt load - okay if fails. @@ -4268,9 +4269,9 @@ bool p3IdService::recogn_start() RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; uint32_t token = 0; - + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, recognList); - GxsTokenQueue::queueRequest(token, GXSIDREQ_RECOGN); + GxsTokenQueue::queueRequest(token, GXSIDREQ_RECOGN); return true; } @@ -4285,16 +4286,16 @@ bool p3IdService::recogn_handlerequest(uint32_t token) std::vector grpData; bool ok = RsGenExchange::getGroupData(token, grpData); - + if(ok) { #ifdef DEBUG_RECOGN std::cerr << "p3IdService::recogn_request() Have " << grpData.size() << " Groups"; std::cerr << std::endl; #endif // DEBUG_RECOGN - + std::vector::iterator vit = grpData.begin(); - + for(; vit != grpData.end(); ++vit) { RsGxsIdGroupItem* item = dynamic_cast(*vit); @@ -4309,7 +4310,7 @@ bool p3IdService::recogn_handlerequest(uint32_t token) RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ mRecognGroupsToProcess.push_back(item); } - else + else { delete (*vit); } @@ -4360,7 +4361,7 @@ bool p3IdService::recogn_process() CacheArbitrationDone(BG_RECOGN); return true; } - + std::list tagItems; @@ -4379,13 +4380,13 @@ bool p3IdService::recogn_process() { tagValidFlags |= i; } - else + else { isPending |= isTagPending; } delete *it; - i *= 2; + i *= 2; } #ifdef DEBUG_RECOGN @@ -4413,7 +4414,7 @@ bool p3IdService::recogn_process() cache_update_if_cached(RsGxsId(item->meta.mGroupId.toStdString()), serviceString); delete item; - + // Schedule Next Processing. RsTickEvent::schedule_in(GXSID_EVENT_RECOGN_PROC, RECOGN_PROC_PERIOD); return false; // as there are more items on the queue to process. @@ -4439,12 +4440,12 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname // id matches. // nickname matches. // signer is valid. - // ------ + // ------ // signature is valid. (only if doSignCheck == true) - + rstime_t now = time(NULL); isPending = false; - + // check date range. if ((item->valid_from > now) || (item->valid_to < now)) { @@ -4455,7 +4456,7 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname return false; } - + // id match. if (id != item->identity) { @@ -4465,7 +4466,7 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname #endif // DEBUG_RECOGN return false; } - + // nickname match. if (nickname != item->nickname) { @@ -4475,14 +4476,14 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname #endif // DEBUG_RECOGN return false; } - - - + + + { /* check they validity of the Tag */ RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - + std::map::iterator it; it = mRecognSignKeys.find(item->sign.keyId); if (it == mRecognSignKeys.end()) @@ -4493,16 +4494,16 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname #endif // DEBUG_RECOGN // If OldKey, then we don't want to reprocess. - if (mRecognOldSignKeys.end() != + if (mRecognOldSignKeys.end() != mRecognOldSignKeys.find(item->sign.keyId)) { isPending = true; // need to reprocess later with new key } return false; } - + // Check tag_class is okay for signer. - if (it->second->signing_classes.ids.end() == + if (it->second->signing_classes.ids.end() == std::find(it->second->signing_classes.ids.begin(), it->second->signing_classes.ids.end(), item->tag_class)) { #ifdef DEBUG_RECOGN @@ -4511,7 +4512,7 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname #endif // DEBUG_RECOGN return false; } - + // ALL Okay, just signature to check. if (!doSignCheck) { @@ -4538,8 +4539,8 @@ void p3IdService::loadRecognKeys() /************************************************************************************/ /************************************************************************************/ -#define MAX_KNOWN_PGPIDS 20 -#define MAX_UNKNOWN_PGPIDS 20 +#define MAX_KNOWN_PGPIDS 20 +#define MAX_UNKNOWN_PGPIDS 20 #define MAX_PSEUDOIDS 20 #define DUMMY_GXSID_DELAY 5 @@ -4733,7 +4734,7 @@ std::string rsIdTypeToString(uint32_t idtype) /* here we are running a background process that calculates the reputation scores * for each of the IDs.... - * + * * As this class will be extensively used by many other threads... it is best * that we don't block at all. This should be in a background thread. * Perhaps a generic method to handle this will be advisable.... but we do that later. @@ -4743,7 +4744,7 @@ std::string rsIdTypeToString(uint32_t idtype) * 4 components: * 1) Your Opinion: Should override everything else. * 2) Implicit Factors: Know the associated GPG Key. - * 3) Your Friends Opinions: + * 3) Your Friends Opinions: * 4) Your Friends Calculated Reputation Scores. * * Must make sure that there is no Feedback loop in the Reputation calculation. @@ -4761,14 +4762,14 @@ std::string rsIdTypeToString(uint32_t idtype) * So we are going to have three different scores (Own, Peers, (the neighbour) Hood)... * * So next question, when do we need to incrementally calculate the score? - * .... how often do we need to recalculate everything -> this could lead to a flux of messages. + * .... how often do we need to recalculate everything -> this could lead to a flux of messages. + * * * - * * MORE NOTES: * - * The Opinion Messages will have to be signed by PGP or SSL Keys, to guarantee that we don't - * multiple votes per person... As the message system doesn't handle uniqueness in this respect, + * The Opinion Messages will have to be signed by PGP or SSL Keys, to guarantee that we don't + * multiple votes per person... As the message system doesn't handle uniqueness in this respect, * we might have to do FULL_CALC for everything - This bit TODO. * * This will make IdService quite different to the other GXS services. @@ -4777,12 +4778,12 @@ std::string rsIdTypeToString(uint32_t idtype) /************************************************************************************/ /* * Processing Algorithm: - * - Grab all Groups which have received messages. + * - Grab all Groups which have received messages. * (opt 1)-> grab latest msgs for each of these and process => score. * (opt 2)-> try incremental system (people probably won't change opinions often -> just set them once) * --> if not possible, fallback to full calculation. * - * + * */ void p3IdService::checkPeerForIdentities() From 16821c4c74f6a0916e7fd9630b8e30325345538e Mon Sep 17 00:00:00 2001 From: David Bears Date: Fri, 17 Oct 2025 16:36:23 -0400 Subject: [PATCH 03/23] elide connection challenge for public chat lobbies --- src/chat/distributedchat.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/chat/distributedchat.cc b/src/chat/distributedchat.cc index cacd68e08..7c7448cba 100644 --- a/src/chat/distributedchat.cc +++ b/src/chat/distributedchat.cc @@ -1127,6 +1127,7 @@ void DistributedChatService::handleConnectionChallenge(RsChatLobbyConnectChallen RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ for(std::map::iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end() && !found;++it) + if(!IS_PUBLIC_LOBBY(it->second.lobby_flags)) for(std::map::const_iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end() && !found;++it2) if(it2->second + CONNECTION_CHALLENGE_MAX_MSG_AGE + 5 > now) // any msg not older than 5 seconds plus max challenge count is fine. { @@ -1990,7 +1991,7 @@ void DistributedChatService::cleanLobbyCaches() // 5 - look at lobby activity and possibly send connection challenge // - if(++it->second.connexion_challenge_count > CONNECTION_CHALLENGE_MAX_COUNT && now > it->second.last_connexion_challenge_time + CONNECTION_CHALLENGE_MIN_DELAY) + if(!IS_PUBLIC_LOBBY(it->second.lobby_flags) && ++it->second.connexion_challenge_count > CONNECTION_CHALLENGE_MAX_COUNT && now > it->second.last_connexion_challenge_time + CONNECTION_CHALLENGE_MIN_DELAY) { it->second.connexion_challenge_count = 0 ; it->second.last_connexion_challenge_time = now ; From 6b26846bcfb6381972cd268fbab95b8f86b1a27f Mon Sep 17 00:00:00 2001 From: Passw Date: Sun, 23 Nov 2025 07:44:45 +0800 Subject: [PATCH 04/23] no V07_NON_BACKWARD_COMPATIBLE_CHANGE_006 in retroshare.pri https://github.com/RetroShare/RetroShare/blob/master/retroshare.pri#L310-L345 --- src/pgp/rnppgphandler.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pgp/rnppgphandler.cc b/src/pgp/rnppgphandler.cc index 31e848d3e..f5ac7703b 100644 --- a/src/pgp/rnppgphandler.cc +++ b/src/pgp/rnppgphandler.cc @@ -114,7 +114,7 @@ typedef t_ScopeGuard rnp_ // This overrides SHA1 security rules, so that certs signed with sha1 alg are still accepted as friends and profiles signed with sha1 still load. -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_006 +#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_005 #define FFI_CREATE(ffi) \ rnp_ffi_create(&ffi,RNP_KEYSTORE_GPG,RNP_KEYSTORE_GPG); #else From e28799f8f06a3bebd8c84689a613695b6b818660 Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Mon, 24 Nov 2025 21:09:04 +0100 Subject: [PATCH 05/23] added dynamic event type generation --- src/retroshare/rsevents.h | 24 +++++++++++++++++++----- src/services/rseventsservice.cc | 21 ++++++++++++++++++++- src/services/rseventsservice.h | 21 ++++++++++++++------- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/src/retroshare/rsevents.h b/src/retroshare/rsevents.h index aa812c1ca..7ecbd9a11 100644 --- a/src/retroshare/rsevents.h +++ b/src/retroshare/rsevents.h @@ -125,7 +125,7 @@ enum class RsEventType : uint32_t /// @see RsWireEvent SYSTEM = 24, // general system notifications - __MAX /// Used internally, keep last + __MAX = 25 // Used internally, keep last. }; enum class RsEventsErrorNum : int32_t @@ -222,8 +222,7 @@ public: * @param[in] event * @return Success or error details. */ - virtual std::error_condition postEvent( - std::shared_ptr event ) = 0; + virtual std::error_condition postEvent( std::shared_ptr event ) = 0; /** * @brief Send event directly to handlers. Blocking API @@ -231,8 +230,7 @@ public: * @param[in] event * @return Success or error details. */ - virtual std::error_condition sendEvent( - std::shared_ptr event ) = 0; + virtual std::error_condition sendEvent( std::shared_ptr event ) = 0; /** * @brief Generate unique handler identifier @@ -240,6 +238,22 @@ public: */ virtual RsEventsHandlerId_t generateUniqueHandlerId() = 0; + /** + * @brief getDynamicEventType + * This function can be used to generate event types on the fly when not already defined in rseventids.h. This is + * for instance useful when plugins need to generate their own event type. Simply calling + * getDynamicEventType("SOME_STRING_SPECIFIC_TO_THE_PLUGIN") will return the given event type, possibly generating it + * on the fly if needed. + * Other event handlers that use EventType values that are already in rseventids.h do not need this function. + * The result is only valid for the current RS session and may change after restart. + * + * @param unique_service_identifier simple string that is unique to the plugin. + * + * @return returns the event type associated to the string identifier. + * + */ + virtual RsEventType getDynamicEventType(const std::string& unique_service_identifier) =0; + /** * @brief Register events handler * Every time an event is dispatced the registered events handlers will get diff --git a/src/services/rseventsservice.cc b/src/services/rseventsservice.cc index 146bd5ae8..fcbf2daad 100644 --- a/src/services/rseventsservice.cc +++ b/src/services/rseventsservice.cc @@ -56,7 +56,7 @@ std::error_condition RsEventsService::isEventTypeInvalid(RsEventType eventType) return RsEventsErrorNum::EVENT_TYPE_UNDEFINED; if( eventType < RsEventType::__NONE || - eventType >= static_cast(mHandlerMaps.size()) ) + static_cast(eventType) >= mHandlerMaps.size() ) return RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE; return std::error_condition(); @@ -93,6 +93,25 @@ RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId() return generateUniqueHandlerId_unlocked(); } +RsEventType RsEventsService::getDynamicEventType(const std::string& unique_service_identifier) +{ + RS_STACK_MUTEX(mHandlerMapMtx); + + auto it = mRegisteredExtraEventTypes.find(unique_service_identifier); + + if(it == mRegisteredExtraEventTypes.end()) + { + mRegisteredExtraEventTypes[unique_service_identifier] = static_cast(mHandlerMaps.size()); + mHandlerMaps.push_back( std::map)> >()); + + it = mRegisteredExtraEventTypes.find(unique_service_identifier); + + RsInfo() << "Registered new dynamic event Type " << (int)it->second << " for service \"" << unique_service_identifier << "\"" << std::endl; + } + + return it->second; +} + RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked() { if(++mLastHandlerId) return mLastHandlerId; // Avoid 0 after overflow diff --git a/src/services/rseventsservice.h b/src/services/rseventsservice.h index 4f6ce98eb..00ddfb612 100644 --- a/src/services/rseventsservice.h +++ b/src/services/rseventsservice.h @@ -36,10 +36,12 @@ class RsEventsService : { public: RsEventsService(): - mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1), - mEventQueueMtx("RsEventsService::mEventQueueMtx") {} + mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), + mLastHandlerId(1), + mHandlerMaps(static_cast(RsEventType::__MAX)), + mEventQueueMtx("RsEventsService::mEventQueueMtx") {} - /// @see RsEvents + /// @see RsEvents std::error_condition postEvent( std::shared_ptr event ) override; @@ -50,7 +52,10 @@ public: /// @see RsEvents RsEventsHandlerId_t generateUniqueHandlerId() override; - /// @see RsEvents + /// @see RsEvents + RsEventType getDynamicEventType(const std::string& unique_service_identifier) override; + + /// @see RsEvents std::error_condition registerEventsHandler( std::function)> multiCallback, RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0), @@ -69,13 +74,15 @@ protected: /** Storage for event handlers, keep 10 extra types for plugins that might * be released indipendently */ - std::array< + std::vector< std::map< RsEventsHandlerId_t, - std::function)> >, - static_cast(RsEventType::__MAX) + 10 + std::function)> > > mHandlerMaps; + /** Extra event types registered by plugins */ + std::map mRegisteredExtraEventTypes; + RsMutex mEventQueueMtx; std::deque< std::shared_ptr > mEventQueue; From 19f4e13aa7b050c6a18325333bf06b439b24510b Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Mon, 24 Nov 2025 21:12:07 +0100 Subject: [PATCH 06/23] Added workflow --- .github/workflows/ci-mingw64.yml | 70 ++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/workflows/ci-mingw64.yml diff --git a/.github/workflows/ci-mingw64.yml b/.github/workflows/ci-mingw64.yml new file mode 100644 index 000000000..d562938b3 --- /dev/null +++ b/.github/workflows/ci-mingw64.yml @@ -0,0 +1,70 @@ +name: MINGW64 Qt5 Build + +on: + push: + paths-ignore: + - '**/*.md' + pull_request: + paths-ignore: + - '**/*.md' + +concurrency: + group: ${{ github.workflow}}-${{ github.head_ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + runs-on: windows-latest + permissions: + actions: write + defaults: + run: + shell: msys2 {0} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Setup MSYS2 + uses: msys2/setup-msys2@40677d36a502eb2cf0fb808cc9dec31bf6152638 # v2.28.0 + with: + msystem: MINGW64 + update: true + install: >- + base-devel + git + wget + p7zip + gcc + perl + ruby + doxygen + cmake + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-miniupnpc + mingw-w64-x86_64-libxslt + mingw-w64-x86_64-xapian-core + mingw-w64-x86_64-sqlcipher + mingw-w64-x86_64-qt5-base + mingw-w64-x86_64-qt5-multimedia + mingw-w64-x86_64-ccmake + mingw-w64-x86_64-rapidjson + mingw-w64-x86_64-json-c + mingw-w64-x86_64-libbotan + mingw-w64-x86_64-asio + + - name: Checkout submodules + run: | + env + git submodule update --init --remote libbitdht/ libretroshare/ retroshare-webui/ + git submodule update --init supportlibs/librnp supportlibs/rapidjson supportlibs/restbed + + - name: CI-Build + run: | + qmake . -r -spec win32-g++ "CONFIG+=release" "CONFIG+=rs_autologin" "CONFIG+=no_rs_sam3" "CONFIG+=no_rs_sam3_libsam3" + mingw32-make -j3 From 06b8cf923ab94f291c49df818067cdff8e73226e Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Mon, 24 Nov 2025 21:15:11 +0100 Subject: [PATCH 07/23] renaming --- .github/workflows/ci-mingw64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-mingw64.yml b/.github/workflows/ci-mingw64.yml index d562938b3..28f9f2d32 100644 --- a/.github/workflows/ci-mingw64.yml +++ b/.github/workflows/ci-mingw64.yml @@ -1,4 +1,4 @@ -name: MINGW64 Qt5 Build +name: MINGW64 Windows Build on: push: From d0e190bdde20907d16ab27d90ec854d3d975c3ea Mon Sep 17 00:00:00 2001 From: Passw Date: Wed, 26 Nov 2025 06:45:07 +0800 Subject: [PATCH 08/23] fix typo README.adoc wihich which --- src/jsonapi/README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsonapi/README.adoc b/src/jsonapi/README.adoc index 64284b85c..dddd03ae6 100644 --- a/src/jsonapi/README.adoc +++ b/src/jsonapi/README.adoc @@ -437,7 +437,7 @@ After spending some hours investigating this topic the most reasonable approach seems to: 1. Properly document headers in +libretroshare/src/retroshare/+ in doxygen syntax -specifying wihich params are input and/or output (doxygen sysntax for this is +specifying which params are input and/or output (doxygen sysntax for this is +@param[in/out/inout]+) this will be the API documentation too. 2. At compile time use doxygen to generate XML description of the headers and use From 41f9ee2fcfb98776eb4c57ba848e853aca7e73d2 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Fri, 28 Nov 2025 12:45:50 +0100 Subject: [PATCH 09/23] rsdir.cc: Remove trailing slash/backslash in directory names to avoid mingw64 _wstat fail --- src/util/rsdir.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/util/rsdir.cc b/src/util/rsdir.cc index b50029879..ce5f8874d 100644 --- a/src/util/rsdir.cc +++ b/src/util/rsdir.cc @@ -521,8 +521,12 @@ bool RsDirUtil::checkDirectory(const std::string& dir) int val; mode_t st_mode; #ifdef WINDOWS_SYS - std::wstring wdir; - librs::util::ConvertUtf8ToUtf16(dir, wdir); + std::string fixed = dir; + std::wstring wdir; + // mingw64 _wstat fails when the directory name has trailing slash or backslash: we remove them + while (!fixed.empty() && (fixed.back() == '\\' || fixed.back() == '/')) + fixed.pop_back(); + librs::util::ConvertUtf8ToUtf16(fixed, wdir); struct _stat buf; val = _wstat(wdir.c_str(), &buf); st_mode = buf.st_mode; From 82aced1fad4a7c261bc61abc6580c52ac51b14bb Mon Sep 17 00:00:00 2001 From: jolavillette Date: Fri, 28 Nov 2025 17:22:33 +0100 Subject: [PATCH 10/23] fix indentation --- src/util/rsdir.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/util/rsdir.cc b/src/util/rsdir.cc index ce5f8874d..69d755c24 100644 --- a/src/util/rsdir.cc +++ b/src/util/rsdir.cc @@ -521,12 +521,12 @@ bool RsDirUtil::checkDirectory(const std::string& dir) int val; mode_t st_mode; #ifdef WINDOWS_SYS - std::string fixed = dir; - std::wstring wdir; - // mingw64 _wstat fails when the directory name has trailing slash or backslash: we remove them - while (!fixed.empty() && (fixed.back() == '\\' || fixed.back() == '/')) - fixed.pop_back(); - librs::util::ConvertUtf8ToUtf16(fixed, wdir); + std::string fixed = dir; + std::wstring wdir; + // mingw64 _wstat fails when the directory name has trailing slash or backslash: we remove them + while (!fixed.empty() && (fixed.back() == '\\' || fixed.back() == '/')) + fixed.pop_back(); + librs::util::ConvertUtf8ToUtf16(fixed, wdir); struct _stat buf; val = _wstat(wdir.c_str(), &buf); st_mode = buf.st_mode; From b7eb2bea9d5f79b2784510fdeeff1349f2dea356 Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Mon, 1 Dec 2025 22:23:20 +0100 Subject: [PATCH 11/23] fixed plugin loading --- src/plugins/pluginmanager.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/pluginmanager.cc b/src/plugins/pluginmanager.cc index 573a81c6a..692e72d6a 100644 --- a/src/plugins/pluginmanager.cc +++ b/src/plugins/pluginmanager.cc @@ -311,7 +311,7 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time) if(!_allow_all_plugins) { - if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() ) +// if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() ) { auto ev = std::make_shared(); ev->mEventCode = RsSystemEventCode::NEW_PLUGIN_FOUND; @@ -321,9 +321,10 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time) rsEvents->sendEvent(ev); // needs to be synchroneous!! } - // at this point, if the plugin was accepted by the sync call above, it will be removed from the _rejected_hashes map. + // at this point, if the plugin was accepted by the sync call above, it will be removed from the _rejected_hashes map, + // and added to the accepted hash map. - if(_rejected_hashes.find(pinfo.file_hash) != _rejected_hashes.end() ) + if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() ) { pinfo.status = PLUGIN_STATUS_REJECTED_HASH ; std::cerr << " -> hash rejected. Giving up plugin. " << std::endl; From 793e83c91216d5aec9cf61ef8dbd1f2fdeb7a55f Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Mon, 1 Dec 2025 22:32:29 +0100 Subject: [PATCH 12/23] re-enabled single request for plugins (disabled by previous commit for debug) --- src/plugins/pluginmanager.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/pluginmanager.cc b/src/plugins/pluginmanager.cc index 692e72d6a..70371360e 100644 --- a/src/plugins/pluginmanager.cc +++ b/src/plugins/pluginmanager.cc @@ -311,7 +311,7 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time) if(!_allow_all_plugins) { -// if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() ) + if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() ) { auto ev = std::make_shared(); ev->mEventCode = RsSystemEventCode::NEW_PLUGIN_FOUND; @@ -324,8 +324,9 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time) // at this point, if the plugin was accepted by the sync call above, it will be removed from the _rejected_hashes map, // and added to the accepted hash map. - if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() ) - { + if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() + ||_rejected_hashes.find(pinfo.file_hash) != _rejected_hashes.end() ) + { pinfo.status = PLUGIN_STATUS_REJECTED_HASH ; std::cerr << " -> hash rejected. Giving up plugin. " << std::endl; return false ; From b14806a600c8e51c78952a1536cbbd71f41fb152 Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Wed, 3 Dec 2025 17:28:20 +0100 Subject: [PATCH 13/23] fixed bug (spotted by sanitizer) --- src/gossipdiscovery/p3gossipdiscovery.cc | 77 ++++++++++++------------ 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/src/gossipdiscovery/p3gossipdiscovery.cc b/src/gossipdiscovery/p3gossipdiscovery.cc index 430b7a843..a5cf8d509 100644 --- a/src/gossipdiscovery/p3gossipdiscovery.cc +++ b/src/gossipdiscovery/p3gossipdiscovery.cc @@ -1164,46 +1164,45 @@ void p3discovery2::statusChange(const std::list &plist) std::cerr << "p3discovery2::statusChange()" << std::endl; #endif - std::list::const_iterator pit; - for(pit = plist.begin(); pit != plist.end(); ++pit) - { - if (pit->actions & RS_SERVICE_PEER_CONNECTED) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Starting Disc with: " << pit->id << std::endl; -#endif - sendOwnContactInfo(pit->id); - } - else if (pit->actions & RS_SERVICE_PEER_DISCONNECTED) - { - std::cerr << "p3discovery2::statusChange() Disconnected: " << pit->id << std::endl; - } - - if (pit->actions & RS_SERVICE_PEER_NEW) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Adding Friend: " << pit->id << std::endl; -#endif - addFriend(pit->id); - } - else if (pit->actions & RS_SERVICE_PEER_REMOVED) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Removing Friend: " << pit->id << std::endl; -#endif - removeFriend(pit->id); - } - } -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() finished." << std::endl; -#endif - if(rsEvents) + for(auto pit = plist.begin(); pit != plist.end(); ++pit) { - auto ev = std::make_shared(); - ev->mGossipDiscoveryEventType = RsGossipDiscoveryEventType::DISCOVERY_INFO_RECEIVED; - ev->mFromId.clear(); - ev->mAboutId = pit->id; - rsEvents->postEvent(ev); + if (pit->actions & RS_SERVICE_PEER_CONNECTED) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3discovery2::statusChange() Starting Disc with: " << pit->id << std::endl; +#endif + sendOwnContactInfo(pit->id); + } + else if (pit->actions & RS_SERVICE_PEER_DISCONNECTED) + { + std::cerr << "p3discovery2::statusChange() Disconnected: " << pit->id << std::endl; + } + + if (pit->actions & RS_SERVICE_PEER_NEW) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3discovery2::statusChange() Adding Friend: " << pit->id << std::endl; +#endif + addFriend(pit->id); + } + else if (pit->actions & RS_SERVICE_PEER_REMOVED) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3discovery2::statusChange() Removing Friend: " << pit->id << std::endl; +#endif + removeFriend(pit->id); + } +#ifdef P3DISC_DEBUG + std::cerr << "p3discovery2::statusChange() finished." << std::endl; +#endif + if(rsEvents) + { + auto ev = std::make_shared(); + ev->mGossipDiscoveryEventType = RsGossipDiscoveryEventType::DISCOVERY_INFO_RECEIVED; + ev->mFromId.clear(); + ev->mAboutId = pit->id; + rsEvents->postEvent(ev); + } } return; From 5ff3b58bbdb8c4d897caceb7d3bcd2d2a7394cbb Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Wed, 3 Dec 2025 18:11:35 +0100 Subject: [PATCH 14/23] fixed free/delete mismatch --- src/services/autoproxy/p3i2psam3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/autoproxy/p3i2psam3.cpp b/src/services/autoproxy/p3i2psam3.cpp index 99e5d457d..4e693184b 100644 --- a/src/services/autoproxy/p3i2psam3.cpp +++ b/src/services/autoproxy/p3i2psam3.cpp @@ -516,7 +516,7 @@ bool p3I2pSam3::startSession() } if (ret != 0) { - delete session; + free(session); session = nullptr; return false; } From 1022bd29673a61e610fe6f8f36b49c21868ee1d8 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Sun, 7 Dec 2025 19:30:36 +0100 Subject: [PATCH 15/23] Fix deserialisation error not detected in pqistreamer --- src/pqi/pqistreamer.cc | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/pqi/pqistreamer.cc b/src/pqi/pqistreamer.cc index a63a84d91..ff242f363 100644 --- a/src/pqi/pqistreamer.cc +++ b/src/pqi/pqistreamer.cc @@ -978,43 +978,51 @@ continue_packet: #ifdef DEBUG_PQISTREAMER std::cerr << "[" << (void*)pthread_self() << "] " << RsUtil::BinToHex((char*)block,8) << "...: deserializing. Size=" << pktlen << std::endl ; #endif - RsItem *pkt ; + RsItem *pkt = NULL; + bool is_error = false; - if(is_partial_packet) + if (is_partial_packet) { #ifdef DEBUG_PACKET_SLICING - std::cerr << "Inputing partial packet " << RsUtil::BinToHex((char*)block,8) << std::endl; + RsDbg() << "Inputing partial packet " << RsUtil::BinToHex((char*)block,8); #endif - uint32_t packet_length = 0 ; - pkt = addPartialPacket(block,pktlen,slice_packet_id,is_packet_starting,is_packet_ending,packet_length) ; - - pktlen = packet_length ; + uint32_t packet_length = 0 ; + pkt = addPartialPacket(block,pktlen,slice_packet_id,is_packet_starting,is_packet_ending,packet_length); + if (pkt != NULL) + pktlen = packet_length; + else if (is_packet_ending) + is_error = true; } else - pkt = mRsSerialiser->deserialise(block, &pktlen); - - if ((pkt != NULL) && (0 < handleincomingitem(pkt,pktlen))) { + pkt = mRsSerialiser->deserialise(block, &pktlen); + if (pkt == NULL) + is_error = true; + } + + if (pkt != NULL) + { + handleincomingitem(pkt,pktlen); #ifdef DEBUG_PQISTREAMER pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "Successfully Read a Packet!"); #endif inReadBytes(pktlen); // only count deserialised packets, because that's what is actually been transfered. } - else if (!is_partial_packet) + else if (is_error) { #ifdef DEBUG_PQISTREAMER pqioutput(PQL_ALERT, pqistreamerzone, "Failed to handle Packet!"); #endif - std::cerr << "Incoming Packet could not be deserialised:" << std::endl; - std::cerr << " Incoming peer id: " << PeerId() << std::endl; + RsDbg() << "Incoming Packet could not be deserialised:"; + RsDbg() << " Incoming peer id: " << PeerId(); if(pktlen >= 8) - std::cerr << " Packet header : " << RsUtil::BinToHex((unsigned char*)block,8) << std::endl; + RsDbg() << " Packet header : " << RsUtil::BinToHex((unsigned char*)block,8); if(pktlen > 8) - std::cerr << " Packet data : " << RsUtil::BinToHex((unsigned char*)block+8,std::min(50u,pktlen-8)) << ((pktlen>58)?"...":"") << std::endl; + RsDbg() << " Packet data : " << RsUtil::BinToHex((unsigned char*)block+8,std::min(50u,pktlen-8)) << ((pktlen>58)?"...":""); } - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; // reset failed read, as the packet has been totally read. + mReading_state = reading_state_initial; // restart at state 1. + mFailed_read_attempts = 0; // reset failed read, as the packet has been totally read. } if(maxin > readbytes && mBio->moretoread(0)) From bb4e8c5d6bd4a4a2def0d1d4a7a95ae7e61ffd91 Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Mon, 8 Dec 2025 20:01:02 +0100 Subject: [PATCH 16/23] added update of external address when needed --- src/pqi/p3netmgr.cc | 1 + src/pqi/p3peermgr.cc | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pqi/p3netmgr.cc b/src/pqi/p3netmgr.cc index 21e45ac16..54e3c5181 100644 --- a/src/pqi/p3netmgr.cc +++ b/src/pqi/p3netmgr.cc @@ -1236,6 +1236,7 @@ bool p3NetMgrIMPL::setExtAddress(const struct sockaddr_storage &addr) #ifdef NETMGR_DEBUG_RESET std::cerr << "p3NetMgrIMPL::setExtAddress() Calling NetReset" << std::endl; #endif + std::cerr << "External address changed to " << sockaddr_storage_iptostring(mExtAddr)<< std::endl; if(rsEvents) { diff --git a/src/pqi/p3peermgr.cc b/src/pqi/p3peermgr.cc index b257eec47..f5407a0c3 100644 --- a/src/pqi/p3peermgr.cc +++ b/src/pqi/p3peermgr.cc @@ -1808,7 +1808,8 @@ bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, cons sockaddr_storage current_best_ext_address_guess ; uint32_t count ; - locked_computeCurrentBestOwnExtAddressCandidate(current_best_ext_address_guess,count) ; + if(locked_computeCurrentBestOwnExtAddressCandidate(current_best_ext_address_guess,count)) + mNetMgr->setExtAddress(current_best_ext_address_guess); std::cerr << "p3PeerMgr:: Current external address is calculated to be: " << sockaddr_storage_iptostring(current_best_ext_address_guess) << " (simultaneously reported by " << count << " peers)." << std::endl; } From 42f1c4c7743de3954aea6f0e5cde7fc56e964c6e Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Tue, 9 Dec 2025 18:42:27 +0100 Subject: [PATCH 17/23] fixed deadlock in setExtAddress call --- src/pqi/p3peermgr.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/pqi/p3peermgr.cc b/src/pqi/p3peermgr.cc index f5407a0c3..fd3e09628 100644 --- a/src/pqi/p3peermgr.cc +++ b/src/pqi/p3peermgr.cc @@ -1789,6 +1789,9 @@ bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, cons // - remove old values for that same peer // - remove values for non connected peers + sockaddr_storage current_best_ext_address_guess ; + bool have_ext_address = false; + { RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ @@ -1805,15 +1808,17 @@ bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, cons else ++it ; - sockaddr_storage current_best_ext_address_guess ; uint32_t count ; if(locked_computeCurrentBestOwnExtAddressCandidate(current_best_ext_address_guess,count)) - mNetMgr->setExtAddress(current_best_ext_address_guess); + have_ext_address = true; std::cerr << "p3PeerMgr:: Current external address is calculated to be: " << sockaddr_storage_iptostring(current_best_ext_address_guess) << " (simultaneously reported by " << count << " peers)." << std::endl; } + if(have_ext_address) + mNetMgr->setExtAddress(current_best_ext_address_guess); // setExtAddress will only send an event if the address actually changed. + // now current sockaddr_storage own_addr ; From 656cd48eeffdfa4aa78ad8f96c09c2ee384e83a4 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Thu, 18 Dec 2025 09:36:07 +0100 Subject: [PATCH 18/23] Fix spurious System time mismatch in distributedchat --- src/chat/distributedchat.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/chat/distributedchat.cc b/src/chat/distributedchat.cc index 37a1f3b34..adf4bc188 100644 --- a/src/chat/distributedchat.cc +++ b/src/chat/distributedchat.cc @@ -611,6 +611,13 @@ void DistributedChatService::handleRecvChatLobbyList(RsChatLobbyListItem *item) void DistributedChatService::addTimeShiftStatistics(int D) { + // consider only 1 item per second + static rstime_t last_stat_time = 0; + rstime_t now = time(NULL); + if(now <= last_stat_time) + return; + last_stat_time = now; + static const int S = 50 ; // accuracy up to 2^50 second. Quite conservative! static int total = 0 ; static std::vector log_delay_histogram(S,0) ; From cc18325917cc7aa73cfa6e7af044da89b9456774 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Fri, 19 Dec 2025 07:34:33 +0100 Subject: [PATCH 19/23] fix indentation --- src/chat/distributedchat.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chat/distributedchat.cc b/src/chat/distributedchat.cc index adf4bc188..c3c1b3a66 100644 --- a/src/chat/distributedchat.cc +++ b/src/chat/distributedchat.cc @@ -613,10 +613,10 @@ void DistributedChatService::addTimeShiftStatistics(int D) { // consider only 1 item per second static rstime_t last_stat_time = 0; - rstime_t now = time(NULL); - if(now <= last_stat_time) - return; - last_stat_time = now; + rstime_t now = time(NULL); + if(now <= last_stat_time) + return; + last_stat_time = now; static const int S = 50 ; // accuracy up to 2^50 second. Quite conservative! static int total = 0 ; From 9bc8123146a0d79e13c0e5d9bf160227caea6f9d Mon Sep 17 00:00:00 2001 From: Cyril Soler Date: Sat, 20 Dec 2025 13:08:28 +0100 Subject: [PATCH 20/23] added /app/bin/tor in the linux search paths --- src/tor/TorManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tor/TorManager.cpp b/src/tor/TorManager.cpp index 4dd34afd8..1a0ff86f3 100644 --- a/src/tor/TorManager.cpp +++ b/src/tor/TorManager.cpp @@ -731,6 +731,11 @@ std::string TorManagerPrivate::torExecutablePath() const if(RsDirUtil::fileExists("/usr/bin/tor")) return std::string("/usr/bin/tor"); + + // If not, try the flatpack location, so as to be compatible with flatpack RS versions. + + if(RsDirUtil::fileExists("/app/bin/tor")) + return std::string("/app/bin/tor"); #endif RsErr() << "Could not find Tor executable anywhere!" ; From b0171aebbd75ec87c41c31dff37ba2188054796d Mon Sep 17 00:00:00 2001 From: natinew77-creator Date: Sat, 20 Dec 2025 18:33:41 -0500 Subject: [PATCH 21/23] Implement upload stats persistence --- src/file_sharing/p3filelists.cc | 62 ++++++++++++++++++++++++++++- src/file_sharing/p3filelists.h | 8 ++++ src/file_sharing/rsfilelistitems.cc | 5 +++ src/file_sharing/rsfilelistitems.h | 12 ++++++ src/ft/ftserver.cc | 24 ++--------- src/ft/ftserver.h | 2 - 6 files changed, 89 insertions(+), 24 deletions(-) diff --git a/src/file_sharing/p3filelists.cc b/src/file_sharing/p3filelists.cc index cda6e4e82..a98ec1145 100644 --- a/src/file_sharing/p3filelists.cc +++ b/src/file_sharing/p3filelists.cc @@ -355,6 +355,27 @@ cleanup = true; sList.push_back(item) ; } + { + RS_STACK_MUTEX(mFLSMtx) ; + RsFileListsUploadStatsItem *item = nullptr; + + for(auto it(mCumulativeUploaded.begin());it!=mCumulativeUploaded.end();++it) + { + if(item == nullptr) + item = new RsFileListsUploadStatsItem ; + + item->hash_stats.insert(*it); + + if(item->hash_stats.size() > 500) // safe bet for size + { + sList.push_back(item) ; + item = nullptr; + } + } + if(item != nullptr) + sList.push_back(item) ; + } + RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); /* basic control parameters */ @@ -486,6 +507,7 @@ bool p3FileDatabase::loadList(std::list& load) ignored_suffixes.push_back( ".part" ); #endif mPrimaryBanList.clear(); + mCumulativeUploaded.clear(); for(std::list::iterator it = load.begin(); it != load.end(); ++it) { @@ -606,6 +628,13 @@ bool p3FileDatabase::loadList(std::list& load) mLastPrimaryBanListChangeTimeStamp = time(NULL); } + RsFileListsUploadStatsItem *fu = dynamic_cast(*it) ; + + if(fu) + { + mCumulativeUploaded.insert(fu->hash_stats.begin(), fu->hash_stats.end()) ; + } + delete *it ; } @@ -982,8 +1011,6 @@ bool p3FileDatabase::findChildPointer( void *ref, int row, void *& result, return res; } -// This function returns statistics about the entire directory - int p3FileDatabase::getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats) { RS_STACK_MUTEX(mFLSMtx) ; @@ -1002,6 +1029,37 @@ int p3FileDatabase::getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& s } } +uint64_t p3FileDatabase::getCumulativeUpload(const RsFileHash& hash) const +{ + RS_STACK_MUTEX(mFLSMtx); + auto it = mCumulativeUploaded.find(hash); + if (it != mCumulativeUploaded.end()) + return it->second; + return 0; +} + +uint64_t p3FileDatabase::getCumulativeUploadAll() const +{ + RS_STACK_MUTEX(mFLSMtx); + uint64_t total = 0; + for (auto it = mCumulativeUploaded.begin(); it != mCumulativeUploaded.end(); ++it) + total += it->second; + return total; +} + +uint64_t p3FileDatabase::getCumulativeUploadNum() const +{ + RS_STACK_MUTEX(mFLSMtx); + return mCumulativeUploaded.size(); +} + +void p3FileDatabase::addUploadStats(const RsFileHash& hash, uint64_t size) +{ + RS_STACK_MUTEX(mFLSMtx); + mCumulativeUploaded[hash] += size; + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_OFTEN); +} + bool p3FileDatabase::removeExtraFile(const RsFileHash& hash) { bool ret = false; diff --git a/src/file_sharing/p3filelists.h b/src/file_sharing/p3filelists.h index 1ecb3cde9..1381096cc 100644 --- a/src/file_sharing/p3filelists.h +++ b/src/file_sharing/p3filelists.h @@ -79,6 +79,7 @@ class LocalDirectoryStorage ; class RsFileListsSyncRequestItem ; class RsFileListsSyncResponseItem ; class RsFileListsBannedHashesItem ; +class RsFileListsUploadStatsItem ; class HashStorage ; @@ -171,6 +172,11 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub int getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats); + virtual uint64_t getCumulativeUpload(const RsFileHash& hash) const; + virtual uint64_t getCumulativeUploadAll() const; + virtual uint64_t getCumulativeUploadNum() const; + virtual void addUploadStats(const RsFileHash& hash, uint64_t size); + // interface for hash caching void setWatchPeriod(uint32_t seconds); @@ -294,6 +300,8 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub bool mBannedFileListNeedsUpdate; rstime_t mLastPrimaryBanListChangeTimeStamp; + std::map mCumulativeUploaded; + void locked_sendBanInfo(const RsPeerId& pid); void handleBannedFilesInfo(RsFileListsBannedHashesItem *item); }; diff --git a/src/file_sharing/rsfilelistitems.cc b/src/file_sharing/rsfilelistitems.cc index 4ac90af10..dc2889e85 100644 --- a/src/file_sharing/rsfilelistitems.cc +++ b/src/file_sharing/rsfilelistitems.cc @@ -50,6 +50,10 @@ void RsFileListsBannedHashesConfigItem::serial_process(RsGenericSerializer::Seri { RsTypeSerializer::serial_process(j,ctx,primary_banned_files_list,"primary_banned_files_list") ; } +void RsFileListsUploadStatsItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) +{ + RsTypeSerializer::serial_process(j,ctx,hash_stats,"hash_stats") ; +} RsItem *RsFileListsSerialiser::create_item(uint16_t service,uint8_t type) const { @@ -62,6 +66,7 @@ RsItem *RsFileListsSerialiser::create_item(uint16_t service,uint8_t type) const case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: return new RsFileListsSyncResponseItem(); case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM: return new RsFileListsBannedHashesItem(); case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM: return new RsFileListsBannedHashesConfigItem(); + case RS_PKT_SUBTYPE_FILELISTS_UPLOAD_STATS_ITEM: return new RsFileListsUploadStatsItem(); default: return NULL ; } diff --git a/src/file_sharing/rsfilelistitems.h b/src/file_sharing/rsfilelistitems.h index a8c84e18b..42b669d6a 100644 --- a/src/file_sharing/rsfilelistitems.h +++ b/src/file_sharing/rsfilelistitems.h @@ -40,6 +40,7 @@ const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM = 0x02; const uint8_t RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM = 0x03; const uint8_t RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM = 0x04; const uint8_t RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM = 0x05; +const uint8_t RS_PKT_SUBTYPE_FILELISTS_UPLOAD_STATS_ITEM = 0x06; /*! * Base class for filelist sync items @@ -127,6 +128,17 @@ public: std::map primary_banned_files_list ; }; +class RsFileListsUploadStatsItem: public RsFileListsItem +{ +public: + RsFileListsUploadStatsItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_UPLOAD_STATS_ITEM){} + + virtual void clear() { hash_stats.clear(); } + virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); + + std::map hash_stats; +}; + class RsFileListsSerialiser : public RsServiceSerializer { public: diff --git a/src/ft/ftserver.cc b/src/ft/ftserver.cc index ef6e4ef9e..335990bb2 100644 --- a/src/ft/ftserver.cc +++ b/src/ft/ftserver.cc @@ -1317,15 +1317,7 @@ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t offset += chunk; tosend -= chunk; } - std::map::iterator it = cumulative_uploaded.find(hash) ; - if(it != cumulative_uploaded.end()) - { - it->second += chunksize; - } - else - { - cumulative_uploaded.insert(std::make_pair(hash,(uint64_t)chunksize)) ; - } + mFileDatabase->addUploadStats(hash, chunksize); /* clean up data */ free(data); @@ -2382,23 +2374,15 @@ std::error_condition ftServer::parseFilesLink( uint64_t ftServer::getCumulativeUpload(RsFileHash hash) { - RS_STACK_MUTEX(srvMutex); - std::map::iterator it = cumulative_uploaded.find(hash) ; - if(it != cumulative_uploaded.end()) - return it->second; - return 0; + return mFileDatabase->getCumulativeUpload(hash); } uint64_t ftServer::getCumulativeUploadAll() { - RS_STACK_MUTEX(srvMutex); - uint64_t all = 0; - for(std::map::iterator it(cumulative_uploaded.begin()); it!=cumulative_uploaded.end(); ++it) - all += it->second; - return all; + return mFileDatabase->getCumulativeUploadAll(); } uint64_t ftServer::getCumulativeUploadNum() { - return cumulative_uploaded.size(); + return mFileDatabase->getCumulativeUploadNum(); } diff --git a/src/ft/ftserver.h b/src/ft/ftserver.h index 8efdfe9d5..24a954bf4 100644 --- a/src/ft/ftserver.h +++ b/src/ft/ftserver.h @@ -426,8 +426,6 @@ private: std::map mEncryptedPeerIds ; // This map holds the hash to be used with each peer id std::map > mUploadLimitMap ; - std::map cumulative_uploaded; - /** Store search callbacks with timeout*/ RS_DEPRECATED std::map< From 106495ddb5361ce234a38103e319a81c44185dd5 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Mon, 22 Dec 2025 10:49:14 +0100 Subject: [PATCH 22/23] add a comment --- src/chat/distributedchat.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/chat/distributedchat.cc b/src/chat/distributedchat.cc index c3c1b3a66..06abf4159 100644 --- a/src/chat/distributedchat.cc +++ b/src/chat/distributedchat.cc @@ -611,7 +611,8 @@ void DistributedChatService::handleRecvChatLobbyList(RsChatLobbyListItem *item) void DistributedChatService::addTimeShiftStatistics(int D) { - // consider only 1 item per second + // Bursts of messages from friends using a wrong system clock can trigger a TIME_SHIFT_PROBLEM event + // We eliminate that by taking into account at most 1 message per second static rstime_t last_stat_time = 0; rstime_t now = time(NULL); if(now <= last_stat_time) From 06f41de22db04d1a41961b34ebef85d4535d6465 Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Sat, 27 Dec 2025 23:24:22 +0100 Subject: [PATCH 23/23] Added clear upload stats featue --- src/file_sharing/p3filelists.cc | 5 +++++ src/file_sharing/p3filelists.h | 1 + src/ft/ftserver.cc | 5 +++++ src/ft/ftserver.h | 1 + src/retroshare/rsfiles.h | 2 ++ 5 files changed, 14 insertions(+) diff --git a/src/file_sharing/p3filelists.cc b/src/file_sharing/p3filelists.cc index 357c90473..85f470836 100644 --- a/src/file_sharing/p3filelists.cc +++ b/src/file_sharing/p3filelists.cc @@ -1082,6 +1082,11 @@ void p3FileDatabase::addUploadStats(const RsFileHash& hash, uint64_t size) IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_OFTEN); } +void p3FileDatabase::clearUploadStats() +{ + mCumulativeUploaded.clear(); +} + bool p3FileDatabase::removeExtraFile(const RsFileHash& hash) { bool ret = false; diff --git a/src/file_sharing/p3filelists.h b/src/file_sharing/p3filelists.h index 1381096cc..b268c17a9 100644 --- a/src/file_sharing/p3filelists.h +++ b/src/file_sharing/p3filelists.h @@ -176,6 +176,7 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub virtual uint64_t getCumulativeUploadAll() const; virtual uint64_t getCumulativeUploadNum() const; virtual void addUploadStats(const RsFileHash& hash, uint64_t size); + void clearUploadStats(); // interface for hash caching diff --git a/src/ft/ftserver.cc b/src/ft/ftserver.cc index 65061c2ba..980f231fc 100644 --- a/src/ft/ftserver.cc +++ b/src/ft/ftserver.cc @@ -2359,3 +2359,8 @@ uint64_t ftServer::getCumulativeUploadNum() { return mFileDatabase->getCumulativeUploadNum(); } + +void ftServer::clearUploadStats() +{ + return mFileDatabase->clearUploadStats(); +} diff --git a/src/ft/ftserver.h b/src/ft/ftserver.h index 24a954bf4..8567b50fb 100644 --- a/src/ft/ftserver.h +++ b/src/ft/ftserver.h @@ -367,6 +367,7 @@ public: virtual uint64_t getCumulativeUpload(RsFileHash hash); virtual uint64_t getCumulativeUploadAll(); virtual uint64_t getCumulativeUploadNum(); + virtual void clearUploadStats(); /*************** Internal Transfer Fns *************************/ virtual int tick(); diff --git a/src/retroshare/rsfiles.h b/src/retroshare/rsfiles.h index b9f2af4a6..1c28da4e0 100644 --- a/src/retroshare/rsfiles.h +++ b/src/retroshare/rsfiles.h @@ -1216,5 +1216,7 @@ public: virtual uint64_t getCumulativeUploadAll() = 0; virtual uint64_t getCumulativeUploadNum() = 0; + virtual void clearUploadStats() = 0; + virtual ~RsFiles() = default; };