Merge remote-tracking branch 'upstream_official/master' into HEAD

This commit is contained in:
Salort Alvaro 2026-01-03 15:35:23 +00:00
commit cb57e66e27
26 changed files with 639 additions and 252 deletions

70
.github/workflows/ci-mingw64.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: MINGW64 Windows 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

View File

@ -611,6 +611,14 @@ void DistributedChatService::handleRecvChatLobbyList(RsChatLobbyListItem *item)
void DistributedChatService::addTimeShiftStatistics(int D)
{
// 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)
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<int> log_delay_histogram(S,0) ;
@ -1150,6 +1158,7 @@ void DistributedChatService::handleConnectionChallenge(RsChatLobbyConnectChallen
RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/
for(std::map<ChatLobbyId,ChatLobbyEntry>::iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end() && !found;++it)
if(!IS_PUBLIC_LOBBY(it->second.lobby_flags))
for(std::map<ChatLobbyMsgId,rstime_t>::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.
{
@ -2031,7 +2040,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 ;

View File

@ -377,6 +377,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 */
@ -508,6 +529,7 @@ bool p3FileDatabase::loadList(std::list<RsItem *>& load)
ignored_suffixes.push_back( ".part" );
#endif
mPrimaryBanList.clear();
mCumulativeUploaded.clear();
for(std::list<RsItem *>::iterator it = load.begin(); it != load.end(); ++it)
{
@ -628,6 +650,13 @@ bool p3FileDatabase::loadList(std::list<RsItem *>& load)
mLastPrimaryBanListChangeTimeStamp = time(NULL);
}
RsFileListsUploadStatsItem *fu = dynamic_cast<RsFileListsUploadStatsItem*>(*it) ;
if(fu)
{
mCumulativeUploaded.insert(fu->hash_stats.begin(), fu->hash_stats.end()) ;
}
delete *it ;
}
@ -1004,8 +1033,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) ;
@ -1024,6 +1051,42 @@ 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);
}
void p3FileDatabase::clearUploadStats()
{
mCumulativeUploaded.clear();
}
bool p3FileDatabase::removeExtraFile(const RsFileHash& hash)
{
bool ret = false;

View File

@ -79,6 +79,7 @@ class LocalDirectoryStorage ;
class RsFileListsSyncRequestItem ;
class RsFileListsSyncResponseItem ;
class RsFileListsBannedHashesItem ;
class RsFileListsUploadStatsItem ;
class HashStorage ;
@ -171,6 +172,12 @@ 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);
void clearUploadStats();
// interface for hash caching
void setWatchPeriod(uint32_t seconds);
@ -294,6 +301,8 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
bool mBannedFileListNeedsUpdate;
rstime_t mLastPrimaryBanListChangeTimeStamp;
std::map<RsFileHash, uint64_t> mCumulativeUploaded;
void locked_sendBanInfo(const RsPeerId& pid);
void handleBannedFilesInfo(RsFileListsBannedHashesItem *item);
};

View File

@ -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 ;
}

View File

@ -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<RsFileHash,BannedFileEntry> 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<RsFileHash, uint64_t> hash_stats;
};
class RsFileListsSerialiser : public RsServiceSerializer
{
public:

View File

@ -1316,6 +1316,7 @@ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t
offset += chunk;
tosend -= chunk;
}
mFileDatabase->addUploadStats(hash, chunksize);
/* clean up data */
free(data);
@ -2343,3 +2344,23 @@ std::error_condition ftServer::parseFilesLink(
if(tft) collection = *tft;
return ec;
}
uint64_t ftServer::getCumulativeUpload(RsFileHash hash)
{
return mFileDatabase->getCumulativeUpload(hash);
}
uint64_t ftServer::getCumulativeUploadAll()
{
return mFileDatabase->getCumulativeUploadAll();
}
uint64_t ftServer::getCumulativeUploadNum()
{
return mFileDatabase->getCumulativeUploadNum();
}
void ftServer::clearUploadStats()
{
return mFileDatabase->clearUploadStats();
}

View File

