diff --git a/.github/workflows/ci-mingw64.yml b/.github/workflows/ci-mingw64.yml new file mode 100644 index 000000000..28f9f2d32 --- /dev/null +++ b/.github/workflows/ci-mingw64.yml @@ -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 diff --git a/src/chat/distributedchat.cc b/src/chat/distributedchat.cc index e6d770e2a..06abf4159 100644 --- a/src/chat/distributedchat.cc +++ b/src/chat/distributedchat.cc @@ -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 log_delay_histogram(S,0) ; @@ -1150,6 +1158,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. { @@ -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 ; diff --git a/src/file_sharing/p3filelists.cc b/src/file_sharing/p3filelists.cc index a206266b5..85f470836 100644 --- a/src/file_sharing/p3filelists.cc +++ b/src/file_sharing/p3filelists.cc @@ -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& load) ignored_suffixes.push_back( ".part" ); #endif mPrimaryBanList.clear(); + mCumulativeUploaded.clear(); for(std::list::iterator it = load.begin(); it != load.end(); ++it) { @@ -628,6 +650,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 ; } @@ -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; diff --git a/src/file_sharing/p3filelists.h b/src/file_sharing/p3filelists.h index 1ecb3cde9..b268c17a9 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,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 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 41a4b85e4..980f231fc 100644 --- a/src/ft/ftserver.cc +++ b/src/ft/ftserver.cc @@ -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(); +} diff --git a/src/ft/ftserver.h b/src/ft/ftserver.h index 02bae7477..8567b50fb 100644 --- a/src/ft/ftserver.h +++ b/src/ft/ftserver.h @@ -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(); 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; 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 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 diff --git a/src/plugins/pluginmanager.cc b/src/plugins/pluginmanager.cc index 573a81c6a..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; @@ -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 ; 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..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,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 ; 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)) 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/retroshare/rsfiles.h b/src/retroshare/rsfiles.h index 673b73979..1c28da4e0 100644 --- a/src/retroshare/rsfiles.h +++ b/src/retroshare/rsfiles.h @@ -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; }; diff --git a/src/retroshare/rswiki.h b/src/retroshare/rswiki.h index 039164a40..0a797caf7 100644 --- a/src/retroshare/rswiki.h +++ b/src/retroshare/rswiki.h @@ -25,9 +25,12 @@ #include #include #include +#include +#include #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 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 &collections) = 0; -virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) = 0; -virtual bool getComments(const uint32_t &token, std::vector &comments) = 0; + /* GXS Data Access */ + virtual bool getCollections(const uint32_t &token, std::vector &collections) = 0; + virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) = 0; + virtual bool getComments(const uint32_t &token, std::vector &comments) = 0; + virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &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 &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 groupIds, std::vector &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 groupIds, std::vector &groups) = 0; }; #endif 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; } diff --git a/src/services/p3idservice.cc b/src/services/p3idservice.cc index df7cc49b9..d8287a078 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 ; } @@ -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 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); @@ -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 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::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() diff --git a/src/services/p3wiki.cc b/src/services/p3wiki.cc index 9999e4ec5..b00240ca0 100644 --- a/src/services/p3wiki.cc +++ b/src/services/p3wiki.cc @@ -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& 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 event = std::make_shared(wikiEventType); event->mWikiGroupId = change->mGroupId; if (dynamic_cast(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& changes) for(auto change : changes) delete change; } changes.clear(); +} + +/* GXS Data Retrieval Methods */ + +bool p3Wiki::getCollections(const uint32_t &token, std::vector &collections) +{ + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + if(ok) { + for(auto it : grpData) { + RsGxsWikiCollectionItem* item = dynamic_cast(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 &snapshots) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + if(ok) { + for(auto& mit : msgData) { + for(auto vit : mit.second) { + RsGxsWikiSnapshotItem* item = dynamic_cast(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 &snapshots) +{ + GxsMsgRelatedDataMap msgData; + bool ok = RsGenExchange::getMsgRelatedData(token, msgData); + if(ok) { + for(auto& mit : msgData) { + for(auto vit : mit.second) { + RsGxsWikiSnapshotItem* item = dynamic_cast(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 &comments) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + if(ok) { + for(auto& mit : msgData) { + for(auto vit : mit.second) { + RsGxsWikiCommentItem* item = dynamic_cast(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 groupIds, std::vector &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; } \ No newline at end of file diff --git a/src/services/p3wiki.h b/src/services/p3wiki.h index 77e34bfab..0325bc71d 100644 --- a/src/services/p3wiki.h +++ b/src/services/p3wiki.h @@ -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& 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& changes) override; public: + /* GXS Data Access Methods */ + virtual bool getCollections(const uint32_t &token, std::vector &collections) override; + virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) override; + virtual bool getComments(const uint32_t &token, std::vector &comments) override; + virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &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 &collections) override; -virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) override; -virtual bool getComments(const uint32_t &token, std::vector &comments) override; - -virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &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 groupIds, std::vector &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 groupIds, std::vector &groups) override; }; #endif 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; 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!" ; diff --git a/src/util/rsdir.cc b/src/util/rsdir.cc index 2881db460..ede99afdb 100644 --- a/src/util/rsdir.cc +++ b/src/util/rsdir.cc @@ -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;