@ -364,6 +364,11 @@ 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();
virtual void clearUploadStats();
/*************** Internal Transfer Fns *************************/
virtual int tick();

View File

@ -1164,46 +1164,45 @@ void p3discovery2::statusChange(const std::list<pqiServicePeer> &plist)
std::cerr << "p3discovery2::statusChange()" << std::endl;
#endif
std::list<pqiServicePeer>::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<RsGossipDiscoveryEvent>();
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<RsGossipDiscoveryEvent>();
ev->mGossipDiscoveryEventType = RsGossipDiscoveryEventType::DISCOVERY_INFO_RECEIVED;
ev->mFromId.clear();
ev->mAboutId = pit->id;
rsEvents->postEvent(ev);
}
}
return;

View File

@ -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

View File

@ -114,7 +114,7 @@ typedef t_ScopeGuard<rnp_ffi_st ,&rnp_ffi_destroy> 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

View File

@ -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<RsSystemEvent>();
ev->mEventCode = RsSystemEventCode::NEW_PLUGIN_FOUND;
@ -321,10 +321,12 @@ 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()
||_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 ;

View File

@ -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)
{

View File

@ -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,14 +1808,17 @@ bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, cons
else
++it ;
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))
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 ;

View File

@ -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))

View File

@ -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<const RsEvent> event ) = 0;
virtual std::error_condition postEvent( std::shared_ptr<const RsEvent> 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<const RsEvent> event ) = 0;
virtual std::error_condition sendEvent( std::shared_ptr<const RsEvent> 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

View File

@ -1212,5 +1212,11 @@ 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 void clearUploadStats() = 0;
virtual ~RsFiles() = default;
};

View File

@ -25,9 +25,12 @@
#include <inttypes.h>
#include <string>
#include <list>
#include <vector>
#include <iostream>
#include "retroshare/rstokenservice.h"
#include "retroshare/rsgxsifacehelper.h"
#include "retroshare/rsevents.h"
/* The Main Interface Class - for information about your Peers */
class RsWiki;
@ -61,40 +64,49 @@ extern RsWiki *rsWiki;
#define FLAG_MSG_TYPE_WIKI_SNAPSHOT 0x0001
#define FLAG_MSG_TYPE_WIKI_COMMENT 0x0002
class CollectionRef
/** Wiki Event Codes */
enum class RsWikiEventCode : uint8_t
{
public:
UPDATED_SNAPSHOT = 0x01,
UPDATED_COLLECTION = 0x02
};
std::string KeyWord;
std::string CollectionId;
/** Specific Wiki Event for UI updates */
struct RsGxsWikiEvent : public RsEvent
{
/* Constructor accepts dynamic event type */
RsGxsWikiEvent(RsEventType type) : RsEvent(type) {}
virtual ~RsGxsWikiEvent() override = default;
RsWikiEventCode mWikiEventCode;
RsGxsGroupId mWikiGroupId;
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override
{
RsEvent::serial_process(j, ctx);
RS_SERIAL_PROCESS(mWikiEventCode);
RS_SERIAL_PROCESS(mWikiGroupId);
}
};
struct RsWikiCollection: RsGxsGenericGroupData
{
public:
std::string mDescription;
std::string mCategory;
std::string mHashTags;
// std::map<std::string, CollectionRef> linkReferences;
};
class RsWikiSnapshot
{
public:
public:
RsMsgMetaData mMeta;
std::string mPage; // all the text is stored here.
std::string mPage;
std::string mHashTags;
};
class RsWikiComment
{
public:
public:
RsMsgMetaData mMeta;
std::string mComment;
};
@ -103,58 +115,26 @@ std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group);
std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot);
std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment);
class RsWiki: public RsGxsIfaceHelper
{
public:
RsWiki(RsGxsIface& gxs): RsGxsIfaceHelper(gxs) {}
virtual ~RsWiki() {}
/* Specific Service Data */
virtual bool getCollections(const uint32_t &token, std::vector<RsWikiCollection> &collections) = 0;
virtual bool getSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) = 0;
virtual bool getComments(const uint32_t &token, std::vector<RsWikiComment> &comments) = 0;
/* GXS Data Access */
virtual bool getCollections(const uint32_t &token, std::vector<RsWikiCollection> &collections) = 0;
virtual bool getSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) = 0;
virtual bool getComments(const uint32_t &token, std::vector<RsWikiComment> &comments) = 0;
virtual bool getRelatedSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) = 0;
virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) = 0;
virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) = 0;
virtual bool submitComment(uint32_t &token, RsWikiComment &comment) = 0;
virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) = 0;
virtual bool getRelatedSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) = 0;
virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) = 0;
virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) = 0;
virtual bool submitComment(uint32_t &token, RsWikiComment &comment) = 0;
virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) = 0;
// Blocking Interfaces.
virtual bool createCollection(RsWikiCollection &collection) = 0;
virtual bool updateCollection(const RsWikiCollection &collection) = 0;
virtual bool getCollections(const std::list<RsGxsGroupId> groupIds, std::vector<RsWikiCollection> &groups) = 0;
};
#include "retroshare/rsevents.h"
enum class RsWikiEventCode : uint8_t
{
UPDATED_SNAPSHOT = 0x01,
UPDATED_COLLECTION = 0x02
};
struct RsGxsWikiEvent : public RsEvent
{
/* Dynamic constructor */
RsGxsWikiEvent(RsEventType type) : RsEvent(type) {}
virtual ~RsGxsWikiEvent() override = default;
RsWikiEventCode mWikiEventCode;
RsGxsGroupId mWikiGroupId;
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override
{
RsEvent::serial_process(j, ctx);
RS_SERIAL_PROCESS(mWikiEventCode);
RS_SERIAL_PROCESS(mWikiGroupId);
}
/* Blocking Interfaces */
virtual bool createCollection(RsWikiCollection &collection) = 0;
virtual bool updateCollection(const RsWikiCollection &collection) = 0;
virtual bool getCollections(const std::list<RsGxsGroupId> groupIds, std::vector<RsWikiCollection> &groups) = 0;
};
#endif

View File

@ -516,7 +516,7 @@ bool p3I2pSam3::startSession()
}
if (ret != 0) {
delete session;
free(session);
session = nullptr;
return false;
}

View File

@ -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<RsGxsId>::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 ;
}
@ -1102,6 +1102,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
@ -2848,7 +2849,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;
}
@ -3162,7 +3163,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
@ -3171,7 +3172,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);
}
@ -3190,15 +3191,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;
}
@ -3302,13 +3303,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);
@ -3484,7 +3485,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?
@ -3746,10 +3747,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.
@ -3805,7 +3806,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.
@ -3918,7 +3919,7 @@ bool p3IdService::pgphash_process()
CacheArbitrationDone(BG_PGPHASH);
return true;
}
SSGxsIdGroup ssdata;
ssdata.load(pg.mMeta.mServiceString); // attempt load - okay if fails.
@ -4251,9 +4252,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;
}
@ -4268,16 +4269,16 @@ bool p3IdService::recogn_handlerequest(uint32_t token)
std::vector<RsGxsGrpItem*> 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<RsGxsGrpItem*>::iterator vit = grpData.begin();
for(; vit != grpData.end(); ++vit)
{
RsGxsIdGroupItem* item = dynamic_cast<RsGxsIdGroupItem*>(*vit);
@ -4292,7 +4293,7 @@ bool p3IdService::recogn_handlerequest(uint32_t token)
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
mRecognGroupsToProcess.push_back(item);
}
else
else
{
delete (*vit);
}
@ -4343,7 +4344,7 @@ bool p3IdService::recogn_process()
CacheArbitrationDone(BG_RECOGN);
return true;
}
std::list<RsGxsRecognTagItem *> tagItems;
@ -4362,13 +4363,13 @@ bool p3IdService::recogn_process()
{
tagValidFlags |= i;
}
else
else
{
isPending |= isTagPending;
}
delete *it;
i *= 2;
i *= 2;
}
#ifdef DEBUG_RECOGN
@ -4396,7 +4397,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.
@ -4422,12 +4423,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))
{
@ -4438,7 +4439,7 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname
return false;
}
// id match.
if (id != item->identity)
{
@ -4448,7 +4449,7 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname
#endif // DEBUG_RECOGN
return false;
}
// nickname match.
if (nickname != item->nickname)
{
@ -4458,14 +4459,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<RsGxsId, RsGxsRecognSignerItem *>::iterator it;
it = mRecognSignKeys.find(item->sign.keyId);
if (it == mRecognSignKeys.end())
@ -4476,16 +4477,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
@ -4494,7 +4495,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)
{
@ -4521,8 +4522,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
@ -4716,7 +4717,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.
@ -4726,7 +4727,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.
@ -4744,14 +4745,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.
@ -4760,12 +4761,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()

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* libretroshare/src/services: p3wiki.h *
* libretroshare/src/services: p3wiki.cc *
* *
* libretroshare: retroshare core library *
* *
@ -46,25 +46,29 @@ uint32_t p3Wiki::wikiAuthenPolicy()
flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN;
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
flag = 0;
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS);
return policy;
}
void p3Wiki::service_tick() {}
void p3Wiki::service_tick()
{
/* Service tick required by RsGenExchange */
}
void p3Wiki::notifyChanges(std::vector<RsGxsNotify*>& changes)
{
if (rsEvents) {
/* Get the same dynamic event type ID used in the GUI */
RsEventType wikiEventType = (RsEventType)rsEvents->getDynamicEventType("GXS_WIKI");
for(auto change : changes) {
/* Create event using the dynamic ID */
std::shared_ptr<RsGxsWikiEvent> event = std::make_shared<RsGxsWikiEvent>(wikiEventType);
event->mWikiGroupId = change->mGroupId;
if (dynamic_cast<RsGxsMsgChange*>(change)) {
event->mWikiEventCode = RsWikiEventCode::UPDATED_SNAPSHOT;
} else {
// This handles new Wikis
event->mWikiEventCode = RsWikiEventCode::UPDATED_COLLECTION;
}
rsEvents->postEvent(event);
@ -74,4 +78,173 @@ void p3Wiki::notifyChanges(std::vector<RsGxsNotify*>& changes)
for(auto change : changes) delete change;
}
changes.clear();
}
/* GXS Data Retrieval Methods */
bool p3Wiki::getCollections(const uint32_t &token, std::vector<RsWikiCollection> &collections)
{
std::vector<RsGxsGrpItem*> grpData;
bool ok = RsGenExchange::getGroupData(token, grpData);
if(ok) {
for(auto it : grpData) {
RsGxsWikiCollectionItem* item = dynamic_cast<RsGxsWikiCollectionItem*>(it);
if (item) {
RsWikiCollection collection = item->collection;
collection.mMeta = item->meta;
collections.push_back(collection);
}
delete it;
}
}
return ok;
}
bool p3Wiki::getSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots)
{
GxsMsgDataMap msgData;
bool ok = RsGenExchange::getMsgData(token, msgData);
if(ok) {
for(auto& mit : msgData) {
for(auto vit : mit.second) {
RsGxsWikiSnapshotItem* item = dynamic_cast<RsGxsWikiSnapshotItem*>(vit);
if(item) {
RsWikiSnapshot snapshot = item->snapshot;
snapshot.mMeta = item->meta;
snapshots.push_back(snapshot);
}
delete vit;
}
}
}
return ok;
}
bool p3Wiki::getRelatedSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots)
{
GxsMsgRelatedDataMap msgData;
bool ok = RsGenExchange::getMsgRelatedData(token, msgData);
if(ok) {
for(auto& mit : msgData) {
for(auto vit : mit.second) {
RsGxsWikiSnapshotItem* item = dynamic_cast<RsGxsWikiSnapshotItem*>(vit);
if(item) {
RsWikiSnapshot snapshot = item->snapshot;
snapshot.mMeta = item->meta;
snapshots.push_back(snapshot);
}
delete vit;
}
}
}
return ok;
}
bool p3Wiki::getComments(const uint32_t &token, std::vector<RsWikiComment> &comments)
{
GxsMsgDataMap msgData;
bool ok = RsGenExchange::getMsgData(token, msgData);
if(ok) {
for(auto& mit : msgData) {
for(auto vit : mit.second) {
RsGxsWikiCommentItem* item = dynamic_cast<RsGxsWikiCommentItem*>(vit);
if(item) {
RsWikiComment comment = item->comment;
comment.mMeta = item->meta;
comments.push_back(comment);
}
delete vit;
}
}
}
return ok;
}
/* Submission Methods */
bool p3Wiki::submitCollection(uint32_t &token, RsWikiCollection &collection)
{
RsGxsWikiCollectionItem* collectionItem = new RsGxsWikiCollectionItem();
collectionItem->collection = collection;
collectionItem->meta = collection.mMeta;
RsGenExchange::publishGroup(token, collectionItem);
return true;
}
bool p3Wiki::submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot)
{
RsGxsWikiSnapshotItem* snapshotItem = new RsGxsWikiSnapshotItem();
snapshotItem->snapshot = snapshot;
snapshotItem->meta = snapshot.mMeta;
snapshotItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_SNAPSHOT;
RsGenExchange::publishMsg(token, snapshotItem);
return true;
}
bool p3Wiki::submitComment(uint32_t &token, RsWikiComment &comment)
{
RsGxsWikiCommentItem* commentItem = new RsGxsWikiCommentItem();
commentItem->comment = comment;
commentItem->meta = comment.mMeta;
commentItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_COMMENT;
RsGenExchange::publishMsg(token, commentItem);
return true;
}
bool p3Wiki::updateCollection(uint32_t &token, RsWikiCollection &group)
{
RsGxsWikiCollectionItem* grpItem = new RsGxsWikiCollectionItem();
grpItem->collection = group;
grpItem->meta = group.mMeta;
RsGenExchange::updateGroup(token, grpItem);
return true;
}
/* Blocking Interfaces */
bool p3Wiki::createCollection(RsWikiCollection &group)
{
uint32_t token;
return submitCollection(token, group) && waitToken(token) == RsTokenService::COMPLETE;
}
bool p3Wiki::updateCollection(const RsWikiCollection &group)
{
uint32_t token;
RsWikiCollection update(group);
return updateCollection(token, update) && waitToken(token) == RsTokenService::COMPLETE;
}
bool p3Wiki::getCollections(const std::list<RsGxsGroupId> groupIds, std::vector<RsWikiCollection> &groups)
{
uint32_t token;
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
if (groupIds.empty()) {
if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) return false;
} else {
if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) return false;
}
return getCollections(token, groups) && !groups.empty();
}
/* Stream operators for debugging */
std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group)
{
out << "RsWikiCollection [ Name: " << group.mMeta.mGroupName << " ]";
return out;
}
std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot)
{
out << "RsWikiSnapshot [ Title: " << shot.mMeta.mMsgName << "]";
return out;
}
std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment)
{
out << "RsWikiComment [ Title: " << comment.mMeta.mMsgName << "]";
return out;
}

View File

@ -36,68 +36,36 @@
*
*/
class p3Wiki: public RsGenExchange, public RsWiki,
public RsTickEvent
class p3Wiki: public RsGenExchange, public RsWiki
{
public:
p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs);
virtual RsServiceInfo getServiceInfo();
static uint32_t wikiAuthenPolicy();
p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs);
virtual RsServiceInfo getServiceInfo() override;
static uint32_t wikiAuthenPolicy();
/* Required by base class */
virtual void service_tick() override;
protected:
virtual void notifyChanges(std::vector<RsGxsNotify*>& changes) ;
// Overloaded from RsTickEvent.
virtual void handle_event(uint32_t event_type, const std::string &elabel);
/* Triggered on GXS updates */
virtual void notifyChanges(std::vector<RsGxsNotify*>& changes) override;
public:
/* GXS Data Access Methods */
virtual bool getCollections(const uint32_t &token, std::vector<RsWikiCollection> &collections) override;
virtual bool getSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) override;
virtual bool getComments(const uint32_t &token, std::vector<RsWikiComment> &comments) override;
virtual bool getRelatedSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) override;
virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) override;
virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) override;
virtual bool submitComment(uint32_t &token, RsWikiComment &comment) override;
virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) override;
void service_tick() override;
/* Specific Service Data */
virtual bool getCollections(const uint32_t &token, std::vector<RsWikiCollection> &collections) override;
virtual bool getSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) override;
virtual bool getComments(const uint32_t &token, std::vector<RsWikiComment> &comments) override;
virtual bool getRelatedSnapshots(const uint32_t &token, std::vector<RsWikiSnapshot> &snapshots) override;
virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) override;
virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) override;
virtual bool submitComment(uint32_t &token, RsWikiComment &comment) override;
virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) override;
// Blocking Interfaces.
virtual bool createCollection(RsWikiCollection &collection) override;
virtual bool updateCollection(const RsWikiCollection &collection) override;
virtual bool getCollections(const std::list<RsGxsGroupId> groupIds, std::vector<RsWikiCollection> &groups) override;
private:
std::string genRandomId();
// RsMutex mWikiMtx;
virtual void generateDummyData();
// Dummy Stuff.
void dummyTick();
bool mAboutActive;
uint32_t mAboutToken;
int mAboutLines;
RsGxsMessageId mAboutThreadId;
bool mImprovActive;
uint32_t mImprovToken;
int mImprovLines;
RsGxsMessageId mImprovThreadId;
bool mMarkdownActive;
uint32_t mMarkdownToken;
int mMarkdownLines;
RsGxsMessageId mMarkdownThreadId;
/* Blocking Interfaces */
virtual bool createCollection(RsWikiCollection &collection) override;
virtual bool updateCollection(const RsWikiCollection &collection) override;
virtual bool getCollections(const std::list<RsGxsGroupId> groupIds, std::vector<RsWikiCollection> &groups) override;
};
#endif

View File

@ -56,7 +56,7 @@ std::error_condition RsEventsService::isEventTypeInvalid(RsEventType eventType)
return RsEventsErrorNum::EVENT_TYPE_UNDEFINED;
if( eventType < RsEventType::__NONE ||
eventType >= static_cast<RsEventType>(mHandlerMaps.size()) )
static_cast<uint32_t>(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<RsEventType>(mHandlerMaps.size());
mHandlerMaps.push_back( std::map<RsEventsHandlerId_t,std::function<void(std::shared_ptr<const RsEvent>)> >());
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

View File

@ -36,10 +36,12 @@ class RsEventsService :
{
public:
RsEventsService():
mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1),
mEventQueueMtx("RsEventsService::mEventQueueMtx") {}
mHandlerMapMtx("RsEventsService::mHandlerMapMtx"),
mLastHandlerId(1),
mHandlerMaps(static_cast<std::size_t>(RsEventType::__MAX)),
mEventQueueMtx("RsEventsService::mEventQueueMtx") {}
/// @see RsEvents
/// @see RsEvents
std::error_condition postEvent(
std::shared_ptr<const RsEvent> 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<void(std::shared_ptr<const RsEvent>)> 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<void(std::shared_ptr<const RsEvent>)> >,
static_cast<std::size_t>(RsEventType::__MAX) + 10
std::function<void(std::shared_ptr<const RsEvent>)> >
> mHandlerMaps;
/** Extra event types registered by plugins */
std::map<std::string,RsEventType> mRegisteredExtraEventTypes;
RsMutex mEventQueueMtx;
std::deque< std::shared_ptr<const RsEvent> > mEventQueue;

View File

@ -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!" ;

View File

@ -520,8 +520,12 @@ bool RsDirUtil::checkDirectory(const std::string& dir)
int val;
mode_t st_mode;
#ifdef WINDOWS_SYS
std::string fixed = dir;
std::wstring wdir;
librs::util::ConvertUtf8ToUtf16(dir, 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;