mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
commit
7646421820
@ -32,7 +32,7 @@ before_install:
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew link --force qt5 ; fi
|
||||
- >
|
||||
if [ $TRAVIS_OS_NAME == osx ]; then
|
||||
brew install openssl miniupnpc rapidjson sqlcipher xapian cmark;
|
||||
brew install openssl miniupnpc rapidjson sqlcipher;
|
||||
fi
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew install p7zip; fi
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then npm install -g appdmg; fi
|
||||
|
@ -855,12 +855,8 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *& ci)
|
||||
{
|
||||
#ifdef RS_DIRECT_CHAT
|
||||
/* notify public chat message */
|
||||
RsServer::notify()->AddPopupMessage(
|
||||
RS_POPUP_GROUPCHAT,
|
||||
ci->PeerId().toStdString(), "", message );
|
||||
RsServer::notify()->AddFeedItem(
|
||||
RS_FEED_ITEM_CHAT_NEW,
|
||||
ci->PeerId().toStdString(), message, "" );
|
||||
RsServer::notify()->AddPopupMessage( RS_POPUP_GROUPCHAT, ci->PeerId().toStdString(), "", message );
|
||||
//RsServer::notify()->AddFeedItem( RS_FEED_ITEM_CHAT_NEW, ci->PeerId().toStdString(), message, "" );
|
||||
#else // def RS_DIRECT_CHAT
|
||||
/* Ignore deprecated direct node broadcast chat messages */
|
||||
return false;
|
||||
|
@ -51,18 +51,13 @@ bool LocalDirectoryUpdater::isEnabled() const
|
||||
}
|
||||
void LocalDirectoryUpdater::setEnabled(bool b)
|
||||
{
|
||||
if(mIsEnabled == b)
|
||||
return ;
|
||||
|
||||
if(!b)
|
||||
shutdown();
|
||||
else if(!isRunning())
|
||||
start("fs dir updater") ;
|
||||
|
||||
mIsEnabled = b ;
|
||||
if(mIsEnabled == b) return;
|
||||
if(!b) RsThread::askForStop();
|
||||
else if(!RsThread::isRunning()) start("fs dir updater");
|
||||
mIsEnabled = b ;
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::data_tick()
|
||||
void LocalDirectoryUpdater::threadTick()
|
||||
{
|
||||
rstime_t now = time(NULL) ;
|
||||
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
bool ignoreDuplicates() const;
|
||||
|
||||
protected:
|
||||
virtual void data_tick() ;
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size);
|
||||
virtual bool hash_confirm(uint32_t client_param) ;
|
||||
|
@ -87,7 +87,7 @@ static std::string friendlyUnit(uint64_t val)
|
||||
return std::string(buf) + " TB";
|
||||
}
|
||||
|
||||
void HashStorage::data_tick()
|
||||
void HashStorage::threadTick()
|
||||
{
|
||||
FileHashJob job;
|
||||
RsFileHash hash;
|
||||
@ -318,14 +318,15 @@ void HashStorage::startHashThread()
|
||||
|
||||
void HashStorage::stopHashThread()
|
||||
{
|
||||
if (mRunning)
|
||||
{
|
||||
std::cerr << "Stopping hashing thread." << std::endl;
|
||||
shutdown();
|
||||
if(mRunning)
|
||||
{
|
||||
RsInfo() << __PRETTY_FUNCTION__ << "Stopping hashing thread."
|
||||
<< std::endl;
|
||||
|
||||
RsThread::askForStop();
|
||||
mRunning = false ;
|
||||
mTotalSizeToHash = 0;
|
||||
mTotalFilesToHash = 0;
|
||||
std::cerr << "done." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,9 +85,7 @@ public:
|
||||
void togglePauseHashingProcess() ;
|
||||
bool hashingProcessPaused();
|
||||
|
||||
// Functions called by the thread
|
||||
|
||||
virtual void data_tick() ;
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& o,const HashStorageInfo& info) ;
|
||||
private:
|
||||
|
@ -209,7 +209,7 @@ void ftController::removeFileSource(const RsFileHash& hash,const RsPeerId& peer_
|
||||
std::cerr << "... not added: hash not found." << std::endl ;
|
||||
#endif
|
||||
}
|
||||
void ftController::data_tick()
|
||||
void ftController::threadTick()
|
||||
{
|
||||
/* check the queues */
|
||||
|
||||
|
@ -109,9 +109,10 @@ class ftPendingRequest
|
||||
};
|
||||
|
||||
|
||||
class ftController: public RsTickingThread, public pqiServiceMonitor, public p3Config
|
||||
class ftController:
|
||||
public RsTickingThread, public pqiServiceMonitor, public p3Config
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
/* Setup */
|
||||
ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId);
|
||||
@ -122,7 +123,7 @@ class ftController: public RsTickingThread, public pqiServiceMonitor, public p3C
|
||||
bool activate();
|
||||
bool isActiveAndNoPending();
|
||||
|
||||
virtual void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
/***************************************************************/
|
||||
/********************** Controller Access **********************/
|
||||
|
@ -47,7 +47,7 @@ ftExtraList::ftExtraList()
|
||||
}
|
||||
|
||||
|
||||
void ftExtraList::data_tick()
|
||||
void ftExtraList::threadTick()
|
||||
{
|
||||
bool todo = false;
|
||||
rstime_t now = time(NULL);
|
||||
|
@ -146,10 +146,7 @@ public:
|
||||
*/
|
||||
void getExtraFileList(std::vector<FileInfo>& files) const ;
|
||||
|
||||
/***
|
||||
* Thread Main Loop
|
||||
**/
|
||||
virtual void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
/***
|
||||
* Configuration - store extra files.
|
||||
|
@ -234,28 +234,28 @@ void ftServer::StartupThreads()
|
||||
void ftServer::StopThreads()
|
||||
{
|
||||
/* stop Dataplex */
|
||||
mFtDataplex->join();
|
||||
mFtDataplex->fullstop();
|
||||
|
||||
/* stop Controller thread */
|
||||
mFtController->join();
|
||||
mFtController->fullstop();
|
||||
|
||||
/* self contained threads */
|
||||
/* stop ExtraList Thread */
|
||||
mFtExtra->join();
|
||||
mFtExtra->fullstop();
|
||||
|
||||
delete (mFtDataplex);
|
||||
mFtDataplex = NULL;
|
||||
mFtDataplex = nullptr;
|
||||
|
||||
delete (mFtController);
|
||||
mFtController = NULL;
|
||||
mFtController = nullptr;
|
||||
|
||||
delete (mFtExtra);
|
||||
mFtExtra = NULL;
|
||||
mFtExtra = nullptr;
|
||||
|
||||
/* stop Monitor Thread */
|
||||
mFileDatabase->stopThreads();
|
||||
delete mFileDatabase;
|
||||
mFileDatabase = NULL ;
|
||||
mFileDatabase = nullptr;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
@ -544,7 +544,7 @@ bool ftTransferModule::isCheckingHash()
|
||||
return mFlag == FT_TM_FLAG_CHECKING || mFlag == FT_TM_FLAG_CHUNK_CRC;
|
||||
}
|
||||
|
||||
class HashThread: public RsSingleJobThread
|
||||
class HashThread: public RsThread
|
||||
{
|
||||
public:
|
||||
explicit HashThread(ftFileCreator *m)
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
Status stat;
|
||||
};
|
||||
|
||||
class ftTransferModule
|
||||
class ftTransferModule
|
||||
{
|
||||
public:
|
||||
ftTransferModule(ftFileCreator *fc, ftDataMultiplex *dm, ftController *c);
|
||||
|
@ -32,7 +32,6 @@
|
||||
/****
|
||||
* #define P3DISC_DEBUG 1
|
||||
****/
|
||||
#define P3DISC_DEBUG 1
|
||||
|
||||
/*extern*/ std::shared_ptr<RsGossipDiscovery> rsGossipDiscovery(nullptr);
|
||||
|
||||
@ -951,11 +950,9 @@ void p3discovery2::processContactInfo(const RsPeerId &fromId, const RsDiscContac
|
||||
return ; // fresh information here.
|
||||
|
||||
bool should_notify_discovery = false;
|
||||
auto sit= it->second.mSslIds.find(item->sslId);
|
||||
|
||||
DiscSslInfo& sslInfo(it->second.mSslIds[item->sslId]); // This line inserts the entry while not removing already existing data
|
||||
// do not remove it!
|
||||
|
||||
if (!mPeerMgr->isFriend(item->sslId))
|
||||
{
|
||||
should_notify_discovery = true;
|
||||
|
@ -132,7 +132,7 @@ bool RsGenExchange::getGroupServerUpdateTS(const RsGxsGroupId& gid, rstime_t& gr
|
||||
return mNetService->getGroupServerUpdateTS(gid,grp_server_update_TS,msg_server_update_TS) ;
|
||||
}
|
||||
|
||||
void RsGenExchange::data_tick()
|
||||
void RsGenExchange::threadTick()
|
||||
{
|
||||
static const double timeDelta = 0.1; // slow tick in sec
|
||||
|
||||
@ -163,10 +163,25 @@ void RsGenExchange::tick()
|
||||
|
||||
processRoutingClues() ;
|
||||
|
||||
if(!mNotifications.empty())
|
||||
{
|
||||
notifyChanges(mNotifications);
|
||||
mNotifications.clear();
|
||||
std::vector<RsGxsNotify*> mNotifications_copy;
|
||||
|
||||
// make a non-deep copy of mNotifications so that it can be passed off-mutex to notifyChanged()
|
||||
// that will delete it. The potential high cost of notifyChanges() makes it preferable to call off-mutex.
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx);
|
||||
if(!mNotifications.empty())
|
||||
{
|
||||
mNotifications_copy = mNotifications;
|
||||
mNotifications.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Calling notifyChanges() calls back RsGxsIfaceHelper::receiveChanges() that deletes the pointers in the array
|
||||
// and the array itself. This is pretty bad and we should normally delete the changes here.
|
||||
|
||||
if(!mNotifications_copy.empty())
|
||||
notifyChanges(mNotifications_copy);
|
||||
}
|
||||
|
||||
// implemented service tick function
|
||||
@ -1118,38 +1133,25 @@ void RsGenExchange::receiveChanges(std::vector<RsGxsNotify*>& changes)
|
||||
if((mc = dynamic_cast<RsGxsMsgChange*>(n)) != nullptr)
|
||||
{
|
||||
if (mc->metaChange())
|
||||
{
|
||||
addMessageChanged(out.mMsgsMeta, mc->msgChangeMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
addMessageChanged(out.mMsgs, mc->msgChangeMap);
|
||||
}
|
||||
}
|
||||
else if((gc = dynamic_cast<RsGxsGroupChange*>(n)) != nullptr)
|
||||
{
|
||||
if(gc->metaChange())
|
||||
{
|
||||
out.mGrpsMeta.splice(out.mGrpsMeta.end(), gc->mGrpIdList);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.mGrps.splice(out.mGrps.end(), gc->mGrpIdList);
|
||||
}
|
||||
}
|
||||
else if(( gt =
|
||||
dynamic_cast<RsGxsDistantSearchResultChange*>(n) ) != nullptr)
|
||||
{
|
||||
else if(( gt = dynamic_cast<RsGxsDistantSearchResultChange*>(n) ) != nullptr)
|
||||
out.mDistantSearchReqs.push_back(gt->mRequestId);
|
||||
}
|
||||
else
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Unknown changes type!"
|
||||
<< std::endl;
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Unknown changes type!" << std::endl;
|
||||
delete n;
|
||||
}
|
||||
changes.clear() ;
|
||||
|
||||
RsServer::notify()->notifyGxsChange(out);
|
||||
if(rsEvents) rsEvents->postEvent(std::move(evt));
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ public:
|
||||
*/
|
||||
RsTokenService* getTokenService();
|
||||
|
||||
virtual void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
/*!
|
||||
* Policy bit pattern portion
|
||||
|
@ -1981,7 +1981,7 @@ bool RsGxsNetService::locked_processTransac(RsNxsTransacItem *item)
|
||||
return false;
|
||||
}
|
||||
|
||||
void RsGxsNetService::data_tick()
|
||||
void RsGxsNetService::threadTick()
|
||||
{
|
||||
static const double timeDelta = 0.5;
|
||||
|
||||
|
@ -76,7 +76,8 @@ struct GroupRequestRecord
|
||||
* Incoming transaction are in 3 different states
|
||||
* 1. START 2. RECEIVING 3. END
|
||||
*/
|
||||
class RsGxsNetService : public RsNetworkExchangeService, public p3ThreadedService, public p3Config
|
||||
class RsGxsNetService :
|
||||
public RsNetworkExchangeService, public p3ThreadedService, public p3Config
|
||||
{
|
||||
public:
|
||||
|
||||
@ -207,10 +208,8 @@ public:
|
||||
*/
|
||||
int tick();
|
||||
|
||||
/*!
|
||||
* Processes transactions and job queue
|
||||
*/
|
||||
virtual void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
|
@ -726,7 +726,7 @@ void RsGxsNetTunnelService::generateEncryptionKey(const RsGxsGroupId& group_id,c
|
||||
// Service parts //
|
||||
//===========================================================================================================================================//
|
||||
|
||||
void RsGxsNetTunnelService::data_tick()
|
||||
void RsGxsNetTunnelService::threadTick()
|
||||
{
|
||||
while(!mPendingTurtleItems.empty())
|
||||
{
|
||||
|
@ -103,7 +103,9 @@
|
||||
class RsGxsNetTunnelItem ;
|
||||
class RsNetworkExchangeService ;
|
||||
|
||||
class RsGxsNetTunnelService: public RsTurtleClientService, public RsTickingThread, public p3Config, public RsGxsDistSync
|
||||
class RsGxsNetTunnelService:
|
||||
public RsTurtleClientService, public RsTickingThread, public p3Config,
|
||||
public RsGxsDistSync
|
||||
{
|
||||
public:
|
||||
RsGxsNetTunnelService() ;
|
||||
@ -196,9 +198,7 @@ public:
|
||||
virtual bool receiveSearchRequest(unsigned char *search_request_data, uint32_t search_request_data_len, unsigned char *& search_result_data, uint32_t& search_result_data_len, uint32_t &max_allowed_hits);
|
||||
virtual void receiveSearchResult(TurtleSearchRequestId request_id,unsigned char *search_result_data,uint32_t search_result_data_len);
|
||||
|
||||
// Overloaded from RsTickingThread
|
||||
|
||||
void data_tick() ;
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
// Overloads p3Config
|
||||
|
||||
|
@ -183,7 +183,7 @@ private:
|
||||
* Checks the integrity message and groups
|
||||
* in rsDataService using computed hash
|
||||
*/
|
||||
class RsGxsIntegrityCheck : public RsSingleJobThread
|
||||
class RsGxsIntegrityCheck : public RsThread
|
||||
{
|
||||
|
||||
enum CheckState { CheckStart, CheckChecking };
|
||||
|
@ -434,8 +434,7 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
|
||||
totalMessageSizeAndCount[msg->metaData->mAuthorId].count++;
|
||||
delete msg;
|
||||
|
||||
if(item != NULL)
|
||||
delete item ;
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,15 +288,15 @@ private:
|
||||
|
||||
void notifyClientService(const OutgoingRecord& pr);
|
||||
|
||||
/*!
|
||||
* Checks the integrity message and groups
|
||||
*/
|
||||
class GxsTransIntegrityCleanupThread : public RsSingleJobThread
|
||||
/// Checks the integrity message and groups
|
||||
class GxsTransIntegrityCleanupThread : public RsThread
|
||||
{
|
||||
enum CheckState { CheckStart, CheckChecking };
|
||||
|
||||
public:
|
||||
explicit GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService),mMtx("GxsTransIntegrityCheck") { mDone=false;}
|
||||
explicit GxsTransIntegrityCleanupThread(
|
||||
RsGeneralDataService* const dataService ):
|
||||
mDs(dataService), mMtx("GxsTransIntegrityCheck"), mDone(false) {}
|
||||
|
||||
bool isDone();
|
||||
void run();
|
||||
@ -312,7 +312,7 @@ private:
|
||||
|
||||
GxsMsgReq mMsgToDel ;
|
||||
std::map<RsGxsId,MsgSizeCount> total_message_size_and_count;
|
||||
bool mDone ;
|
||||
bool mDone;
|
||||
};
|
||||
|
||||
// Overloaded from RsGenExchange.
|
||||
|
@ -1296,7 +1296,9 @@ bool p3GxsTunnelService::locked_sendEncryptedTunnelData(RsGxsTunnelItem *item)
|
||||
}
|
||||
if(it->second.status != RS_GXS_TUNNEL_STATUS_CAN_TALK)
|
||||
{
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << "(EE) Cannot talk to tunnel id " << tunnel_id << ". Tunnel status is: " << it->second.status << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* RetroShare JSON API
|
||||
*
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the
|
||||
@ -588,19 +589,12 @@ bool JsonApiServer::restart()
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsonApiServer::onStopRequested()
|
||||
{ if(mService->is_up()) mService->stop(); }
|
||||
|
||||
bool JsonApiServer::fullstop()
|
||||
{
|
||||
if(!mService->is_up()) return true;
|
||||
|
||||
mService->stop();
|
||||
RsThread::ask_for_stop();
|
||||
|
||||
while(isRunning())
|
||||
{
|
||||
RsDbg() << __PRETTY_FUNCTION__ << " shutting down JSON API service."
|
||||
<< std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
RsThread::fullstop();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -610,7 +604,7 @@ void JsonApiServer::setBindingAddress(const std::string& bindAddress)
|
||||
{ mBindingAddress = bindAddress; }
|
||||
std::string JsonApiServer::getBindingAddress() const { return mBindingAddress; }
|
||||
|
||||
void JsonApiServer::runloop()
|
||||
void JsonApiServer::run()
|
||||
{
|
||||
auto settings = std::make_shared<restbed::Settings>();
|
||||
settings->set_port(mListeningPort);
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* RetroShare JSON API
|
||||
*
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the
|
||||
@ -139,7 +140,14 @@ public:
|
||||
const std::function<bool(const std::string&, const std::string&)>&
|
||||
callback );
|
||||
|
||||
protected:
|
||||
/// @see RsThread
|
||||
void onStopRequested() override;
|
||||
|
||||
private:
|
||||
/// @see RsThread
|
||||
void run() override;
|
||||
|
||||
/// @see p3Config::setupSerialiser
|
||||
RsSerialiser* setupSerialiser() override;
|
||||
|
||||
@ -184,9 +192,6 @@ private:
|
||||
std::reference_wrapper<const JsonApiResourceProvider>,
|
||||
std::less<const JsonApiResourceProvider> > mResourceProviders;
|
||||
|
||||
/// @see RsThread
|
||||
void runloop() override;
|
||||
|
||||
std::shared_ptr<restbed::Service> mService;
|
||||
|
||||
uint16_t mListeningPort;
|
||||
|
@ -495,7 +495,8 @@ HEADERS += util/folderiterator.h \
|
||||
util/rsdeprecate.h \
|
||||
util/cxx11retrocompat.h \
|
||||
util/cxx17retrocompat.h \
|
||||
util/rsurl.h
|
||||
util/rsurl.h \
|
||||
util/rserrno.h
|
||||
|
||||
SOURCES += ft/ftchunkmap.cc \
|
||||
ft/ftcontroller.cc \
|
||||
@ -634,7 +635,8 @@ SOURCES += util/folderiterator.cc \
|
||||
util/rstickevent.cc \
|
||||
util/rsrecogn.cc \
|
||||
util/rstime.cc \
|
||||
util/rsurl.cc
|
||||
util/rsurl.cc \
|
||||
util/rserrno.cc
|
||||
|
||||
equals(RS_UPNP_LIB, miniupnpc) {
|
||||
HEADERS += rs_upnp/upnputil.h rs_upnp/upnphandler_miniupnp.h
|
||||
|
@ -116,11 +116,11 @@ void AuthGPG::init(
|
||||
|
||||
void AuthGPG::exit()
|
||||
{
|
||||
if(_instance != NULL)
|
||||
if(_instance)
|
||||
{
|
||||
_instance->join();
|
||||
delete _instance ;
|
||||
_instance = NULL;
|
||||
_instance->fullstop();
|
||||
delete _instance;
|
||||
_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ int AuthGPG::GPGInit(const RsPgpId &ownId)
|
||||
{
|
||||
}
|
||||
|
||||
void AuthGPG::data_tick()
|
||||
void AuthGPG::threadTick()
|
||||
{
|
||||
rstime::rs_usleep(100 * 1000); //100 msec
|
||||
|
||||
|
@ -239,7 +239,7 @@ public:
|
||||
virtual bool loadList(std::list<RsItem *>& load);
|
||||
/*****************************************************************/
|
||||
|
||||
private:
|
||||
private:
|
||||
// Gets the certificate pointer and returns NULL if the string is invalid, or the
|
||||
// cert was not found.
|
||||
//
|
||||
@ -271,10 +271,9 @@ public:
|
||||
bool printAllKeys_locked();
|
||||
bool printOwnKeys_locked();
|
||||
|
||||
/* own thread */
|
||||
virtual void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
static AuthGPG *instance_gpg; // pointeur vers le singleton
|
||||
|
||||
|
@ -1186,11 +1186,13 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx)
|
||||
|
||||
RsErr() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl;
|
||||
|
||||
if(rsEvents)
|
||||
{
|
||||
ev->mErrorMsg = errMsg;
|
||||
rsEvents->postEvent(std::move(ev));
|
||||
}
|
||||
// if(rsEvents)
|
||||
// {
|
||||
// ev->mErrorMsg = errMsg;
|
||||
// ev->mErrorCode = RsAuthSslConnectionAutenticationEvent::NO_CERTIFICATE_SUPPLIED;
|
||||
//
|
||||
// rsEvents->postEvent(std::move(ev));
|
||||
// }
|
||||
|
||||
return verificationFailed;
|
||||
}
|
||||
@ -1217,8 +1219,11 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx)
|
||||
if(rsEvents)
|
||||
{
|
||||
ev->mSslCn = sslCn;
|
||||
ev->mSslId = sslId;
|
||||
ev->mPgpId = pgpId;
|
||||
ev->mErrorMsg = errMsg;
|
||||
ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO;
|
||||
|
||||
rsEvents->postEvent(std::move(ev));
|
||||
}
|
||||
|
||||
@ -1237,6 +1242,8 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx)
|
||||
ev->mSslId = sslId;
|
||||
ev->mSslCn = sslCn;
|
||||
ev->mErrorMsg = errMsg;
|
||||
ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO;
|
||||
|
||||
rsEvents->postEvent(std::move(ev));
|
||||
}
|
||||
|
||||
@ -1266,6 +1273,7 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx)
|
||||
ev->mSslCn = sslCn;
|
||||
ev->mPgpId = pgpId;
|
||||
ev->mErrorMsg = errorMsg;
|
||||
ev->mErrorCode = RsAuthSslError::MISMATCHED_PGP_ID;
|
||||
rsEvents->postEvent(std::move(ev));
|
||||
}
|
||||
|
||||
@ -1290,12 +1298,29 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx)
|
||||
ev->mSslId = sslId;
|
||||
ev->mSslCn = sslCn;
|
||||
ev->mPgpId = pgpId;
|
||||
|
||||
switch(auth_diagnostic)
|
||||
{
|
||||
case RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN:
|
||||
ev->mErrorCode = RsAuthSslError::NOT_A_FRIEND;
|
||||
break;
|
||||
case RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE:
|
||||
ev->mErrorCode = RsAuthSslError::PGP_SIGNATURE_VALIDATION_FAILED;
|
||||
break;
|
||||
default:
|
||||
ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
ev->mErrorMsg = errMsg;
|
||||
rsEvents->postEvent(std::move(ev));
|
||||
}
|
||||
|
||||
return verificationFailed;
|
||||
}
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cerr << "******* VerifyX509Callback cert: " << std::hex << ctx->cert <<std::dec << std::endl;
|
||||
#endif
|
||||
|
||||
if ( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) )
|
||||
{
|
||||
@ -1311,28 +1336,20 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx)
|
||||
ev->mSslCn = sslCn;
|
||||
ev->mPgpId = pgpId;
|
||||
ev->mErrorMsg = errMsg;
|
||||
ev->mErrorCode = RsAuthSslError::NOT_A_FRIEND;
|
||||
rsEvents->postEvent(std::move(ev));
|
||||
}
|
||||
|
||||
return verificationFailed;
|
||||
}
|
||||
|
||||
setCurrentConnectionAttemptInfo(pgpId, sslId, sslCn);
|
||||
//setCurrentConnectionAttemptInfo(pgpId, sslId, sslCn);
|
||||
LocalStoreCert(x509Cert);
|
||||
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " authentication successfull for "
|
||||
<< "sslId: " << sslId << " isSslOnlyFriend: " << isSslOnlyFriend
|
||||
<< std::endl;
|
||||
|
||||
if(rsEvents)
|
||||
{
|
||||
ev->mSuccess = true;
|
||||
ev->mSslId = sslId;
|
||||
ev->mSslCn = sslCn;
|
||||
ev->mPgpId = pgpId;
|
||||
rsEvents->postEvent(std::move(ev));
|
||||
}
|
||||
|
||||
return verificationSuccess;
|
||||
}
|
||||
|
||||
@ -1583,32 +1600,6 @@ bool AuthSSLimpl::decrypt(void *&out, int &outlen, const void *in, int inlen)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
/********************* Cert Search / Add / Remove **************************/
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
|
||||
void AuthSSLimpl::setCurrentConnectionAttemptInfo(const RsPgpId& gpg_id,const RsPeerId& ssl_id,const std::string& ssl_cn)
|
||||
{
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cerr << "AuthSSL: registering connection attempt from:" << std::endl;
|
||||
std::cerr << " GPG id: " << gpg_id << std::endl;
|
||||
std::cerr << " SSL id: " << ssl_id << std::endl;
|
||||
std::cerr << " SSL cn: " << ssl_cn << std::endl;
|
||||
#endif
|
||||
_last_gpgid_to_connect = gpg_id ;
|
||||
_last_sslid_to_connect = ssl_id ;
|
||||
_last_sslcn_to_connect = ssl_cn ;
|
||||
}
|
||||
void AuthSSLimpl::getCurrentConnectionAttemptInfo(RsPgpId& gpg_id,RsPeerId& ssl_id,std::string& ssl_cn)
|
||||
{
|
||||
gpg_id = _last_gpgid_to_connect ;
|
||||
ssl_id = _last_sslid_to_connect ;
|
||||
ssl_cn = _last_sslcn_to_connect ;
|
||||
}
|
||||
|
||||
/* Locked search -> internal help function */
|
||||
bool AuthSSLimpl::locked_FindCert(const RsPeerId& id, X509** cert)
|
||||
{
|
||||
@ -1785,9 +1776,6 @@ bool AuthSSLimpl::loadList(std::list<RsItem*>& load)
|
||||
return true;
|
||||
}
|
||||
|
||||
RsAuthSslConnectionAutenticationEvent::RsAuthSslConnectionAutenticationEvent() :
|
||||
RsEvent(RsEventType::AUTHSSL_CONNECTION_AUTENTICATION), mSuccess(false) {}
|
||||
|
||||
const EVP_PKEY*RsX509Cert::getPubKey(const X509& x509)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
|
@ -52,34 +52,6 @@ RsPeerId getCertSslId(const X509& x509);
|
||||
const EVP_PKEY* getPubKey(const X509& x509);
|
||||
};
|
||||
|
||||
/**
|
||||
* Event triggered by AuthSSL when authentication of a connection attempt either
|
||||
* fail or success
|
||||
*/
|
||||
struct RsAuthSslConnectionAutenticationEvent : RsEvent
|
||||
{
|
||||
RsAuthSslConnectionAutenticationEvent();
|
||||
|
||||
bool mSuccess;
|
||||
RsPeerId mSslId;
|
||||
std::string mSslCn;
|
||||
RsPgpId mPgpId;
|
||||
std::string mErrorMsg;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mSuccess);
|
||||
RS_SERIAL_PROCESS(mSslId);
|
||||
RS_SERIAL_PROCESS(mSslCn);
|
||||
RS_SERIAL_PROCESS(mPgpId);
|
||||
RS_SERIAL_PROCESS(mErrorMsg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is an implementation of SSL certificate authentication with PGP
|
||||
* signatures, instead of centralized certification authority.
|
||||
@ -165,13 +137,6 @@ public:
|
||||
/// SSL specific functions used in pqissl/pqissllistener
|
||||
virtual SSL_CTX* getCTX() = 0;
|
||||
|
||||
virtual void setCurrentConnectionAttemptInfo(
|
||||
const RsPgpId& gpg_id, const RsPeerId& ssl_id,
|
||||
const std::string& ssl_cn ) = 0;
|
||||
virtual void getCurrentConnectionAttemptInfo(
|
||||
RsPgpId& gpg_id, RsPeerId& ssl_id, std::string& ssl_cn ) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* This function parse X509 certificate from the file and return some
|
||||
* verified informations, like ID and signer
|
||||
@ -258,14 +223,6 @@ public:
|
||||
/* SSL specific functions used in pqissl/pqissllistener */
|
||||
SSL_CTX* getCTX() override;
|
||||
|
||||
/* Restored these functions: */
|
||||
void setCurrentConnectionAttemptInfo(
|
||||
const RsPgpId& gpg_id, const RsPeerId& ssl_id,
|
||||
const std::string& ssl_cn ) override;
|
||||
void getCurrentConnectionAttemptInfo(
|
||||
RsPgpId& gpg_id, RsPeerId& ssl_id, std::string& ssl_cn ) override;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool LocalStoreCert(X509* x509);
|
||||
|
@ -473,27 +473,20 @@ void p3LinkMgrIMPL::tickMonitors()
|
||||
#endif
|
||||
|
||||
/* notify GUI */
|
||||
if (peer.actions & RS_PEER_CONNECTED)
|
||||
if (rsEvents && (peer.actions & RS_PEER_CONNECTED))
|
||||
{
|
||||
p3Notify *notify = RsServer::notify();
|
||||
|
||||
if (notify)
|
||||
{
|
||||
// normally these two below should disappear: there's no notion of popup in libretroshare.
|
||||
// all GUI-type display features should be chosen in NotifyQt.
|
||||
notify->AddPopupMessage(RS_POPUP_CONNECT, peer.id.toStdString(),"", "Online: ");
|
||||
notify->AddFeedItem(RS_FEED_ITEM_PEER_CONNECT, peer.id.toStdString());
|
||||
|
||||
notify->notifyPeerConnected(peer.id.toStdString());
|
||||
}
|
||||
auto e = std::make_shared<RsConnectionEvent>();
|
||||
e->mConnectionInfoCode = RsConnectionEventCode::PEER_CONNECTED;
|
||||
e->mSslId = peer.id;
|
||||
rsEvents->postEvent(e);
|
||||
}
|
||||
if (peer.actions & RS_PEER_DISCONNECTED)
|
||||
if (rsEvents && (peer.actions & RS_PEER_DISCONNECTED))
|
||||
{
|
||||
p3Notify *notify = RsServer::notify();
|
||||
|
||||
if (notify)
|
||||
notify->notifyPeerDisconnected(peer.id.toStdString());
|
||||
}
|
||||
auto e = std::make_shared<RsConnectionEvent>();
|
||||
e->mConnectionInfoCode = RsConnectionEventCode::PEER_DISCONNECTED;
|
||||
e->mSslId = peer.id;
|
||||
rsEvents->postEvent(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,8 +217,6 @@ void p3Notify::notifyChatLobbyEvent(uint64_t lobby_id, uint32_t event_type,const
|
||||
void p3Notify::notifyListPreChange(int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListPreChange(list,type) ; }
|
||||
void p3Notify::notifyListChange (int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListChange (list,type) ; }
|
||||
|
||||
void p3Notify::notifyPeerConnected (const std::string& peer_id) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerConnected(peer_id); }
|
||||
void p3Notify::notifyPeerDisconnected (const std::string& peer_id) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerDisconnected(peer_id); }
|
||||
void p3Notify::notifyErrorMsg (int list, int sev, std::string msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyErrorMsg(list,sev,msg) ; }
|
||||
void p3Notify::notifyChatMessage (const ChatMessage &msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatMessage(msg) ; }
|
||||
void p3Notify::notifyChatStatus (const ChatId& chat_id, const std::string& status_string) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatStatus(chat_id,status_string) ; }
|
||||
@ -235,8 +233,6 @@ void p3Notify::notifyOwnAvatarChanged ()
|
||||
void p3Notify::notifyOwnStatusMessageChanged() { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyOwnStatusMessageChanged() ; }
|
||||
void p3Notify::notifyDiskFull (uint32_t location , uint32_t size_limit_in_MB ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiskFull (location,size_limit_in_MB) ; }
|
||||
void p3Notify::notifyPeerStatusChanged (const std::string& peer_id , uint32_t status ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChanged (peer_id,status) ; }
|
||||
void p3Notify::notifyGxsChange (const RsGxsChanges& changes) {FOR_ALL_NOTIFY_CLIENTS (*it)->notifyGxsChange(changes) ;}
|
||||
void p3Notify::notifyConnectionWithoutCert () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyConnectionWithoutCert(); }
|
||||
|
||||
void p3Notify::notifyPeerStatusChangedSummary () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChangedSummary() ; }
|
||||
void p3Notify::notifyDiscInfoChanged () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiscInfoChanged () ; }
|
||||
|
@ -91,8 +91,6 @@ class p3Notify: public RsNotify
|
||||
|
||||
// Notifications of clients. Can be called from anywhere inside libretroshare.
|
||||
//
|
||||
void notifyPeerConnected (const std::string& /* peer_id */);
|
||||
void notifyPeerDisconnected (const std::string& /* peer_id */);
|
||||
void notifyListPreChange (int /* list */, int /* type */) ;
|
||||
void notifyListChange (int /* list */, int /* type */) ;
|
||||
void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) ;
|
||||
@ -111,7 +109,6 @@ class p3Notify: public RsNotify
|
||||
void notifyOwnStatusMessageChanged () ;
|
||||
void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) ;
|
||||
void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) ;
|
||||
void notifyGxsChange (const RsGxsChanges& /* changes */);
|
||||
void notifyConnectionWithoutCert ();
|
||||
|
||||
void notifyPeerStatusChangedSummary () ;
|
||||
|
@ -1804,12 +1804,24 @@ bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, cons
|
||||
|
||||
// Notify for every friend that has reported a wrong external address, except if that address is in the IP whitelist.
|
||||
|
||||
if((rsBanList!=NULL && !rsBanList->isAddressAccepted(addr_filtered,RSBANLIST_CHECKING_FLAGS_WHITELIST)) && (!sockaddr_storage_sameip(own_addr,addr_filtered)))
|
||||
{
|
||||
std::cerr << " Peer " << from << " reports a connection address (" << sockaddr_storage_iptostring(addr_filtered) <<") that is not your current external address (" << sockaddr_storage_iptostring(own_addr) << "). This is weird." << std::endl;
|
||||
if((rsBanList && !rsBanList->isAddressAccepted(addr_filtered, RSBANLIST_CHECKING_FLAGS_WHITELIST))
|
||||
&& !sockaddr_storage_sameip(own_addr, addr_filtered) )
|
||||
{
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " Peer " << from
|
||||
<< " reports a connection address (" << addr_filtered
|
||||
<<") that is not your current external address ("
|
||||
<< own_addr << "). This is weird." << std::endl;
|
||||
|
||||
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, from.toStdString(), sockaddr_storage_iptostring(own_addr), sockaddr_storage_iptostring(addr));
|
||||
}
|
||||
if(rsEvents)
|
||||
{
|
||||
auto ev = std::make_shared<RsConnectionEvent>();
|
||||
ev->mSslId = from;
|
||||
ev->mOwnLocator = RsUrl(own_addr);
|
||||
ev->mReportedLocator = RsUrl(addr);
|
||||
ev->mConnectionInfoCode = RsConnectionEventCode::PEER_REPORTS_WRONG_IP;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
// we could also sweep over all connected friends and see if some report a different address.
|
||||
|
||||
|
@ -366,9 +366,9 @@ int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState,
|
||||
<< " CONNECT_FAILED->marking so!" << std::endl;
|
||||
#endif
|
||||
|
||||
activepqi->shutdown(); // STOP THREAD.
|
||||
activepqi->askForStop(); // STOP THREAD.
|
||||
active = false;
|
||||
activepqi = NULL;
|
||||
activepqi = nullptr;
|
||||
}
|
||||
#ifdef PERSON_DEBUG
|
||||
else
|
||||
@ -406,7 +406,7 @@ int pqiperson::reset_locked()
|
||||
std::map<uint32_t, pqiconnect *>::iterator it;
|
||||
for(it = kids.begin(); it != kids.end(); ++it)
|
||||
{
|
||||
(it->second) -> shutdown(); // STOP THREAD.
|
||||
it->second->askForStop(); // STOP THREAD.
|
||||
(it->second) -> reset();
|
||||
}
|
||||
|
||||
|
@ -1096,8 +1096,7 @@ int pqissl::SSL_Connection_Complete()
|
||||
if (err != 1)
|
||||
{
|
||||
int serr = SSL_get_error(ssl_connection, err);
|
||||
if ((serr == SSL_ERROR_WANT_READ)
|
||||
|| (serr == SSL_ERROR_WANT_WRITE))
|
||||
if ((serr == SSL_ERROR_WANT_READ) || (serr == SSL_ERROR_WANT_WRITE))
|
||||
{
|
||||
#ifdef PQISSL_LOG_DEBUG
|
||||
rslog(RSL_DEBUG_BASIC, pqisslzone,
|
||||
@ -1108,6 +1107,14 @@ int pqissl::SSL_Connection_Complete()
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(rsEvents)
|
||||
{
|
||||
X509 *x509 = SSL_get_peer_certificate(ssl_connection);
|
||||
auto ev = std::make_shared<RsAuthSslConnectionAutenticationEvent>();
|
||||
ev->mSslId = RsX509Cert::getCertSslId(*x509);
|
||||
ev->mErrorCode = RsAuthSslError::PEER_REFUSED_CONNECTION;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
|
||||
std::string out;
|
||||
rs_sprintf(out, "pqissl::SSL_Connection_Complete()\nIssues with SSL Connect(%d)!\n", err);
|
||||
@ -1253,10 +1260,12 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL)
|
||||
checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST;
|
||||
|
||||
if(rsBanList && !rsBanList->isAddressAccepted(
|
||||
foreign_addr, checking_flags, check_result ))
|
||||
if( RsX509Cert::getCertSslId(*SSL_get_peer_certificate(ssl)) != PeerId())
|
||||
std::cerr << "(EE) pqissl::accept_locked(): PeerId() is " << PeerId() << " but certificate ID is " << RsX509Cert::getCertSslId(*SSL_get_peer_certificate(ssl)) << std::endl;
|
||||
|
||||
if(rsBanList && !rsBanList->isAddressAccepted( foreign_addr, checking_flags, check_result ))
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__
|
||||
RsInfo() << __PRETTY_FUNCTION__
|
||||
<< " Refusing incoming SSL connection from blacklisted "
|
||||
<< "foreign address " << foreign_addr
|
||||
<< ". Reason: " << check_result << ". This should never happen "
|
||||
@ -1264,11 +1273,16 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
RsServer::notify()->AddFeedItem(
|
||||
RS_FEED_ITEM_SEC_IP_BLACKLISTED,
|
||||
PeerId().toStdString(),
|
||||
sockaddr_storage_iptostring(foreign_addr), "", "",
|
||||
check_result);
|
||||
if(rsEvents)
|
||||
{
|
||||
X509 *x509 = SSL_get_peer_certificate(ssl);
|
||||
auto ev = std::make_shared<RsAuthSslConnectionAutenticationEvent>();
|
||||
ev->mSslId = RsX509Cert::getCertSslId(*x509);
|
||||
ev->mLocator = RsUrl(foreign_addr);
|
||||
ev->mErrorCode = RsAuthSslError::IP_IS_BLACKLISTED;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
|
||||
reset_locked();
|
||||
return failure;
|
||||
}
|
||||
@ -1324,7 +1338,7 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
/* shutdown existing - in all cases use the new one */
|
||||
if ((ssl_connection) && (ssl_connection != ssl))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__
|
||||
RsInfo() << __PRETTY_FUNCTION__
|
||||
<< " closing Previous/Existing ssl_connection" << std::endl;
|
||||
SSL_shutdown(ssl_connection);
|
||||
SSL_free (ssl_connection);
|
||||
@ -1332,7 +1346,7 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
|
||||
if ((sockfd > -1) && (sockfd != fd))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " closing Previous/Existing sockfd"
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " closing Previous/Existing sockfd"
|
||||
<< std::endl;
|
||||
net_internal_close(sockfd);
|
||||
}
|
||||
@ -1348,7 +1362,7 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
*/
|
||||
sockaddr_storage_copy(foreign_addr, remote_addr);
|
||||
|
||||
std::cerr << __PRETTY_FUNCTION__ << " SUCCESSFUL connection to: "
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " SUCCESSFUL connection to: "
|
||||
<< PeerId().toStdString() << " remoteaddr: "
|
||||
<< sockaddr_storage_iptostring(remote_addr) << std::endl;
|
||||
|
||||
|
@ -424,23 +424,8 @@ int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool
|
||||
{
|
||||
// attempt the accept again.
|
||||
int fd = SSL_get_fd(incoming_connexion_info.ssl);
|
||||
|
||||
AuthSSL::getAuthSSL()->setCurrentConnectionAttemptInfo(RsPgpId(),RsPeerId(),std::string()) ;
|
||||
int err = SSL_accept(incoming_connexion_info.ssl);
|
||||
|
||||
// Now grab the connection info that was filled in by the callback.
|
||||
// In the case the callback did not succeed the SSL certificate will not be accessible
|
||||
// from SSL_get_peer_certificate, so we need to get it from the callback system.
|
||||
//
|
||||
AuthSSL::getAuthSSL()->getCurrentConnectionAttemptInfo(incoming_connexion_info.gpgid,incoming_connexion_info.sslid,incoming_connexion_info.sslcn) ;
|
||||
|
||||
#ifdef DEBUG_LISTENNER
|
||||
std::cerr << "Info from callback: " << std::endl;
|
||||
std::cerr << " Got PGP Id = " << incoming_connexion_info.gpgid << std::endl;
|
||||
std::cerr << " Got SSL Id = " << incoming_connexion_info.sslid << std::endl;
|
||||
std::cerr << " Got SSL CN = " << incoming_connexion_info.sslcn << std::endl;
|
||||
#endif
|
||||
|
||||
if (err <= 0)
|
||||
{
|
||||
int ssl_err = SSL_get_error(incoming_connexion_info.ssl, err);
|
||||
@ -486,10 +471,22 @@ int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool
|
||||
break;
|
||||
}
|
||||
|
||||
closeConnection(fd, incoming_connexion_info.ssl) ;
|
||||
|
||||
pqioutput(PQL_WARNING, pqissllistenzone, "Read Error on the SSL Socket\nShutting it down!");
|
||||
|
||||
// We use SSL_get_verify_result() in order to differentiate two cases:
|
||||
// case 1: the incoming connection is closed because the peer is not a friend. This is already handled in authssl.
|
||||
// case 2: the incoming connection is closed because no authentication info is available, in which case it returns X509_V_OK
|
||||
auto vres = SSL_get_verify_result(incoming_connexion_info.ssl);
|
||||
|
||||
if(vres == X509_V_OK && nullptr != rsEvents)
|
||||
{
|
||||
auto ev = std::make_shared<RsAuthSslConnectionAutenticationEvent>();
|
||||
ev->mLocator = RsUrl(incoming_connexion_info.addr);
|
||||
ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
closeConnection(fd, incoming_connexion_info.ssl);
|
||||
|
||||
// failure -1, pending 0, sucess 1.
|
||||
return -1;
|
||||
}
|
||||
@ -505,23 +502,22 @@ int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool
|
||||
incoming_connexion_info.sslcn = RsX509Cert::getCertName(*x509);
|
||||
incoming_connexion_info.sslid = RsX509Cert::getCertSslId(*x509);
|
||||
|
||||
#ifdef DEBUG_LISTENNER
|
||||
#ifndef DEBUG_LISTENNER
|
||||
std::cerr << "ContinueSSL:" << std::endl;
|
||||
std::cerr << " Got PGP Id = " << incoming_connexion_info.gpgid << std::endl;
|
||||
std::cerr << " Got SSL Id = " << incoming_connexion_info.sslid << std::endl;
|
||||
std::cerr << " Got SSL CN = " << incoming_connexion_info.sslcn << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LISTENNER
|
||||
else
|
||||
std::cerr << " no info." << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
// if it succeeds
|
||||
if (0 < completeConnection(fd, incoming_connexion_info))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* else we shut it down! */
|
||||
pqioutput(PQL_WARNING, pqissllistenzone,
|
||||
|
@ -49,7 +49,7 @@ int pqithreadstreamer::tick()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pqithreadstreamer::data_tick()
|
||||
void pqithreadstreamer::threadTick()
|
||||
{
|
||||
uint32_t recv_timeout = 0;
|
||||
uint32_t sleep_period = 0;
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
virtual int tick();
|
||||
|
||||
protected:
|
||||
virtual void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
PQInterface *mParent;
|
||||
uint32_t mTimeout;
|
||||
|
@ -23,10 +23,14 @@
|
||||
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
|
||||
#include "util/rsmemory.h"
|
||||
#include "util/rsurl.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "serialiser/rstypeserializer.h"
|
||||
#include "util/rstime.h"
|
||||
|
||||
class RsEvents;
|
||||
|
||||
@ -58,7 +62,7 @@ enum class RsEventType : uint32_t
|
||||
AUTHSSL_CONNECTION_AUTENTICATION = 3,
|
||||
|
||||
/// @see pqissl
|
||||
REMOTE_PEER_REFUSED_CONNECTION = 4,
|
||||
PEER_CONNECTION = 4,
|
||||
|
||||
/// @see RsGxsChanges
|
||||
GXS_CHANGES = 5,
|
||||
@ -69,6 +73,18 @@ enum class RsEventType : uint32_t
|
||||
/// @see RsMailStatusEvent
|
||||
MAIL_STATUS_CHANGE = 7,
|
||||
|
||||
/// @see RsGxsCircleEvent
|
||||
GXS_CIRCLES = 8,
|
||||
|
||||
/// @see RsGxsChannelEvent
|
||||
GXS_CHANNELS = 9,
|
||||
|
||||
/// @see RsGxsForumEvent
|
||||
GXS_FORUMS = 10,
|
||||
|
||||
/// @see RsGxsPostedEvent
|
||||
GXS_POSTED = 11,
|
||||
|
||||
MAX /// Used to detect invalid event type passed
|
||||
};
|
||||
|
||||
@ -170,3 +186,4 @@ public:
|
||||
|
||||
virtual ~RsEvents();
|
||||
};
|
||||
|
||||
|
@ -103,6 +103,48 @@ struct RsGxsChannelPost : RsSerializable
|
||||
};
|
||||
|
||||
|
||||
enum class RsChannelEventCode: uint8_t
|
||||
{
|
||||
UNKNOWN = 0x00,
|
||||
NEW_CHANNEL = 0x01, /// emitted when new channel is received
|
||||
|
||||
/// emitted when existing channel is updated
|
||||
UPDATED_CHANNEL = 0x02,
|
||||
|
||||
/// new message reeived in a particular channel (group and msg id)
|
||||
NEW_MESSAGE = 0x03,
|
||||
|
||||
/// existing message has been updated in a particular channel
|
||||
UPDATED_MESSAGE = 0x04,
|
||||
|
||||
/// publish key for this channel has been received
|
||||
RECEIVED_PUBLISH_KEY = 0x05,
|
||||
|
||||
/// subscription for channel mChannelGroupId changed.
|
||||
SUBSCRIBE_STATUS_CHANGED = 0x06,
|
||||
};
|
||||
|
||||
struct RsGxsChannelEvent: RsEvent
|
||||
{
|
||||
RsGxsChannelEvent():
|
||||
RsEvent(RsEventType::GXS_CHANNELS),
|
||||
mChannelEventCode(RsChannelEventCode::UNKNOWN) {}
|
||||
|
||||
RsChannelEventCode mChannelEventCode;
|
||||
RsGxsGroupId mChannelGroupId;
|
||||
RsGxsMessageId mChannelMsgId;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
|
||||
RS_SERIAL_PROCESS(mChannelEventCode);
|
||||
RS_SERIAL_PROCESS(mChannelGroupId);
|
||||
RS_SERIAL_PROCESS(mChannelMsgId);
|
||||
}
|
||||
};
|
||||
|
||||
class RsGxsChannels: public RsGxsIfaceHelper, public RsGxsCommentService
|
||||
{
|
||||
public:
|
||||
|
@ -123,7 +123,7 @@ struct RsGxsCircleDetails : RsSerializable
|
||||
{
|
||||
RsGxsCircleDetails() :
|
||||
mCircleType(static_cast<uint32_t>(RsGxsCircleType::EXTERNAL)),
|
||||
mAmIAllowed(false) {}
|
||||
mAmIAllowed(false),mAmIAdmin(false) {}
|
||||
~RsGxsCircleDetails() override;
|
||||
|
||||
RsGxsCircleId mCircleId;
|
||||
@ -136,6 +136,9 @@ struct RsGxsCircleDetails : RsSerializable
|
||||
* list & subscribed list). */
|
||||
bool mAmIAllowed;
|
||||
|
||||
/// true when we're an administrator of the circle group, meaning that we can add/remove members from the invitee list.
|
||||
bool mAmIAdmin;
|
||||
|
||||
/// This crosses admin list and subscribed list
|
||||
std::set<RsGxsId> mAllowedGxsIds;
|
||||
std::set<RsPgpId> mAllowedNodes;
|
||||
@ -152,12 +155,63 @@ struct RsGxsCircleDetails : RsSerializable
|
||||
RS_SERIAL_PROCESS(mCircleType);
|
||||
RS_SERIAL_PROCESS(mRestrictedCircleId);
|
||||
RS_SERIAL_PROCESS(mAmIAllowed);
|
||||
RS_SERIAL_PROCESS(mAmIAdmin);
|
||||
RS_SERIAL_PROCESS(mAllowedGxsIds);
|
||||
RS_SERIAL_PROCESS(mAllowedNodes);
|
||||
RS_SERIAL_PROCESS(mSubscriptionFlags);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum class RsGxsCircleEventCode: uint8_t
|
||||
{
|
||||
UNKNOWN = 0x00,
|
||||
|
||||
/** mCircleId contains the circle id and mGxsId is the id requesting
|
||||
* membership */
|
||||
CIRCLE_MEMBERSHIP_REQUEST = 0x01,
|
||||
|
||||
/** mCircleId is the circle that invites me, and mGxsId is my own Id that is
|
||||
* invited */
|
||||
CIRCLE_MEMBERSHIP_INVITE = 0x02,
|
||||
|
||||
/** mCircleId contains the circle id and mGxsId is the id dropping
|
||||
* membership */
|
||||
CIRCLE_MEMBERSHIP_LEAVE = 0x03,
|
||||
|
||||
/// mCircleId contains the circle id and mGxsId is the id of the new member
|
||||
CIRCLE_MEMBERSHIP_JOIN = 0x04,
|
||||
|
||||
/** mCircleId contains the circle id and mGxsId is the id that was revoqued
|
||||
* by admin */
|
||||
CIRCLE_MEMBERSHIP_REVOQUED= 0x05,
|
||||
};
|
||||
|
||||
struct RsGxsCircleEvent: RsEvent
|
||||
{
|
||||
RsGxsCircleEvent()
|
||||
: RsEvent(RsEventType::GXS_CIRCLES),
|
||||
mCircleEventType(RsGxsCircleEventCode::UNKNOWN) {}
|
||||
|
||||
|
||||
RsGxsCircleEventCode mCircleEventType;
|
||||
RsGxsCircleId mCircleId;
|
||||
RsGxsId mGxsId;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx ) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mCircleEventType);
|
||||
RS_SERIAL_PROCESS(mCircleId);
|
||||
RS_SERIAL_PROCESS(mGxsId);
|
||||
}
|
||||
|
||||
~RsGxsCircleEvent() override;
|
||||
};
|
||||
|
||||
class RsGxsCircles: public RsGxsIfaceHelper
|
||||
{
|
||||
public:
|
||||
@ -243,6 +297,17 @@ public:
|
||||
*/
|
||||
virtual bool getCircleRequests( const RsGxsGroupId& circleId,
|
||||
std::vector<RsGxsCircleMsg>& requests ) = 0;
|
||||
/**
|
||||
* @brief Get specific circle request
|
||||
* @jsonapi{development}
|
||||
* @param[in] circleId id of the circle of which the requests are requested
|
||||
* @param[in] msgId id of the request
|
||||
* @param[out] msg storage for the circle request
|
||||
* @return false if something failed, true otherwhise
|
||||
*/
|
||||
virtual bool getCircleRequest(const RsGxsGroupId& circleId,
|
||||
const RsGxsMessageId& msgId,
|
||||
RsGxsCircleMsg& msg) =0;
|
||||
|
||||
/**
|
||||
* @brief Invite identities to circle
|
||||
|
@ -105,6 +105,46 @@ struct RsGxsForumMsg : RsSerializable
|
||||
};
|
||||
|
||||
|
||||
enum class RsForumEventCode: uint8_t
|
||||
{
|
||||
UNKNOWN = 0x00,
|
||||
NEW_FORUM = 0x01, /// emitted when new forum is received
|
||||
UPDATED_FORUM = 0x02, /// emitted when existing forum is updated
|
||||
|
||||
/// new message reeived in a particular forum
|
||||
NEW_MESSAGE = 0x03,
|
||||
|
||||
/// existing message has been updated in a particular forum
|
||||
UPDATED_MESSAGE = 0x04,
|
||||
|
||||
/// forum was subscribed or unsubscribed
|
||||
SUBSCRIBE_STATUS_CHANGED = 0x05,
|
||||
};
|
||||
|
||||
struct RsGxsForumEvent: RsEvent
|
||||
{
|
||||
RsGxsForumEvent()
|
||||
: RsEvent(RsEventType::GXS_FORUMS),
|
||||
mForumEventCode(RsForumEventCode::UNKNOWN) {}
|
||||
|
||||
RsForumEventCode mForumEventCode;
|
||||
RsGxsGroupId mForumGroupId;
|
||||
RsGxsMessageId mForumMsgId;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx ) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mForumEventCode);
|
||||
RS_SERIAL_PROCESS(mForumGroupId);
|
||||
RS_SERIAL_PROCESS(mForumMsgId);
|
||||
}
|
||||
|
||||
~RsGxsForumEvent() override;
|
||||
};
|
||||
|
||||
class RsGxsForums: public RsGxsIfaceHelper
|
||||
{
|
||||
public:
|
||||
|
@ -296,10 +296,25 @@ struct MsgTagType : RsSerializable
|
||||
} //namespace Rs
|
||||
} //namespace Msgs
|
||||
|
||||
|
||||
enum class RsMailStatusEventCode: uint8_t
|
||||
{
|
||||
NEW_MESSAGE = 0x00,
|
||||
MESSAGE_REMOVED = 0x01,
|
||||
MESSAGE_SENT = 0x02,
|
||||
|
||||
/// means the peer received the message
|
||||
MESSAGE_RECEIVED_ACK = 0x03,
|
||||
|
||||
/// An error occurred attempting to sign the message
|
||||
SIGNATURE_FAILED = 0x04,
|
||||
};
|
||||
|
||||
struct RsMailStatusEvent : RsEvent
|
||||
{
|
||||
RsMailStatusEvent() : RsEvent(RsEventType::MAIL_STATUS_CHANGE) {}
|
||||
|
||||
RsMailStatusEventCode mMailStatusEventCode;
|
||||
std::set<RsMailMessageId> mChangedMsgIds;
|
||||
|
||||
/// @see RsEvent
|
||||
@ -308,6 +323,7 @@ struct RsMailStatusEvent : RsEvent
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mChangedMsgIds);
|
||||
RS_SERIAL_PROCESS(mMailStatusEventCode);
|
||||
}
|
||||
|
||||
~RsMailStatusEvent() override;
|
||||
|
@ -79,9 +79,10 @@ const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x000
|
||||
const uint32_t RS_FEED_ITEM_PEER_HELLO = RS_FEED_TYPE_PEER | 0x0003;
|
||||
const uint32_t RS_FEED_ITEM_PEER_NEW = RS_FEED_TYPE_PEER | 0x0004;
|
||||
const uint32_t RS_FEED_ITEM_PEER_OFFSET = RS_FEED_TYPE_PEER | 0x0005;
|
||||
const uint32_t RS_FEED_ITEM_PEER_DENIES_CONNEXION = RS_FEED_TYPE_PEER | 0x0006;
|
||||
|
||||
const uint32_t RS_FEED_ITEM_SEC_CONNECT_ATTEMPT = RS_FEED_TYPE_SECURITY | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_SEC_AUTH_DENIED = RS_FEED_TYPE_SECURITY | 0x0002;
|
||||
const uint32_t RS_FEED_ITEM_SEC_AUTH_DENIED = RS_FEED_TYPE_SECURITY | 0x0002; // locally denied connection
|
||||
const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_IN = RS_FEED_TYPE_SECURITY | 0x0003;
|
||||
const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_OUT = RS_FEED_TYPE_SECURITY | 0x0004;
|
||||
const uint32_t RS_FEED_ITEM_SEC_WRONG_SIGNATURE = RS_FEED_TYPE_SECURITY | 0x0005;
|
||||
@ -114,8 +115,11 @@ const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001;
|
||||
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REQ = RS_FEED_TYPE_CIRCLE | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_INVIT_REC = RS_FEED_TYPE_CIRCLE | 0x0002;
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REQ = RS_FEED_TYPE_CIRCLE | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_INVIT_REC = RS_FEED_TYPE_CIRCLE | 0x0002;
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_LEAVE = RS_FEED_TYPE_CIRCLE | 0x0003;
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_JOIN = RS_FEED_TYPE_CIRCLE | 0x0004;
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REVOQUED = RS_FEED_TYPE_CIRCLE | 0x0005;
|
||||
|
||||
const uint32_t RS_MESSAGE_CONNECT_ATTEMPT = 0x0001;
|
||||
|
||||
@ -212,8 +216,6 @@ public:
|
||||
NotifyClient() {}
|
||||
virtual ~NotifyClient() {}
|
||||
|
||||
virtual void notifyPeerConnected (const std::string& /* peer_id */) {}
|
||||
virtual void notifyPeerDisconnected (const std::string& /* peer_id */) {}
|
||||
virtual void notifyListPreChange (int /* list */, int /* type */) {}
|
||||
virtual void notifyListChange (int /* list */, int /* type */) {}
|
||||
virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {}
|
||||
@ -230,8 +232,6 @@ public:
|
||||
virtual void notifyOwnStatusMessageChanged () {}
|
||||
virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {}
|
||||
virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {}
|
||||
virtual void notifyGxsChange (const RsGxsChanges& /* changes */) {}
|
||||
virtual void notifyConnectionWithoutCert () {}
|
||||
|
||||
/* one or more peers has changed the states */
|
||||
virtual void notifyPeerStatusChangedSummary () {}
|
||||
|
@ -206,6 +206,100 @@ std::string RsPeerTrustString(uint32_t trustLvl);
|
||||
std::string RsPeerNetModeString(uint32_t netModel);
|
||||
std::string RsPeerLastConnectString(uint32_t lastConnect);
|
||||
|
||||
//===================================================================================================//
|
||||
// Connexion and security events //
|
||||
//===================================================================================================//
|
||||
|
||||
enum class RsAuthSslError: uint8_t
|
||||
{
|
||||
// NO_ERROR = 0x00, // enabling break windows build
|
||||
MISSING_AUTHENTICATION_INFO = 0x01,
|
||||
PGP_SIGNATURE_VALIDATION_FAILED = 0x02,
|
||||
MISMATCHED_PGP_ID = 0x03,
|
||||
NO_CERTIFICATE_SUPPLIED = 0x04,
|
||||
NOT_A_FRIEND = 0x05,
|
||||
MISSING_CERTIFICATE = 0x06,
|
||||
IP_IS_BLACKLISTED = 0x07,
|
||||
PEER_REFUSED_CONNECTION = 0x08,
|
||||
UNKNOWN_ERROR = 0x09,
|
||||
};
|
||||
|
||||
/**
|
||||
* Event triggered by AuthSSL when authentication of a connection attempt either
|
||||
* fail or success
|
||||
*/
|
||||
struct RsAuthSslConnectionAutenticationEvent : RsEvent
|
||||
{
|
||||
RsAuthSslConnectionAutenticationEvent() :
|
||||
RsEvent(RsEventType::AUTHSSL_CONNECTION_AUTENTICATION) {}
|
||||
|
||||
RsPeerId mSslId;
|
||||
std::string mSslCn;
|
||||
RsPgpId mPgpId;
|
||||
RsUrl mLocator;
|
||||
std::string mErrorMsg;
|
||||
RsAuthSslError mErrorCode;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mSslId);
|
||||
RS_SERIAL_PROCESS(mSslCn);
|
||||
RS_SERIAL_PROCESS(mPgpId);
|
||||
RS_SERIAL_PROCESS(mLocator);
|
||||
RS_SERIAL_PROCESS(mErrorMsg);
|
||||
RS_SERIAL_PROCESS(mErrorCode);
|
||||
}
|
||||
|
||||
~RsAuthSslConnectionAutenticationEvent() override;
|
||||
};
|
||||
|
||||
enum class RsConnectionEventCode: uint8_t
|
||||
{
|
||||
UNKNOWN = 0x00,
|
||||
PEER_CONNECTED = 0x01,
|
||||
PEER_DISCONNECTED = 0x02,
|
||||
PEER_TIME_SHIFT = 0x03, // mTimeShift = time shift in seconds
|
||||
PEER_REPORTS_WRONG_IP = 0x04, // mPeerLocator = address reported, mOwnLocator = own address
|
||||
};
|
||||
|
||||
struct RsConnectionEvent : RsEvent
|
||||
{
|
||||
RsConnectionEvent()
|
||||
: RsEvent(RsEventType::PEER_CONNECTION),
|
||||
mConnectionInfoCode(RsConnectionEventCode::UNKNOWN), mTimeShift(0) {}
|
||||
|
||||
RsConnectionEventCode mConnectionInfoCode;
|
||||
RsPeerId mSslId;
|
||||
RsUrl mOwnLocator;
|
||||
RsUrl mReportedLocator;
|
||||
|
||||
/** If there is a time shift with the peer aka
|
||||
* mConnectionInfoCode == PEER_TIME_SHIFT contains the time shift value in
|
||||
* seconds */
|
||||
rstime_t mTimeShift;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx ) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mConnectionInfoCode);
|
||||
RS_SERIAL_PROCESS(mSslId);
|
||||
RS_SERIAL_PROCESS(mOwnLocator);
|
||||
RS_SERIAL_PROCESS(mReportedLocator);
|
||||
RS_SERIAL_PROCESS(mTimeShift);
|
||||
}
|
||||
|
||||
~RsConnectionEvent() override;
|
||||
};
|
||||
|
||||
//===================================================================================================//
|
||||
// Peer Details //
|
||||
//===================================================================================================//
|
||||
|
||||
/* We should definitely split this into 2 sub-structures:
|
||||
* PGP info (or profile info) with all info related to PGP keys
|
||||
|
@ -68,6 +68,33 @@ class RsPostedGroup
|
||||
std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group);
|
||||
std::ostream &operator<<(std::ostream &out, const RsPostedPost &post);
|
||||
|
||||
enum class RsPostedEventCode: uint8_t
|
||||
{
|
||||
UNKNOWN = 0x00,
|
||||
NEW_POSTED_GROUP = 0x01,
|
||||
NEW_MESSAGE = 0x02
|
||||
};
|
||||
|
||||
|
||||
struct RsGxsPostedEvent: RsEvent
|
||||
{
|
||||
RsGxsPostedEvent():
|
||||
RsEvent(RsEventType::GXS_POSTED),
|
||||
mPostedEventCode(RsPostedEventCode::UNKNOWN) {}
|
||||
|
||||
RsPostedEventCode mPostedEventCode;
|
||||
RsGxsGroupId mPostedGroupId;
|
||||
RsGxsMessageId mPostedMsgId;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mPostedEventCode);
|
||||
RS_SERIAL_PROCESS(mPostedGroupId);
|
||||
RS_SERIAL_PROCESS(mPostedMsgId);
|
||||
}
|
||||
};
|
||||
|
||||
class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService
|
||||
{
|
||||
|
@ -4,7 +4,8 @@
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright (C) 2012-2018 Retroshare Team <contact@retroshare.cc> *
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -55,7 +56,7 @@
|
||||
* Customize it trough qmake command line @see retroshare.pri
|
||||
*/
|
||||
#ifndef RS_EXTRA_VERSION
|
||||
# define RS_EXTRA_VERSION "alpha"
|
||||
# define RS_EXTRA_VERSION "-alpha"
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include "util/rsstring.h"
|
||||
#include "rs_upnp/upnp18_retrocompat.h"
|
||||
#include "util/rstime.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ >= 4
|
||||
|
@ -139,7 +139,7 @@ RsServer::~RsServer()
|
||||
|
||||
|
||||
/* Thread Fn: Run the Core */
|
||||
void RsServer::data_tick()
|
||||
void RsServer::threadTick()
|
||||
{
|
||||
rstime::rs_usleep(mTimeDelta * 1000000);
|
||||
|
||||
|
@ -88,9 +88,7 @@ public:
|
||||
void setShutdownCallback(const std::function<void(int)>& callback)
|
||||
{ mShutdownCallback = callback; }
|
||||
|
||||
|
||||
/* Thread Fn: Run the Core */
|
||||
virtual void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
/* locking stuff */
|
||||
void lockRsCore()
|
||||
|
@ -1859,3 +1859,5 @@ RsPeerStateChangedEvent::RsPeerStateChangedEvent(RsPeerId sslId) :
|
||||
RsEvent(RsEventType::PEER_STATE_CHANGED), mSslId(sslId) {}
|
||||
|
||||
RsPeers::~RsPeers() = default;
|
||||
RsAuthSslConnectionAutenticationEvent::~RsAuthSslConnectionAutenticationEvent() = default;
|
||||
RsConnectionEvent::~RsConnectionEvent() = default;
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include "retroshare/rsnotify.h"
|
||||
#include "retroshare/rsiface.h"
|
||||
#include "plugins/pluginmanager.h"
|
||||
|
||||
#include "retroshare/rsversion.h"
|
||||
#include "rsserver/rsloginhandler.h"
|
||||
#include "rsserver/rsaccounts.h"
|
||||
|
||||
@ -96,10 +96,6 @@ RsDht *rsDht = NULL ;
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
# include "jsonapi/jsonapi.h"
|
||||
#ifdef RS_WEBUI
|
||||
#include "jsonapi/jsonapi.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef RS_BROADCAST_DISCOVERY
|
||||
@ -195,6 +191,9 @@ static const int SSLPWD_LEN = 64;
|
||||
|
||||
void RsInit::InitRsConfig()
|
||||
{
|
||||
RsInfo() << " libretroshare version: " << RS_HUMAN_READABLE_VERSION
|
||||
<< std::endl;
|
||||
|
||||
rsInitConfig = new RsInitConfig;
|
||||
|
||||
|
||||
|
@ -280,7 +280,7 @@ bool inline isTunnelActiveError(const std::string &answer) {
|
||||
return answer.compare(0, 22, "ERROR tunnel is active") == 0;
|
||||
}
|
||||
|
||||
void p3I2pBob::data_tick()
|
||||
void p3I2pBob::threadTick()
|
||||
{
|
||||
int sleepTime = 0;
|
||||
{
|
||||
|
@ -205,9 +205,7 @@ public:
|
||||
|
||||
static std::string keyToBase32Addr(const std::string &key);
|
||||
|
||||
// RsTickingThread interface
|
||||
public:
|
||||
void data_tick();
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
private:
|
||||
int stateMachineBOB();
|
||||
|
@ -139,7 +139,7 @@ void BroadcastDiscoveryService::updatePublishedData()
|
||||
BroadcastDiscoveryPack::fromPeerDetails(od).serializeToString());
|
||||
}
|
||||
|
||||
void BroadcastDiscoveryService::data_tick()
|
||||
void BroadcastDiscoveryService::threadTick()
|
||||
{
|
||||
auto nextRunAt = std::chrono::system_clock::now() + std::chrono::seconds(5);
|
||||
|
||||
|
@ -57,8 +57,7 @@ public:
|
||||
/// @see RsBroadcastDiscovery
|
||||
bool disableMulticastListening() override;
|
||||
|
||||
/// @see RsTickingThread
|
||||
void data_tick() override;
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
protected:
|
||||
constexpr static uint16_t port = 36405;
|
||||
|
@ -136,14 +136,14 @@ uint32_t p3GxsChannels::channelsAuthenPolicy()
|
||||
static const uint32_t GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months
|
||||
static const uint8_t GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ;
|
||||
|
||||
struct RsGxsForumNotifyRecordsItem: public RsItem
|
||||
struct RsGxsGroupNotifyRecordsItem: public RsItem
|
||||
{
|
||||
|
||||
RsGxsForumNotifyRecordsItem()
|
||||
RsGxsGroupNotifyRecordsItem()
|
||||
: RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG,GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD)
|
||||
{}
|
||||
|
||||
virtual ~RsGxsForumNotifyRecordsItem() {}
|
||||
virtual ~RsGxsGroupNotifyRecordsItem() {}
|
||||
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
@ -167,7 +167,7 @@ public:
|
||||
|
||||
switch(item_sub_id)
|
||||
{
|
||||
case GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsForumNotifyRecordsItem();
|
||||
case GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsGroupNotifyRecordsItem();
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@ -178,7 +178,7 @@ bool p3GxsChannels::saveList(bool &cleanup, std::list<RsItem *>&saveList)
|
||||
{
|
||||
cleanup = true ;
|
||||
|
||||
RsGxsForumNotifyRecordsItem *item = new RsGxsForumNotifyRecordsItem ;
|
||||
RsGxsGroupNotifyRecordsItem *item = new RsGxsGroupNotifyRecordsItem ;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mKnownChannelsMutex);
|
||||
@ -198,7 +198,7 @@ bool p3GxsChannels::loadList(std::list<RsItem *>& loadList)
|
||||
|
||||
rstime_t now = time(NULL);
|
||||
|
||||
RsGxsForumNotifyRecordsItem *fnr = dynamic_cast<RsGxsForumNotifyRecordsItem*>(item) ;
|
||||
RsGxsGroupNotifyRecordsItem *fnr = dynamic_cast<RsGxsGroupNotifyRecordsItem*>(item) ;
|
||||
|
||||
if(fnr)
|
||||
{
|
||||
@ -238,12 +238,6 @@ void p3GxsChannels::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
std::cerr << "p3GxsChannels::notifyChanges() : " << changes.size() << "changes to notify" << std::endl;
|
||||
#endif
|
||||
|
||||
p3Notify* notify = nullptr;
|
||||
if (!changes.empty())
|
||||
{
|
||||
notify = RsServer::notify();
|
||||
}
|
||||
|
||||
/* iterate through and grab any new messages */
|
||||
std::list<RsGxsGroupId> unprocessedGroups;
|
||||
|
||||
@ -256,13 +250,17 @@ void p3GxsChannels::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
if (msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW)
|
||||
{
|
||||
/* message received */
|
||||
if (notify)
|
||||
if (rsEvents)
|
||||
{
|
||||
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgChangeMap = msgChange->msgChangeMap;
|
||||
for (auto mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit)
|
||||
for (auto mit1 = mit->second.begin(); mit1 != mit->second.end(); ++mit1)
|
||||
{
|
||||
notify->AddFeedItem(RS_FEED_ITEM_CHANNEL_MSG, mit->first.toStdString(), mit1->toStdString());
|
||||
auto ev = std::make_shared<RsGxsChannelEvent>();
|
||||
ev->mChannelMsgId = *mit1;
|
||||
ev->mChannelGroupId = mit->first;
|
||||
ev->mChannelEventCode = RsChannelEventCode::NEW_MESSAGE;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -298,48 +296,68 @@ void p3GxsChannels::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (notify)
|
||||
if (rsEvents)
|
||||
{
|
||||
RsGxsGroupChange *grpChange = dynamic_cast<RsGxsGroupChange*>(*it);
|
||||
if (grpChange)
|
||||
{
|
||||
switch (grpChange->getType())
|
||||
{
|
||||
default:
|
||||
case RsGxsNotify::TYPE_PROCESSED:
|
||||
case RsGxsNotify::TYPE_PUBLISHED:
|
||||
break;
|
||||
|
||||
case RsGxsNotify::TYPE_RECEIVED_NEW:
|
||||
default:
|
||||
case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed
|
||||
{
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
RS_STACK_MUTEX(mKnownChannelsMutex);
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
if(mKnownChannels.find(*git) == mKnownChannels.end())
|
||||
{
|
||||
notify->AddFeedItem(RS_FEED_ITEM_CHANNEL_NEW, git->toStdString());
|
||||
mKnownChannels.insert(std::make_pair(*git,time(NULL))) ;
|
||||
}
|
||||
else
|
||||
std::cerr << "(II) Not notifying already known channel " << *git << std::endl;
|
||||
}
|
||||
break;
|
||||
auto ev = std::make_shared<RsGxsChannelEvent>();
|
||||
ev->mChannelGroupId = *git;
|
||||
ev->mChannelEventCode = RsChannelEventCode::SUBSCRIBE_STATUS_CHANGED;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
|
||||
case RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY:
|
||||
}
|
||||
break;
|
||||
|
||||
case RsGxsNotify::TYPE_PUBLISHED:
|
||||
case RsGxsNotify::TYPE_RECEIVED_NEW:
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
RS_STACK_MUTEX(mKnownChannelsMutex);
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
if(mKnownChannels.find(*git) == mKnownChannels.end())
|
||||
{
|
||||
notify->AddFeedItem(RS_FEED_ITEM_CHANNEL_PUBLISHKEY, git->toStdString());
|
||||
mKnownChannels.insert(std::make_pair(*git,time(NULL))) ;
|
||||
IndicateConfigChanged();
|
||||
|
||||
auto ev = std::make_shared<RsGxsChannelEvent>();
|
||||
ev->mChannelGroupId = *git;
|
||||
ev->mChannelEventCode = RsChannelEventCode::NEW_CHANNEL;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
break;
|
||||
else
|
||||
std::cerr << "(II) Not notifying already known channel " << *git << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY:
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
auto ev = std::make_shared<RsGxsChannelEvent>();
|
||||
ev->mChannelGroupId = *git;
|
||||
ev->mChannelEventCode = RsChannelEventCode::RECEIVED_PUBLISH_KEY;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -351,6 +369,7 @@ void p3GxsChannels::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
if(!unprocessedGroups.empty())
|
||||
request_SpecificSubscribedGroups(unprocessedGroups);
|
||||
|
||||
// the call below deletes changes and its content.
|
||||
RsGxsIfaceHelper::receiveChanges(changes);
|
||||
}
|
||||
|
||||
|
@ -305,6 +305,32 @@ bool p3GxsCircles::getCircleRequests( const RsGxsGroupId& circleId,
|
||||
return getMsgData(token, requests);
|
||||
}
|
||||
|
||||
bool p3GxsCircles::getCircleRequest(const RsGxsGroupId& circleId,const RsGxsMessageId& msgId,RsGxsCircleMsg& msg)
|
||||
{
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||
|
||||
std::set<RsGxsMessageId> contentsIds;
|
||||
contentsIds.insert(msgId);
|
||||
|
||||
GxsMsgReq msgIds;
|
||||
msgIds[circleId] = contentsIds;
|
||||
|
||||
uint32_t token;
|
||||
if( !requestMsgInfo(token, opts, msgIds) || waitToken(token) != RsTokenService::COMPLETE )
|
||||
return false;
|
||||
|
||||
std::vector<RsGxsCircleMsg> msgs;
|
||||
|
||||
if(getMsgData(token, msgs) && msgs.size() == 1)
|
||||
{
|
||||
msg = msgs.front();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool p3GxsCircles::inviteIdsToCircle( const std::set<RsGxsId>& identities,
|
||||
const RsGxsCircleId& circleId )
|
||||
{
|
||||
@ -442,6 +468,7 @@ void p3GxsCircles::service_tick()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
@ -467,13 +494,31 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
#ifdef DEBUG_CIRCLES
|
||||
std::cerr << " Msgs for Group: " << mit->first << std::endl;
|
||||
#endif
|
||||
force_cache_reload(RsGxsCircleId(mit->first));
|
||||
RsGxsCircleId circle_id(mit->first);
|
||||
|
||||
if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW) )
|
||||
force_cache_reload(circle_id);
|
||||
|
||||
RsGxsCircleDetails details;
|
||||
getCircleDetails(circle_id,details);
|
||||
|
||||
if(rsEvents && (c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW) )
|
||||
for (auto msgIdIt(mit->second.begin()), end(mit->second.end()); msgIdIt != end; ++msgIdIt)
|
||||
{
|
||||
const RsGxsMessageId& msgId = *msgIdIt;
|
||||
notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_MEMB_REQ,RsGxsCircleId(mit->first).toStdString(),msgId.toStdString());
|
||||
RsGxsCircleMsg msg;
|
||||
getCircleRequest(RsGxsGroupId(circle_id),*msgIdIt,msg);
|
||||
|
||||
auto ev = std::make_shared<RsGxsCircleEvent>();
|
||||
ev->mCircleId = circle_id;
|
||||
ev->mGxsId = msg.mMeta.mAuthorId;
|
||||
|
||||
if (msg.stuff == "SUBSCRIPTION_REQUEST_UNSUBSCRIBE")
|
||||
ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_LEAVE;
|
||||
else if(details.mAllowedGxsIds.find(msg.mMeta.mAuthorId) != details.mAllowedGxsIds.end())
|
||||
ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_JOIN;
|
||||
else
|
||||
ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_REQUEST;
|
||||
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
|
||||
}
|
||||
@ -506,15 +551,59 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
}
|
||||
|
||||
if(groupChange)
|
||||
{
|
||||
std::list<RsGxsId> own_ids;
|
||||
rsIdentity->getOwnIds(own_ids);
|
||||
|
||||
for(std::list<RsGxsGroupId>::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git)
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl;
|
||||
#endif
|
||||
force_cache_reload(RsGxsCircleId(*git)) ;
|
||||
if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW) )
|
||||
notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_INVIT_REC,RsGxsCircleId(*git).toStdString(),"");
|
||||
}
|
||||
|
||||
#ifdef TODO
|
||||
// This code will not work: we would like to detect changes in the circle data that reflects the fact that one of the
|
||||
// owned GXS ids is invited. But there's no way to compare the old circle data to the new if cache has to be updated.
|
||||
// For this we need to add the old metadata and group data in the RsGxsGroupChange structure and account for it.
|
||||
|
||||
if(rsEvents && (c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW) )
|
||||
{
|
||||
RsGxsCircleId circle_id(*git);
|
||||
force_cache_reload(circle_id);
|
||||
|
||||
RsGxsCircleDetails details;
|
||||
getCircleDetails(circle_id,details);
|
||||
|
||||
// We check that the change corresponds to one of our own ids. Since we do not know what the change is, we notify
|
||||
// for whatever is different from what is currently known. Other ids, that get invited only trigger a notification when the
|
||||
// ID also accepts the invitation, so it becomes a member of the circle.
|
||||
|
||||
for(auto own_id: own_ids)
|
||||
{
|
||||
auto it = details.mSubscriptionFlags.find(own_id);
|
||||
|
||||
if(it == details.mSubscriptionFlags.end())
|
||||
continue;
|
||||
|
||||
bool invited ( it->second & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST );
|
||||
bool subscrb ( it->second & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED );
|
||||
|
||||
if(std::find(details.mAllowedGxsIds.begin(),details.mAllowedGxsIds.end(),id) != details.mAllowedGxsIds.end() && !me_in_circle)
|
||||
{
|
||||
auto ev = std::make_shared<RsGxsCircleEvent>();
|
||||
|
||||
ev->mType = RsGxsCircleEvent::CIRCLE_MEMBERSHIP_INVITE;
|
||||
ev->mCircleId = circle_id;
|
||||
ev->mGxsId = ;
|
||||
|
||||
rsEvents->sendEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements
|
||||
@ -550,6 +639,7 @@ bool p3GxsCircles::getCircleDetails(
|
||||
details.mSubscriptionFlags.clear();
|
||||
details.mAllowedGxsIds.clear();
|
||||
details.mAmIAllowed = false ;
|
||||
details.mAmIAdmin = bool(data.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN);
|
||||
|
||||
for(std::map<RsGxsId,RsGxsCircleMembershipStatus>::const_iterator it(data.mMembershipStatus.begin());it!=data.mMembershipStatus.end();++it)
|
||||
{
|
||||
@ -860,7 +950,7 @@ RsGxsCircleCache::RsGxsCircleCache()
|
||||
mUpdateTime = 0;
|
||||
mGroupStatus = 0;
|
||||
mGroupSubscribeFlags = 0;
|
||||
mLastUpdatedMembershipTS = 0 ;
|
||||
mLastUpdatedMembershipTS = 0 ;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -2324,3 +2414,4 @@ RsGxsCircles::~RsGxsCircles() = default;
|
||||
RsGxsCircleMsg::~RsGxsCircleMsg() = default;
|
||||
RsGxsCircleDetails::~RsGxsCircleDetails() = default;
|
||||
RsGxsCircleGroup::~RsGxsCircleGroup() = default;
|
||||
RsGxsCircleEvent::~RsGxsCircleEvent() = default;
|
||||
|
@ -208,6 +208,11 @@ public:
|
||||
bool inviteIdsToCircle( const std::set<RsGxsId>& identities,
|
||||
const RsGxsCircleId& circleId ) override;
|
||||
|
||||
/// @see RsGxsCircles
|
||||
bool getCircleRequest(const RsGxsGroupId& circleId,
|
||||
const RsGxsMessageId& msgId,
|
||||
RsGxsCircleMsg& msg) override;
|
||||
|
||||
/// @see RsGxsCircles
|
||||
bool exportCircleLink(
|
||||
std::string& link, const RsGxsCircleId& circleId,
|
||||
|
@ -53,7 +53,7 @@ p3GxsForums::p3GxsForums( RsGeneralDataService *gds,
|
||||
RsGenExchange( gds, nes, new RsGxsForumSerialiser(),
|
||||
RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy()),
|
||||
RsGxsForums(static_cast<RsGxsIface&>(*this)), mGenToken(0),
|
||||
mGenActive(false), mGenCount(0)
|
||||
mGenActive(false), mGenCount(0), mKnownForumsMutex("GXS forums known forums timestamp cache")
|
||||
{
|
||||
// Test Data disabled in Repo.
|
||||
//RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD);
|
||||
@ -96,14 +96,14 @@ uint32_t p3GxsForums::forumsAuthenPolicy()
|
||||
static const uint32_t GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months
|
||||
static const uint8_t GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ;
|
||||
|
||||
struct RsGxsForumNotifyRecordsItem: public RsItem
|
||||
struct RsGxsGroupNotifyRecordsItem: public RsItem
|
||||
{
|
||||
|
||||
RsGxsForumNotifyRecordsItem()
|
||||
RsGxsGroupNotifyRecordsItem()
|
||||
: RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_FORUMS_CONFIG,GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD)
|
||||
{}
|
||||
|
||||
virtual ~RsGxsForumNotifyRecordsItem() {}
|
||||
virtual ~RsGxsGroupNotifyRecordsItem() {}
|
||||
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
@ -127,7 +127,7 @@ public:
|
||||
|
||||
switch(item_sub_id)
|
||||
{
|
||||
case GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsForumNotifyRecordsItem();
|
||||
case GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsGroupNotifyRecordsItem();
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@ -138,7 +138,7 @@ bool p3GxsForums::saveList(bool &cleanup, std::list<RsItem *>&saveList)
|
||||
{
|
||||
cleanup = true ;
|
||||
|
||||
RsGxsForumNotifyRecordsItem *item = new RsGxsForumNotifyRecordsItem ;
|
||||
RsGxsGroupNotifyRecordsItem *item = new RsGxsGroupNotifyRecordsItem ;
|
||||
|
||||
item->records = mKnownForums ;
|
||||
|
||||
@ -155,7 +155,7 @@ bool p3GxsForums::loadList(std::list<RsItem *>& loadList)
|
||||
|
||||
rstime_t now = time(NULL);
|
||||
|
||||
RsGxsForumNotifyRecordsItem *fnr = dynamic_cast<RsGxsForumNotifyRecordsItem*>(item) ;
|
||||
RsGxsGroupNotifyRecordsItem *fnr = dynamic_cast<RsGxsGroupNotifyRecordsItem*>(item) ;
|
||||
|
||||
if(fnr != NULL)
|
||||
{
|
||||
@ -181,82 +181,140 @@ RsSerialiser* p3GxsForums::setupSerialiser()
|
||||
|
||||
void p3GxsForums::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
{
|
||||
if (!changes.empty())
|
||||
#ifdef GXSFORUMS_DEBUG
|
||||
std::cerr << "p3GxsForums::notifyChanges() : " << changes.size() << "changes to notify" << std::endl;
|
||||
#endif
|
||||
|
||||
std::vector<RsGxsNotify *>::iterator it;
|
||||
for(it = changes.begin(); it != changes.end(); ++it)
|
||||
{
|
||||
p3Notify *notify = RsServer::notify();
|
||||
|
||||
if (notify)
|
||||
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
|
||||
if (msgChange)
|
||||
{
|
||||
std::vector<RsGxsNotify*>::iterator it;
|
||||
for(it = changes.begin(); it != changes.end(); ++it)
|
||||
{
|
||||
RsGxsNotify *c = *it;
|
||||
|
||||
switch (c->getType())
|
||||
if (msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW) /* message received */
|
||||
if (rsEvents)
|
||||
{
|
||||
default:
|
||||
case RsGxsNotify::TYPE_PROCESSED:
|
||||
case RsGxsNotify::TYPE_PUBLISHED:
|
||||
break;
|
||||
std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgChangeMap = msgChange->msgChangeMap;
|
||||
for (auto mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit)
|
||||
for (auto mit1 = mit->second.begin(); mit1 != mit->second.end(); ++mit1)
|
||||
{
|
||||
auto ev = std::make_shared<RsGxsForumEvent>();
|
||||
ev->mForumMsgId = *mit1;
|
||||
ev->mForumGroupId = mit->first;
|
||||
ev->mForumEventCode = RsForumEventCode::NEW_MESSAGE;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
case RsGxsNotify::TYPE_RECEIVED_NEW:
|
||||
#ifdef NOT_USED_YET
|
||||
if (!msgChange->metaChange())
|
||||
{
|
||||
#ifdef GXSCHANNELS_DEBUG
|
||||
std::cerr << "p3GxsForums::notifyChanges() Found Message Change Notification";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgChangeMap = msgChange->msgChangeMap;
|
||||
for(auto mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit)
|
||||
{
|
||||
#ifdef GXSCHANNELS_DEBUG
|
||||
std::cerr << "p3GxsForums::notifyChanges() Msgs for Group: " << mit->first;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
bool enabled = false;
|
||||
if (autoDownloadEnabled(mit->first, enabled) && enabled)
|
||||
{
|
||||
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange*>(c);
|
||||
if (msgChange)
|
||||
{
|
||||
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgChangeMap = msgChange->msgChangeMap;
|
||||
#ifdef GXSCHANNELS_DEBUG
|
||||
std::cerr << "p3GxsChannels::notifyChanges() AutoDownload for Group: " << mit->first;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
for (auto mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit)
|
||||
{
|
||||
for (auto mit1 = mit->second.begin(); mit1 != mit->second.end(); ++mit1)
|
||||
notify->AddFeedItem(RS_FEED_ITEM_FORUM_MSG, mit->first.toStdString(), mit1->toStdString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
RsGxsGroupChange *grpChange = dynamic_cast<RsGxsGroupChange *>(*it);
|
||||
if (grpChange)
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
if(mKnownForums.find(*git) == mKnownForums.end())
|
||||
{
|
||||
notify->AddFeedItem(RS_FEED_ITEM_FORUM_NEW, git->toStdString());
|
||||
mKnownForums.insert(std::make_pair(*git,time(NULL))) ;
|
||||
|
||||
IndicateConfigChanged();
|
||||
}
|
||||
else
|
||||
std::cerr << "(II) Not notifying already known forum " << *git << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY:
|
||||
{
|
||||
RsGxsGroupChange *grpChange = dynamic_cast<RsGxsGroupChange *>(*it);
|
||||
if (grpChange)
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
notify->AddFeedItem(RS_FEED_ITEM_FORUM_PUBLISHKEY, git->toStdString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* problem is most of these will be comments and votes,
|
||||
* should make it occasional - every 5mins / 10minutes TODO */
|
||||
unprocessedGroups.push_back(mit->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rsEvents)
|
||||
{
|
||||
RsGxsGroupChange *grpChange = dynamic_cast<RsGxsGroupChange*>(*it);
|
||||
if (grpChange)
|
||||
{
|
||||
switch (grpChange->getType())
|
||||
{
|
||||
default:
|
||||
case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed
|
||||
{
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
auto ev = std::make_shared<RsGxsForumEvent>();
|
||||
ev->mForumGroupId = *git;
|
||||
ev->mForumEventCode = RsForumEventCode::SUBSCRIBE_STATUS_CHANGED;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case RsGxsNotify::TYPE_PUBLISHED:
|
||||
case RsGxsNotify::TYPE_RECEIVED_NEW:
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
|
||||
RS_STACK_MUTEX(mKnownForumsMutex);
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
if(mKnownForums.find(*git) == mKnownForums.end())
|
||||
{
|
||||
mKnownForums.insert(
|
||||
std::make_pair(*git, time(nullptr)));
|
||||
IndicateConfigChanged();
|
||||
|
||||
auto ev = std::make_shared<RsGxsForumEvent>();
|
||||
ev->mForumGroupId = *git;
|
||||
ev->mForumEventCode = RsForumEventCode::NEW_FORUM;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
else
|
||||
RsInfo() << __PRETTY_FUNCTION__
|
||||
<< " Not notifying already known forum "
|
||||
<< *git << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef NOT_USED_YET
|
||||
case RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY:
|
||||
{
|
||||
/* group received */
|
||||
std::list<RsGxsGroupId> &grpList = grpChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
||||
{
|
||||
auto ev = std::make_shared<RsGxsChannelEvent>();
|
||||
|
||||
ev->mChannelGroupId = *git;
|
||||
ev->mChannelEventCode = RsGxsChannelEvent::RECEIVED_PUBLISH_KEY;
|
||||
|
||||
rsEvents->sendEvent(ev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* shouldn't need to worry about groups - as they need to be subscribed to */
|
||||
}
|
||||
|
||||
RsGxsIfaceHelper::receiveChanges(changes);
|
||||
@ -1087,3 +1145,4 @@ bool RsGxsForumGroup::canEditPosts(const RsGxsId& id) const
|
||||
RsGxsForumGroup::~RsGxsForumGroup() = default;
|
||||
RsGxsForumMsg::~RsGxsForumMsg() = default;
|
||||
RsGxsForums::~RsGxsForums() = default;
|
||||
RsGxsForumEvent::~RsGxsForumEvent() = default;
|
||||
|
@ -166,4 +166,5 @@ bool generateGroup(uint32_t &token, std::string groupName);
|
||||
RsGxsMessageId mGenThreadId;
|
||||
std::map<RsGxsGroupId,rstime_t> mKnownForums ;
|
||||
|
||||
RsMutex mKnownForumsMutex;
|
||||
};
|
||||
|
@ -175,14 +175,12 @@ void p3MsgService::processIncomingMsg(RsMsgItem *mi)
|
||||
mi->msgFlags &= (RS_MSG_FLAGS_DISTANT | RS_MSG_FLAGS_SYSTEM); // remove flags except those
|
||||
mi->msgFlags |= RS_MSG_FLAGS_NEW;
|
||||
|
||||
p3Notify *notify = RsServer::notify();
|
||||
if (notify)
|
||||
if (rsEvents)
|
||||
{
|
||||
notify->AddPopupMessage(RS_POPUP_MSG, mi->PeerId().toStdString(), mi->subject, mi->message);
|
||||
|
||||
std::string out;
|
||||
rs_sprintf(out, "%lu", mi->msgId);
|
||||
notify->AddFeedItem(RS_FEED_ITEM_MESSAGE, out, "", "");
|
||||
auto ev = std::make_shared<RsMailStatusEvent>();
|
||||
ev->mMailStatusEventCode = RsMailStatusEventCode::NEW_MESSAGE;
|
||||
ev->mChangedMsgIds.insert(std::to_string(mi->msgId));
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
|
||||
imsg[mi->msgId] = mi;
|
||||
@ -207,13 +205,6 @@ void p3MsgService::processIncomingMsg(RsMsgItem *mi)
|
||||
}
|
||||
|
||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD);
|
||||
|
||||
if(rsEvents)
|
||||
{
|
||||
std::shared_ptr<RsMailStatusEvent> pEvent(new RsMailStatusEvent());
|
||||
pEvent->mChangedMsgIds.insert(std::to_string(mi->msgId));
|
||||
rsEvents->postEvent(pEvent);
|
||||
}
|
||||
}
|
||||
|
||||
bool p3MsgService::checkAndRebuildPartialMessage(RsMsgItem *ci)
|
||||
@ -345,8 +336,8 @@ int p3MsgService::checkOutgoingMessages()
|
||||
bool changed = false;
|
||||
std::list<RsMsgItem*> output_queue;
|
||||
|
||||
using Evt_t = RsMailStatusEvent;
|
||||
std::shared_ptr<Evt_t> pEvent(new Evt_t());
|
||||
auto pEvent = std::make_shared<RsMailStatusEvent>();
|
||||
pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mMsgMtx); /********** STACK LOCKED MTX ******/
|
||||
@ -404,11 +395,10 @@ int p3MsgService::checkOutgoingMessages()
|
||||
mit->second->msgFlags |= RS_MSG_FLAGS_ROUTED;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_DISTANT_MSG
|
||||
else
|
||||
{
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Delaying until available..."
|
||||
<< std::endl;
|
||||
}
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Delaying until available..." << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
@ -906,8 +896,9 @@ bool p3MsgService::removeMsgId(const std::string &mid)
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
using Evt_t = RsMailStatusEvent;
|
||||
std::shared_ptr<Evt_t> pEvent(new Evt_t());
|
||||
|
||||
auto pEvent = std::make_shared<RsMailStatusEvent>();
|
||||
pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_REMOVED;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
|
||||
@ -1274,8 +1265,9 @@ uint32_t p3MsgService::sendMail(
|
||||
std::back_inserter(msgInfo.files) );
|
||||
|
||||
uint32_t ret = 0;
|
||||
using Evt_t = RsMailStatusEvent;
|
||||
std::shared_ptr<Evt_t> pEvent(new Evt_t());
|
||||
|
||||
auto pEvent = std::make_shared<RsMailStatusEvent>();
|
||||
pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT;
|
||||
|
||||
auto pSend = [&](const std::set<RsGxsId>& sDest)
|
||||
{
|
||||
@ -2089,10 +2081,13 @@ void p3MsgService::notifyDataStatus( const GRouterMsgPropagationId& id,
|
||||
NOTIFY_TYPE_ADD );
|
||||
IndicateConfigChanged();
|
||||
|
||||
using Evt_t = RsMailStatusEvent;
|
||||
std::shared_ptr<Evt_t> pEvent(new Evt_t());
|
||||
pEvent->mChangedMsgIds.insert(std::to_string(msg_id));
|
||||
if(rsEvents) rsEvents->postEvent(pEvent);
|
||||
if(rsEvents)
|
||||
{
|
||||
auto pEvent = std::make_shared<RsMailStatusEvent>();
|
||||
pEvent->mMailStatusEventCode = RsMailStatusEventCode::NEW_MESSAGE;
|
||||
pEvent->mChangedMsgIds.insert(std::to_string(msg_id));
|
||||
rsEvents->postEvent(pEvent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -2189,11 +2184,11 @@ bool p3MsgService::notifyGxsTransSendStatus( RsGxsTransId mailId,
|
||||
Dbg2() << __PRETTY_FUNCTION__ << " " << mailId << ", "
|
||||
<< static_cast<uint32_t>(status) << std::endl;
|
||||
|
||||
using Evt_t = RsMailStatusEvent;
|
||||
std::shared_ptr<Evt_t> pEvent(new Evt_t());
|
||||
auto pEvent = std::make_shared<RsMailStatusEvent>();
|
||||
|
||||
if( status == GxsTransSendStatus::RECEIPT_RECEIVED )
|
||||
{
|
||||
pEvent->mMailStatusEventCode = RsMailStatusEventCode::NEW_MESSAGE;
|
||||
uint32_t msg_id;
|
||||
|
||||
{
|
||||
@ -2248,19 +2243,20 @@ bool p3MsgService::notifyGxsTransSendStatus( RsGxsTransId mailId,
|
||||
else if( status >= GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE )
|
||||
{
|
||||
uint32_t msg_id;
|
||||
pEvent->mMailStatusEventCode = RsMailStatusEventCode::SIGNATURE_FAILED;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(gxsOngoingMutex);
|
||||
|
||||
std::cerr << __PRETTY_FUNCTION__ << " mail delivery "
|
||||
<< "mailId: " << mailId
|
||||
<< " failed with " << static_cast<uint32_t>(status);
|
||||
RsErr() << __PRETTY_FUNCTION__ << " mail delivery "
|
||||
<< "mailId: " << mailId
|
||||
<< " failed with " << static_cast<uint32_t>(status);
|
||||
|
||||
auto it = gxsOngoingMessages.find(mailId);
|
||||
if(it == gxsOngoingMessages.end())
|
||||
{
|
||||
std::cerr << " cannot find pending message to notify"
|
||||
<< std::endl;
|
||||
RsErr() << __PRETTY_FUNCTION__
|
||||
<< " cannot find pending message to notify"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "rsitems/rsgxscommentitems.h"
|
||||
|
||||
#include "rsserver/p3face.h"
|
||||
#include "retroshare/rsnotify.h"
|
||||
#include "retroshare/rsposted.h"
|
||||
|
||||
// For Dummy Msgs.
|
||||
#include "util/rsrandom.h"
|
||||
@ -87,12 +87,6 @@ void p3PostBase::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
p3Notify *notify = NULL;
|
||||
if (!changes.empty())
|
||||
{
|
||||
notify = RsServer::notify();
|
||||
}
|
||||
|
||||
std::vector<RsGxsNotify *>::iterator it;
|
||||
|
||||
for(it = changes.begin(); it != changes.end(); ++it)
|
||||
@ -118,13 +112,15 @@ void p3PostBase::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
// It could be taken a step further and directly request these msgs for an update.
|
||||
addGroupForProcessing(mit->first);
|
||||
|
||||
if (notify && msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW)
|
||||
{
|
||||
if (rsEvents && msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW)
|
||||
for (auto mit1 = mit->second.begin(); mit1 != mit->second.end(); ++mit1)
|
||||
{
|
||||
notify->AddFeedItem(RS_FEED_ITEM_POSTED_MSG, mit->first.toStdString(), mit1->toStdString());
|
||||
auto ev = std::make_shared<RsGxsPostedEvent>();
|
||||
ev->mPostedMsgId = *mit1;
|
||||
ev->mPostedGroupId = mit->first;
|
||||
ev->mPostedEventCode = RsPostedEventCode::NEW_MESSAGE;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,17 +133,20 @@ void p3PostBase::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
#endif
|
||||
|
||||
std::list<RsGxsGroupId> &groupList = groupChange->mGrpIdList;
|
||||
std::list<RsGxsGroupId>::iterator git;
|
||||
for(git = groupList.begin(); git != groupList.end(); ++git)
|
||||
|
||||
for(auto git = groupList.begin(); git != groupList.end(); ++git)
|
||||
{
|
||||
#ifdef POSTBASE_DEBUG
|
||||
std::cerr << "p3PostBase::notifyChanges() Incoming Group: " << *git;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if (notify && groupChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW)
|
||||
if (rsEvents && groupChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW)
|
||||
{
|
||||
notify->AddFeedItem(RS_FEED_ITEM_POSTED_NEW, git->toStdString());
|
||||
auto ev = std::make_shared<RsGxsPostedEvent>();
|
||||
ev->mPostedGroupId = *git;
|
||||
ev->mPostedEventCode = RsPostedEventCode::NEW_POSTED_GROUP;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,19 +20,20 @@
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#include <iomanip>
|
||||
#include <sys/time.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "util/rsdir.h"
|
||||
#include "retroshare/rsiface.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
#include "pqi/pqibin.h"
|
||||
#include "pqi/pqistore.h"
|
||||
#include "pqi/p3linkmgr.h"
|
||||
#include "rsserver/p3face.h"
|
||||
|
||||
#include "util/cxx17retrocompat.h"
|
||||
#include "services/p3rtt.h"
|
||||
#include "rsitems/rsrttitems.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <math.h>
|
||||
|
||||
/****
|
||||
* #define DEBUG_RTT 1
|
||||
@ -352,28 +353,29 @@ int p3rtt::storePongResult(const RsPeerId& id, uint32_t counter, double recv_ts,
|
||||
|
||||
|
||||
while(peerInfo->mPongResults.size() > MAX_PONG_RESULTS)
|
||||
{
|
||||
peerInfo->mPongResults.pop_front();
|
||||
}
|
||||
|
||||
//Wait at least 20 pongs before compute mean time offset
|
||||
if(peerInfo->mPongResults.size() > 20)
|
||||
{
|
||||
double mean = 0;
|
||||
for(std::list<RsRttPongResult>::const_iterator prIt = peerInfo->mPongResults.begin(), end = peerInfo->mPongResults.end(); prIt != end; ++ prIt)
|
||||
{
|
||||
mean += prIt->mOffset;
|
||||
}
|
||||
for(auto prIt : std::as_const(peerInfo->mPongResults))
|
||||
mean += prIt.mOffset;
|
||||
peerInfo->mCurrentMeanOffset = mean / peerInfo->mPongResults.size();
|
||||
|
||||
if(fabs(peerInfo->mCurrentMeanOffset) > 120)
|
||||
{
|
||||
p3Notify *notify = RsServer::notify();
|
||||
if (notify)
|
||||
if(rsEvents)
|
||||
{
|
||||
//notify->AddPopupMessage(RS_POPUP_OFFSET, eerInfo->mId.toStdString(),"", "Time Offset: ");
|
||||
notify->AddFeedItem(RS_FEED_ITEM_PEER_OFFSET, peerInfo->mId.toStdString());
|
||||
auto ev = std::make_shared<RsConnectionEvent>();
|
||||
ev->mSslId = peerInfo->mId;
|
||||
ev->mTimeShift = static_cast<rstime_t>(peerInfo->mCurrentMeanOffset);
|
||||
ev->mConnectionInfoCode = RsConnectionEventCode::PEER_TIME_SHIFT;
|
||||
rsEvents->postEvent(ev);
|
||||
}
|
||||
std::cerr << "(WW) Peer:" << peerInfo->mId << " get time offset more than two minutes with you!!!" << std::endl;
|
||||
RsWarn() << __PRETTY_FUNCTION__ << " Peer: " << peerInfo->mId
|
||||
<< " have a time offset of more than two minutes with you"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@ -438,6 +440,7 @@ bool RttPeerInfo::initialisePeerInfo(const RsPeerId& id)
|
||||
mCurrentPingTS = 0;
|
||||
mCurrentPingCounter = 0;
|
||||
mCurrentPongRecvd = true;
|
||||
mCurrentMeanOffset = 0;
|
||||
|
||||
mSentPings = 0;
|
||||
mLostPongs = 0;
|
||||
|
@ -34,6 +34,8 @@ class p3ServiceControl;
|
||||
class RttPeerInfo
|
||||
{
|
||||
public:
|
||||
RttPeerInfo()
|
||||
: mCurrentPingTS(0.0),mCurrentPingCounter(0.0),mCurrentPongRecvd(false),mCurrentMeanOffset(0.0),mLostPongs(0),mSentPings(0){}
|
||||
|
||||
bool initialisePeerInfo(const RsPeerId& id);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
*******************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "services/rseventsservice.h"
|
||||
|
||||
@ -117,7 +118,7 @@ bool RsEventsService::unregisterEventsHandler(RsEventsHandlerId_t hId)
|
||||
return true;
|
||||
}
|
||||
|
||||
void RsEventsService::data_tick()
|
||||
void RsEventsService::threadTick()
|
||||
{
|
||||
auto nextRunAt = std::chrono::system_clock::now() +
|
||||
std::chrono::milliseconds(200);
|
||||
|
@ -71,8 +71,7 @@ protected:
|
||||
RsMutex mEventQueueMtx;
|
||||
std::deque< std::shared_ptr<const RsEvent> > mEventQueue;
|
||||
|
||||
/// @see RsTickingThread
|
||||
void data_tick() override;
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
void handleEvent(std::shared_ptr<const RsEvent> event);
|
||||
RsEventsHandlerId_t generateUniqueHandlerId_unlocked();
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
#include "util/rstime.h"
|
||||
|
||||
struct sockaddr ;
|
||||
|
||||
|
@ -23,8 +23,10 @@
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
#include "util/rsnet.h"
|
||||
#include "util/rstime.h"
|
||||
|
||||
struct sockaddr ;
|
||||
|
||||
|
54
libretroshare/src/util/rserrno.cc
Normal file
54
libretroshare/src/util/rserrno.cc
Normal file
@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
* libretroshare/src/util: rserrno.cc *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <cerrno>
|
||||
|
||||
#define RS_INTERNAL_ERRNO_CASE(e) case e: return #e
|
||||
|
||||
const char* rsErrnoName(int err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
RS_INTERNAL_ERRNO_CASE(EINVAL);
|
||||
RS_INTERNAL_ERRNO_CASE(EBUSY);
|
||||
RS_INTERNAL_ERRNO_CASE(EAGAIN);
|
||||
RS_INTERNAL_ERRNO_CASE(EDEADLK);
|
||||
RS_INTERNAL_ERRNO_CASE(EPERM);
|
||||
RS_INTERNAL_ERRNO_CASE(EBADF);
|
||||
RS_INTERNAL_ERRNO_CASE(EFAULT);
|
||||
RS_INTERNAL_ERRNO_CASE(ENOTSOCK);
|
||||
RS_INTERNAL_ERRNO_CASE(EISCONN);
|
||||
RS_INTERNAL_ERRNO_CASE(ECONNREFUSED);
|
||||
RS_INTERNAL_ERRNO_CASE(ETIMEDOUT);
|
||||
RS_INTERNAL_ERRNO_CASE(ENETUNREACH);
|
||||
RS_INTERNAL_ERRNO_CASE(EADDRINUSE);
|
||||
RS_INTERNAL_ERRNO_CASE(EINPROGRESS);
|
||||
RS_INTERNAL_ERRNO_CASE(EALREADY);
|
||||
RS_INTERNAL_ERRNO_CASE(ENOTCONN);
|
||||
RS_INTERNAL_ERRNO_CASE(EPIPE);
|
||||
RS_INTERNAL_ERRNO_CASE(ECONNRESET);
|
||||
RS_INTERNAL_ERRNO_CASE(EHOSTUNREACH);
|
||||
RS_INTERNAL_ERRNO_CASE(EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
return "rsErrnoName UNKNOWN ERROR CODE";
|
||||
}
|
24
libretroshare/src/util/rserrno.h
Normal file
24
libretroshare/src/util/rserrno.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* libretroshare/src/util: rserrno.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
const char* rsErrnoName(int err);
|
@ -3,7 +3,9 @@
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2004-2007 by Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2004-2007 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -20,14 +22,20 @@
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include "rsthreads.h"
|
||||
#include <unistd.h> // for usleep()
|
||||
#include <errno.h> // for errno
|
||||
#include <iostream>
|
||||
#include "util/rstime.h"
|
||||
#include "util/rsdebug.h"
|
||||
#include <time.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
#include <cstdio>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "rsthreads.h"
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rserrno.h"
|
||||
|
||||
#include "util/rstime.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
int __attribute__((weak)) pthread_setname_np(const char *__buf) ;
|
||||
@ -41,16 +49,14 @@ int RS_pthread_setname_np(pthread_t __target_thread, const char *__buf) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/*******
|
||||
* #define DEBUG_THREADS 1
|
||||
* #define RSMUTEX_ABORT 1 // Catch wrong pthreads mode.
|
||||
*******/
|
||||
#define THREAD_DEBUG std::cerr << "[this=" << (void*)this << ", caller thread ID: " << std::hex << pthread_self() << ", thread ID: " << mTid << std::dec << "] "
|
||||
#define THREAD_DEBUG RsDbg() << "[this=" << static_cast<void*>(this) \
|
||||
<< ", caller thread ID: " << std::hex << pthread_self() << ", thread ID: " \
|
||||
<< mTid << std::dec << "] "
|
||||
|
||||
#ifdef RSMUTEX_ABORT
|
||||
#include <stdlib.h>
|
||||
@ -60,215 +66,113 @@ int RS_pthread_setname_np(pthread_t __target_thread, const char *__buf) {
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
void RsThread::go()
|
||||
/*static*/ void* RsThread::rsthread_init(void* p)
|
||||
{
|
||||
mShouldStopSemaphore.set(0) ;
|
||||
mHasStoppedSemaphore.set(0) ;
|
||||
RsThread* thread = reinterpret_cast<RsThread *>(p);
|
||||
if(!thread) return nullptr;
|
||||
|
||||
runloop();
|
||||
|
||||
mShouldStopSemaphore.set(0);
|
||||
mHasStoppedSemaphore.set(1); // last value that we modify because this is interpreted as a signal that the object can be deleted.
|
||||
}
|
||||
void *RsThread::rsthread_init(void* p)
|
||||
{
|
||||
RsThread *thread = (RsThread *) p;
|
||||
if (!thread)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
// tell the OS to free the thread resources when this function exits
|
||||
// it is a replacement for pthread_join()
|
||||
pthread_detach(pthread_self());
|
||||
/* Using pthread_detach(...) the thread resources will be automatically
|
||||
* freed when this function return, so there is no need for pthread_join()
|
||||
* later. */
|
||||
pthread_detach(pthread_self());
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
std::cerr << "[Thread ID:" << std::hex << pthread_self() << std::dec << "] thread is started. Calling runloop()..." << std::endl;
|
||||
std::cerr << "[Thread ID:" << std::hex << pthread_self() << std::dec
|
||||
<< "] thread is started. Calling wrapRun()..." << std::endl;
|
||||
#endif
|
||||
|
||||
thread->go();
|
||||
return NULL;
|
||||
|
||||
thread->wrapRun();
|
||||
return nullptr;
|
||||
}
|
||||
RsThread::RsThread()
|
||||
|
||||
RsThread::RsThread() : mHasStopped(true), mShouldStop(false)
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
memset (&mTid, 0, sizeof(mTid));
|
||||
memset (&mTid, 0, sizeof(mTid));
|
||||
#else
|
||||
mTid = 0;
|
||||
#endif
|
||||
// The thread is certainly not running. This avoids to lock down when calling shutdown on a thread that has never started.
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "[Thread ID:" << std::hex << pthread_self() << std::dec << "] thread object created. Initing stopped=1, should_stop=0" << std::endl;
|
||||
#endif
|
||||
mHasStoppedSemaphore.set(1) ;
|
||||
mShouldStopSemaphore.set(0) ;
|
||||
}
|
||||
|
||||
RsThread::~RsThread()
|
||||
{
|
||||
if(isRunning())
|
||||
{
|
||||
RsErr() << "Deleting a thread that is still running! Something is very wrong here and Retroshare is likely to crash because of this." << std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
while(isRunning())
|
||||
{
|
||||
std::cerr << "." << std::endl;
|
||||
rstime::rs_usleep(1000*1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RsThread::isRunning()
|
||||
{
|
||||
// do we need a mutex for this ?
|
||||
int sval = mHasStoppedSemaphore.value() ;
|
||||
|
||||
return !sval ;
|
||||
}
|
||||
|
||||
bool RsThread::shouldStop()
|
||||
{
|
||||
int sval = mShouldStopSemaphore.value() ;
|
||||
return sval > 0;
|
||||
}
|
||||
|
||||
void RsTickingThread::shutdown()
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "pqithreadstreamer::shutdown()" << std::endl;
|
||||
#endif
|
||||
|
||||
int sval = mHasStoppedSemaphore.value() ;
|
||||
|
||||
if(sval > 0)
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << " thread not running. Quit." << std::endl;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
|
||||
ask_for_stop() ;
|
||||
}
|
||||
|
||||
void RsThread::ask_for_stop()
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << " calling stop" << std::endl;
|
||||
#endif
|
||||
mShouldStopSemaphore.set(1);
|
||||
}
|
||||
|
||||
void RsTickingThread::fullstop()
|
||||
{
|
||||
shutdown() ;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << " waiting stop" << std::endl;
|
||||
#endif
|
||||
if(pthread_equal(mTid,pthread_self()))
|
||||
{
|
||||
THREAD_DEBUG << "(WW) RsTickingThread::fullstop() called by same thread. This is unexpected." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
mHasStoppedSemaphore.wait_no_relock(); // Wait for semaphore value to become 1, but does not decrement it when obtained.
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << " finished!" << std::endl;
|
||||
mTid = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void RsThread::start(const std::string &threadName)
|
||||
bool RsThread::isRunning() { return !mHasStopped; }
|
||||
|
||||
bool RsThread::shouldStop() { return mShouldStop; }
|
||||
|
||||
void RsThread::askForStop()
|
||||
{
|
||||
if(isRunning())
|
||||
/* Call onStopRequested() only once even if askForStop() is called multiple
|
||||
* times */
|
||||
if(!mShouldStop.exchange(true))
|
||||
RsThread::async([&](){ onStopRequested(); });
|
||||
}
|
||||
|
||||
void RsThread::wrapRun()
|
||||
{
|
||||
run();
|
||||
mHasStopped = true;
|
||||
}
|
||||
|
||||
void RsThread::fullstop()
|
||||
{
|
||||
askForStop();
|
||||
|
||||
const pthread_t callerTid = pthread_self();
|
||||
if(pthread_equal(mTid, callerTid))
|
||||
{
|
||||
std::cerr << "(EE) RsThread \"" << threadName
|
||||
<< "\" is already running. Will not start twice!"
|
||||
<< std::endl;
|
||||
RsErr() << __PRETTY_FUNCTION__ << " called by same thread. This should "
|
||||
<< "never happen! this: " << static_cast<void*>(this)
|
||||
<< std::hex << ", callerTid: " << callerTid
|
||||
<< ", mTid: " << mTid << std::dec << std::endl;
|
||||
print_stacktrace();
|
||||
return;
|
||||
}
|
||||
pthread_t tid;
|
||||
void *data = (void *)this ;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "pqithreadstreamer::start() initing should_stop=0" << std::endl;
|
||||
#endif
|
||||
mShouldStopSemaphore.set(0) ;
|
||||
mHasStoppedSemaphore.set(0) ;
|
||||
|
||||
int err ;
|
||||
|
||||
// pthread_create is a memory barrier
|
||||
// -> the new thread will see mIsRunning() = true
|
||||
|
||||
if( 0 == (err=pthread_create(&tid, 0, &rsthread_init, data)))
|
||||
{
|
||||
mTid = tid;
|
||||
|
||||
// set name
|
||||
|
||||
if(pthread_setname_np)
|
||||
{
|
||||
if(!threadName.empty())
|
||||
{
|
||||
// thread names are restricted to 16 characters including the terminating null byte
|
||||
if(threadName.length() > 15)
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "RsThread::start called with to long name '" << threadName << "' truncating..." << std::endl;
|
||||
#endif
|
||||
RS_pthread_setname_np(mTid, threadName.substr(0, 15).c_str());
|
||||
} else {
|
||||
RS_pthread_setname_np(mTid, threadName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
THREAD_DEBUG << "Fatal error: pthread_create could not create a thread. Error returned: " << err << " !!!!!!!" << std::endl;
|
||||
mHasStoppedSemaphore.set(1) ;
|
||||
}
|
||||
// Wait for the thread being stopped
|
||||
auto i = 1;
|
||||
while(!mHasStopped)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
++i;
|
||||
if(!(i%5))
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " " << i*0.2 << " seconds passed"
|
||||
<< " waiting for thread: " << mTid << " " << mFullName
|
||||
<< " to stop" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
RsTickingThread::RsTickingThread()
|
||||
bool RsThread::start(const std::string& threadName)
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "RsTickingThread::RsTickingThread()" << std::endl;
|
||||
#endif
|
||||
}
|
||||
// Atomically check if the thread was already started and set it as running
|
||||
if(mHasStopped.exchange(false))
|
||||
{
|
||||
mShouldStop = false;
|
||||
int pError = pthread_create(
|
||||
&mTid, nullptr, &rsthread_init, static_cast<void*>(this) );
|
||||
if(pError)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " pthread_create could not create"
|
||||
<< " new thread: " << threadName << " pError: " << pError
|
||||
<< std::endl;
|
||||
mHasStopped = true;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
RsTickingThread::~RsTickingThread()
|
||||
{
|
||||
fullstop();
|
||||
}
|
||||
void RsSingleJobThread::runloop()
|
||||
{
|
||||
run() ;
|
||||
}
|
||||
/* Store thread full name as PThread is not able to keep it entirely */
|
||||
mFullName = threadName;
|
||||
|
||||
void RsTickingThread::runloop()
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "RsTickingThread::runloop(). Setting stopped=0" << std::endl;
|
||||
#endif
|
||||
/* Set PThread thread name which is restricted to 16 characters
|
||||
* including the terminating null byte */
|
||||
if(pthread_setname_np && !threadName.empty())
|
||||
RS_pthread_setname_np(mTid, threadName.substr(0, 15).c_str());
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(shouldStop())
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "pqithreadstreamer::runloop(): asked to stop. setting hasStopped=1, and returning. Thread ends." << std::endl;
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
data_tick();
|
||||
}
|
||||
RsErr() << __PRETTY_FUNCTION__ << " attempt to start already running thread"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor )
|
||||
@ -278,14 +182,14 @@ RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor )
|
||||
mLastWork = time(NULL) ;
|
||||
}
|
||||
|
||||
void RsQueueThread::data_tick()
|
||||
void RsQueueThread::threadTick()
|
||||
{
|
||||
bool doneWork = false;
|
||||
while(workQueued() && doWork())
|
||||
{
|
||||
doneWork = true;
|
||||
}
|
||||
rstime_t now = time(NULL);
|
||||
time_t now = time(NULL);
|
||||
if (doneWork)
|
||||
{
|
||||
mLastWork = now;
|
||||
@ -310,94 +214,38 @@ void RsQueueThread::data_tick()
|
||||
THREAD_DEBUG << "RsQueueThread::data_tick() no work: sleeping for: " << mLastSleep << " ms" << std::endl;
|
||||
#endif
|
||||
}
|
||||
rstime::rs_usleep(mLastSleep * 1000); // mLastSleep msec
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(mLastSleep));
|
||||
}
|
||||
|
||||
void RsMutex::unlock()
|
||||
{
|
||||
#ifdef RSTHREAD_SELF_LOCKING_GUARD
|
||||
if(--_cnt == 0)
|
||||
{
|
||||
#endif
|
||||
_thread_id = 0 ;
|
||||
pthread_mutex_unlock(&realMutex);
|
||||
|
||||
#ifdef RSTHREAD_SELF_LOCKING_GUARD
|
||||
}
|
||||
#endif
|
||||
{
|
||||
_thread_id = 0;
|
||||
pthread_mutex_unlock(&realMutex);
|
||||
}
|
||||
|
||||
void RsMutex::lock()
|
||||
{
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
pthread_t owner = _thread_id ;
|
||||
#endif
|
||||
|
||||
int retval = 0;
|
||||
#ifdef RSTHREAD_SELF_LOCKING_GUARD
|
||||
if(!trylock())
|
||||
if(!pthread_equal(_thread_id,pthread_self()))
|
||||
#endif
|
||||
retval = pthread_mutex_lock(&realMutex);
|
||||
|
||||
switch(retval)
|
||||
int err = pthread_mutex_lock(&realMutex);
|
||||
if( err != 0)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
RsErr() << __PRETTY_FUNCTION__ << "pthread_mutex_lock returned: "
|
||||
<< rsErrnoName(err)
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
<< " name: " << name
|
||||
#endif
|
||||
<< std::endl;
|
||||
|
||||
case EINVAL:
|
||||
std::cerr << "RsMutex::lock() pthread_mutex_lock returned EINVAL";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
|
||||
case EBUSY:
|
||||
std::cerr << "RsMutex::lock() pthread_mutex_lock returned EBUSY";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
|
||||
case EAGAIN:
|
||||
std::cerr << "RsMutex::lock() pthread_mutex_lock returned EAGAIN";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
|
||||
case EDEADLK:
|
||||
std::cerr << "RsMutex::lock() pthread_mutex_lock returned EDEADLK";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
|
||||
case EPERM:
|
||||
std::cerr << "RsMutex::lock() pthread_mutex_lock returned EPERM";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
print_stacktrace();
|
||||
|
||||
default:
|
||||
std::cerr << "RsMutex::lock() pthread_mutex_lock returned UNKNOWN ERROR";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Here is some debugging code - to catch failed locking attempts.
|
||||
* Major bug is it is ever triggered.
|
||||
*/
|
||||
#ifdef RSMUTEX_ABORT
|
||||
|
||||
if (retval != 0)
|
||||
{
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
std::cerr << "RsMutex::lock() name: " << name << std::endl;
|
||||
#endif
|
||||
std::cerr << "RsMutex::lock() pthread_mutex_lock returned an Error. Aborting()";
|
||||
std::cerr << std::endl;
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
_thread_id = pthread_self() ;
|
||||
#ifdef RSTHREAD_SELF_LOCKING_GUARD
|
||||
++_cnt ;
|
||||
#endif
|
||||
_thread_id = pthread_self();
|
||||
}
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
double RsStackMutex::getCurrentTS()
|
||||
{
|
||||
@ -416,3 +264,18 @@ double RsStackMutex::getCurrentTS()
|
||||
#endif
|
||||
|
||||
|
||||
RsThread::~RsThread()
|
||||
{
|
||||
if(isRunning())
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " deleting thread: " << mTid << " "
|
||||
<< mFullName << " that is still "
|
||||
<< "running! Something seems very wrong here and RetroShare is "
|
||||
<< "likely to crash because of this." << std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
fullstop();
|
||||
}
|
||||
}
|
||||
|
||||
RsQueueThread::~RsQueueThread() = default;
|
||||
|
@ -3,7 +3,9 @@
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2004-2006 by Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2004-2006 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2016-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -26,243 +28,199 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <semaphore.h>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
#include <util/rsmemory.h>
|
||||
#include "util/rstime.h"
|
||||
#include "util/rsmemory.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
|
||||
/* RsIface Thread Wrappers */
|
||||
|
||||
#undef RSTHREAD_SELF_LOCKING_GUARD
|
||||
//#define RSMUTEX_DEBUG 300 // Milliseconds for print in the stderr
|
||||
//#define RSMUTEX_DEBUG
|
||||
//#define RSMUTEX_DEBUG
|
||||
|
||||
/**
|
||||
* @brief Provide mutexes that keep track of the owner. Based on pthread mutex.
|
||||
*/
|
||||
class RsMutex
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
RsMutex(const std::string& name)
|
||||
{
|
||||
/* remove unused parameter warnings */
|
||||
|
||||
pthread_mutex_init(&realMutex, NULL);
|
||||
_thread_id = 0 ;
|
||||
RsMutex(const std::string& name) : _thread_id(0)
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
this->_name = name;
|
||||
#else
|
||||
(void) name;
|
||||
, _name(name)
|
||||
#endif
|
||||
{
|
||||
pthread_mutex_init(&realMutex, nullptr);
|
||||
|
||||
#ifndef RSMUTEX_DEBUG
|
||||
(void) name; // remove unused parameter warnings
|
||||
#endif
|
||||
}
|
||||
~RsMutex()
|
||||
{
|
||||
pthread_mutex_destroy(&realMutex);
|
||||
}
|
||||
|
||||
inline const pthread_t& owner() const { return _thread_id ; }
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
void setName(const std::string &name)
|
||||
{
|
||||
this->_name = name;
|
||||
}
|
||||
#endif
|
||||
~RsMutex() { pthread_mutex_destroy(&realMutex); }
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); }
|
||||
inline const pthread_t& owner() const { return _thread_id; }
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); }
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
const std::string& name() const { return _name ; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
pthread_mutex_t realMutex;
|
||||
pthread_t _thread_id ;
|
||||
#ifdef RSTHREAD_SELF_LOCKING_GUARD
|
||||
uint32_t _cnt ;
|
||||
#endif
|
||||
private:
|
||||
pthread_mutex_t realMutex;
|
||||
pthread_t _thread_id;
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
std::string _name;
|
||||
std::string _name;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @def RS_STACK_MUTEX(m)
|
||||
* This macro allows you to trace which mutex in the code is locked and for how
|
||||
* much time. You can use this as follows:
|
||||
* @code
|
||||
* {
|
||||
* RS_STACK_MUTEX(myMutex);
|
||||
* do_something();
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
#define RS_STACK_MUTEX(m) \
|
||||
RsStackMutex __local_retroshare_stack_mutex_##m( \
|
||||
m, __PRETTY_FUNCTION__, __FILE__, __LINE__ )
|
||||
|
||||
/**
|
||||
* Provide mutexes that automatically lock/unlock on creation/destruction and
|
||||
* have powerfull debugging facilities (if RSMUTEX_DEBUG is defined at
|
||||
* compiletime).
|
||||
* In most of the cases you should not use this directly instead
|
||||
* @see RS_STACK_MUTEX(m)
|
||||
*/
|
||||
class RsStackMutex
|
||||
{
|
||||
public:
|
||||
|
||||
RsStackMutex(RsMutex &mtx)
|
||||
: mMtx(mtx)
|
||||
{
|
||||
mMtx.lock();
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
double ts = getCurrentTS() ;
|
||||
_time_stamp = ts ;
|
||||
_lineno = 0 ;
|
||||
_info = "[no info]" ;
|
||||
#endif
|
||||
}
|
||||
RsStackMutex(RsMutex &mtx,const char *function_name,const char *file_name,int lineno)
|
||||
: mMtx(mtx)
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
, _info(std::string(function_name)+" in file "+file_name),_lineno(lineno)
|
||||
#endif
|
||||
{
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
double ts = getCurrentTS() ;
|
||||
_time_stamp = ts ;
|
||||
pthread_t owner = mMtx.owner() ;
|
||||
#else
|
||||
/* remove unused parameter warnings */
|
||||
(void) function_name;
|
||||
(void) file_name;
|
||||
(void) lineno;
|
||||
#endif
|
||||
|
||||
mMtx.lock();
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
ts = getCurrentTS() ;
|
||||
|
||||
if(ts - _time_stamp > 1.0)
|
||||
std::cerr << "Mutex " << (void*)&mMtx << " \"" << mtx.name() << "\""
|
||||
<< " waited for " << ts - _time_stamp
|
||||
<< " seconds in thread " << pthread_self()
|
||||
<< " for locked thread " << owner << ". in " << _info << ":" << _lineno << std::endl;
|
||||
|
||||
_time_stamp = ts ; // This is to re-init the locking time without accounting for how much we waited.
|
||||
#endif
|
||||
}
|
||||
|
||||
~RsStackMutex()
|
||||
{
|
||||
mMtx.unlock();
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
double ts = getCurrentTS() ;
|
||||
|
||||
if(ts - _time_stamp > 1.0)
|
||||
std::cerr << "Mutex " << (void*)&mMtx << " \"" << mMtx.name() << "\""
|
||||
<< " locked for " << ts - _time_stamp
|
||||
<< " seconds in thread " << pthread_self()
|
||||
<< ". in " << _info << ":" << _lineno << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
RsMutex &mMtx;
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
static double getCurrentTS() ;
|
||||
double _time_stamp ;
|
||||
std::string _info ;
|
||||
int _lineno ;
|
||||
#endif
|
||||
};
|
||||
|
||||
// This macro allows you to trace which mutex in the code is locked for how much time.
|
||||
// se this as follows:
|
||||
//
|
||||
// {
|
||||
// RS_STACK_MUTEX(myMutex) ;
|
||||
//
|
||||
// do_something() ;
|
||||
// }
|
||||
//
|
||||
#define RS_STACK_MUTEX(m) RsStackMutex __local_retroshare_mutex(m,__PRETTY_FUNCTION__,__FILE__,__LINE__)
|
||||
|
||||
// This class handles a Mutex-based semaphore, that makes it cross plateform.
|
||||
class RsSemaphore
|
||||
{
|
||||
class RsSemStruct
|
||||
{
|
||||
public:
|
||||
RsSemStruct() : mtx("Semaphore mutex"), val(0) {}
|
||||
|
||||
RsMutex mtx ;
|
||||
uint32_t val ;
|
||||
};
|
||||
|
||||
public:
|
||||
RsSemaphore()
|
||||
{
|
||||
s = new RsSemStruct ;
|
||||
}
|
||||
|
||||
~RsSemaphore()
|
||||
{
|
||||
delete s ;
|
||||
}
|
||||
RsStackMutex(RsMutex &mtx) : mMtx(mtx)
|
||||
{
|
||||
mMtx.lock();
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
double ts = getCurrentTS();
|
||||
_time_stamp = ts;
|
||||
_lineno = 0;
|
||||
_info = "[no info]";
|
||||
#endif
|
||||
}
|
||||
|
||||
void set(uint32_t i)
|
||||
{
|
||||
RS_STACK_MUTEX(s->mtx) ;
|
||||
s->val = i ;
|
||||
}
|
||||
RsStackMutex(RsMutex &mtx, const char *function_name, const char *file_name,
|
||||
int lineno) : mMtx(mtx)
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
, _info(std::string(function_name)+" in file "+file_name), _lineno(lineno)
|
||||
#endif
|
||||
{
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
double ts = getCurrentTS();
|
||||
_time_stamp = ts;
|
||||
pthread_t owner = mMtx.owner();
|
||||
#else
|
||||
// remove unused parameter warnings
|
||||
(void) function_name; (void) file_name; (void) lineno;
|
||||
#endif
|
||||
|
||||
void post()
|
||||
{
|
||||
RS_STACK_MUTEX(s->mtx) ;
|
||||
++(s->val) ;
|
||||
}
|
||||
mMtx.lock();
|
||||
|
||||
uint32_t value()
|
||||
{
|
||||
RS_STACK_MUTEX(s->mtx) ;
|
||||
return s->val ;
|
||||
}
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
ts = getCurrentTS();
|
||||
|
||||
// waits but does not re-locks the semaphore
|
||||
|
||||
void wait_no_relock()
|
||||
{
|
||||
static const uint32_t max_waiting_time_before_warning=1000 *5 ; // 5 secs
|
||||
uint32_t tries=0;
|
||||
if(ts - _time_stamp > 1.0)
|
||||
std::cerr << "Mutex " << (void*)&mMtx << " \"" << mtx.name() << "\""
|
||||
<< " waited for " << ts - _time_stamp
|
||||
<< " seconds in thread " << pthread_self()
|
||||
<< " for locked thread " << owner << ". in " << _info
|
||||
<< ":" << _lineno << std::endl;
|
||||
_time_stamp = ts ; // This is to re-init the locking time without accounting for how much we waited.
|
||||
#endif
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
usleep(1000) ;
|
||||
if(++tries >= max_waiting_time_before_warning)
|
||||
std::cerr << "(EE) Semaphore waiting for too long. Something is probably wrong in the code." << std::endl;
|
||||
~RsStackMutex()
|
||||
{
|
||||
mMtx.unlock();
|
||||
|
||||
RS_STACK_MUTEX(s->mtx) ;
|
||||
if(s->val > 0)
|
||||
return ;
|
||||
}
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
double ts = getCurrentTS();
|
||||
|
||||
if(ts - _time_stamp > 1.0)
|
||||
std::cerr << "Mutex " << (void*)&mMtx << " \"" << mMtx.name()
|
||||
<< "\"" << " locked for " << ts - _time_stamp
|
||||
<< " seconds in thread " << pthread_self()
|
||||
<< ". in " << _info << ":" << _lineno << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
private:
|
||||
RsSemStruct *s ;
|
||||
RsMutex &mMtx;
|
||||
|
||||
#ifdef RSMUTEX_DEBUG
|
||||
static double getCurrentTS();
|
||||
double _time_stamp;
|
||||
std::string _info;
|
||||
int _lineno;
|
||||
#endif
|
||||
};
|
||||
|
||||
class RsThread;
|
||||
|
||||
/* to create a thread! */
|
||||
pthread_t createThread(RsThread &thread);
|
||||
|
||||
/// @brief Offer basic threading functionalities.
|
||||
class RsThread
|
||||
{
|
||||
public:
|
||||
RsThread();
|
||||
virtual ~RsThread() ;
|
||||
|
||||
void start(const std::string &threadName = "");
|
||||
|
||||
// Returns true if the thread is still running.
|
||||
|
||||
bool isRunning();
|
||||
|
||||
// Returns true if the thread received a stopping order and hasn't yet stopped.
|
||||
|
||||
bool shouldStop();
|
||||
|
||||
// Can be called to set the stopping flags. The stop will not be handled
|
||||
// by RsThread itself, but in subclasses. If you derive your own subclass,
|
||||
// you need to call shouldStop() in order to check for a possible stopping order.
|
||||
|
||||
void ask_for_stop();
|
||||
RsThread();
|
||||
virtual ~RsThread();
|
||||
|
||||
/**
|
||||
* Execute given function on another thread without blocking the caller
|
||||
* @brief start the thread and call run() on it.
|
||||
* @param threadName string containing the name of the thread used for
|
||||
* debugging purposes, @note inside PThread it is
|
||||
* truncated to 16 characters including \0 at the end of
|
||||
* the string.
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
bool start(const std::string& threadName = "");
|
||||
|
||||
/**
|
||||
* @brief Check if thread is running.
|
||||
* @return true if the thread is still running, false otherwise.
|
||||
*/
|
||||
bool isRunning();
|
||||
|
||||
/**
|
||||
* @brief Check if the thread should stop.
|
||||
* Expecially useful for subclasses which implement a @see run() method
|
||||
* which may take lot of time before returning when not asked, to check if
|
||||
* stop has been requested and therefore interrupting the execution ASAP
|
||||
* returning in a coherent state.
|
||||
* @return true if the thread received a stopping order.
|
||||
*/
|
||||
bool shouldStop();
|
||||
|
||||
/**
|
||||
* @brief Asyncronously ask the thread to stop.
|
||||
* The real stop will happen when the @see run() method finish.
|
||||
*/
|
||||
void askForStop();
|
||||
|
||||
/**
|
||||
* Call @see askForStop() then wait it has really stopped before returning.
|
||||
* It must not be called in the same thread, as it would not wait for the
|
||||
* effective stop to occur as it would cause a deadlock.
|
||||
*/
|
||||
void fullstop();
|
||||
|
||||
/**
|
||||
* Execute given function on a detached thread without blocking the caller
|
||||
* execution.
|
||||
* This can be generalized with variadic template, ATM it is enough to wrap
|
||||
* any kind of function call or job into a lambda which get no paramethers
|
||||
@ -272,60 +230,84 @@ public:
|
||||
static void async(const std::function<void()>& fn)
|
||||
{ std::thread(fn).detach(); }
|
||||
|
||||
/** @return RsThread full name */
|
||||
const std::string& threadName() { return mFullName; }
|
||||
|
||||
protected:
|
||||
virtual void runloop() =0; /* called once the thread is started. Should be overloaded by subclasses. */
|
||||
void go() ; // this one calls runloop and also sets the flags correctly when the thread is finished running.
|
||||
/**
|
||||
* This method must be implemented by sublasses, will be called once the
|
||||
* thread is started. Should return on request, use @see shouldStop() to
|
||||
* check if stop has been requested.
|
||||
*/
|
||||
virtual void run() = 0;
|
||||
|
||||
RsSemaphore mHasStoppedSemaphore;
|
||||
RsSemaphore mShouldStopSemaphore;
|
||||
/**
|
||||
* This method is meant to be overridden by subclasses with long running
|
||||
* @see run() method and is executed asyncronously when @see askForStop()
|
||||
* is called, any task necessary to stop the thread (aka inducing @see run()
|
||||
* to return in a coherent state) should be done in the overridden version
|
||||
* of this method, @see JsonApiServer for an usage example. */
|
||||
virtual void onStopRequested() {}
|
||||
|
||||
static void *rsthread_init(void*) ;
|
||||
pthread_t mTid;
|
||||
private:
|
||||
/** Call @see run() setting the appropriate flags around it*/
|
||||
void wrapRun();
|
||||
|
||||
/// True if thread is stopped, false otherwise
|
||||
std::atomic<bool> mHasStopped;
|
||||
|
||||
/// True if stop has been requested
|
||||
std::atomic<bool> mShouldStop;
|
||||
|
||||
/// Passed as argument for pthread_create(), call start()
|
||||
static void *rsthread_init(void*);
|
||||
|
||||
/// Store the id of the corresponding pthread
|
||||
pthread_t mTid;
|
||||
|
||||
/// Store thread full name
|
||||
std::string mFullName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide a detached execution loop that continuously call data_tick() once the
|
||||
* thread is started
|
||||
*/
|
||||
class RsTickingThread: public RsThread
|
||||
{
|
||||
public:
|
||||
RsTickingThread();
|
||||
virtual ~RsTickingThread();
|
||||
|
||||
void shutdown();
|
||||
void fullstop();
|
||||
void join() { fullstop() ; } // used for compatibility
|
||||
|
||||
virtual void data_tick() =0;
|
||||
/**
|
||||
* Subclasses must implement this method, it will be called in a loop once
|
||||
* the thread is started, so repetitive work (like checking if data is
|
||||
* available on a socket) should be done here, at the end of this method
|
||||
* sleep_for(...) or similar function should be called or the CPU will
|
||||
* be used as much as possible also if there is nothing to do.
|
||||
*/
|
||||
virtual void threadTick() = 0;
|
||||
|
||||
private:
|
||||
virtual void runloop() ; /* called once the thread is started. Should be overloaded by subclasses. */
|
||||
};
|
||||
|
||||
class RsSingleJobThread: public RsThread
|
||||
{
|
||||
public:
|
||||
virtual void run() =0;
|
||||
|
||||
protected:
|
||||
virtual void runloop() ;
|
||||
/// Implement the run loop and continuously call threadTick() in it
|
||||
void run() override { while(!shouldStop()) threadTick(); }
|
||||
};
|
||||
|
||||
// TODO: Used just one time, is this really an useful abstraction?
|
||||
class RsQueueThread: public RsTickingThread
|
||||
{
|
||||
public:
|
||||
|
||||
RsQueueThread(uint32_t min, uint32_t max, double relaxFactor );
|
||||
virtual ~RsQueueThread() { return; }
|
||||
RsQueueThread(uint32_t min, uint32_t max, double relaxFactor);
|
||||
~RsQueueThread() override;
|
||||
|
||||
protected:
|
||||
virtual bool workQueued() = 0;
|
||||
virtual bool doWork() = 0;
|
||||
|
||||
virtual bool workQueued() = 0;
|
||||
virtual bool doWork() = 0;
|
||||
virtual void data_tick() ;
|
||||
void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
private:
|
||||
uint32_t mMinSleep; /* ms */
|
||||
uint32_t mMaxSleep; /* ms */
|
||||
uint32_t mLastSleep; /* ms */
|
||||
rstime_t mLastWork; /* secs */
|
||||
time_t mLastWork; /* secs */
|
||||
float mRelaxFactor;
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,7 +56,7 @@ class RsFeedItem;
|
||||
class FeedNotify;
|
||||
class FeedItem;
|
||||
|
||||
class NewsFeed : public RsAutoUpdatePage, public FeedHolder, public TokenResponse
|
||||
class NewsFeed : public MainPage,public FeedHolder
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -81,7 +81,7 @@ public:
|
||||
static void testFeeds(uint notifyFlags);
|
||||
static void testFeed(FeedNotify *feedNotify);
|
||||
|
||||
virtual void updateDisplay();
|
||||
void handleEvent(std::shared_ptr<const RsEvent> event); // get events from libretroshare
|
||||
|
||||
signals:
|
||||
void newsFeedChanged(int count);
|
||||
@ -89,82 +89,36 @@ signals:
|
||||
protected:
|
||||
void processSettings(bool load);
|
||||
|
||||
/* TokenResponse */
|
||||
virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req);
|
||||
|
||||
private slots:
|
||||
// void toggleChanMsgItems(bool on);
|
||||
void feedoptions();
|
||||
void sortChanged(int index);
|
||||
|
||||
void sendNewsFeedChanged();
|
||||
|
||||
private:
|
||||
void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
|
||||
|
||||
void handleSecurityEvent(std::shared_ptr<const RsEvent> event);
|
||||
void handleConnectionEvent(std::shared_ptr<const RsEvent> event);
|
||||
void handleCircleEvent(std::shared_ptr<const RsEvent> event);
|
||||
void handleForumEvent(std::shared_ptr<const RsEvent> event);
|
||||
void handleMailEvent(std::shared_ptr<const RsEvent> event);
|
||||
void handlePostedEvent(std::shared_ptr<const RsEvent> event);
|
||||
void handleChannelEvent(std::shared_ptr<const RsEvent> event);
|
||||
|
||||
void addFeedItem(FeedItem *item);
|
||||
void addFeedItemIfUnique(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, bool replace);
|
||||
void remUniqueFeedItem(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4);
|
||||
|
||||
void addFeedItemPeerConnect(const RsFeedItem &fi);
|
||||
void addFeedItemPeerDisconnect(const RsFeedItem &fi);
|
||||
void addFeedItemPeerHello(const RsFeedItem &fi);
|
||||
void addFeedItemPeerNew(const RsFeedItem &fi);
|
||||
void addFeedItemPeerOffset(const RsFeedItem &fi);
|
||||
|
||||
void addFeedItemSecurityConnectAttempt(const RsFeedItem &fi);
|
||||
void addFeedItemSecurityAuthDenied(const RsFeedItem &fi);
|
||||
void addFeedItemSecurityUnknownIn(const RsFeedItem &fi);
|
||||
void addFeedItemSecurityUnknownOut(const RsFeedItem &fi);
|
||||
void addFeedItemSecurityIpBlacklisted(const RsFeedItem &fi, bool isTest);
|
||||
void addFeedItemSecurityWrongExternalIpReported(const RsFeedItem &fi, bool isTest);
|
||||
|
||||
void addFeedItemChannelNew(const RsFeedItem &fi);
|
||||
// void addFeedItemChannelUpdate(const RsFeedItem &fi);
|
||||
void addFeedItemChannelMsg(const RsFeedItem &fi);
|
||||
void addFeedItemChannelPublishKey(const RsFeedItem &fi);
|
||||
|
||||
void addFeedItemForumNew(const RsFeedItem &fi);
|
||||
// void addFeedItemForumUpdate(const RsFeedItem &fi);
|
||||
void addFeedItemForumMsg(const RsFeedItem &fi);
|
||||
|
||||
void addFeedItemPostedNew(const RsFeedItem &fi);
|
||||
// void addFeedItemPostedUpdate(const RsFeedItem &fi);
|
||||
void addFeedItemPostedMsg(const RsFeedItem &fi);
|
||||
|
||||
void addFeedItemIfUnique(FeedItem *item, bool replace);
|
||||
void remUniqueFeedItem(FeedItem *item);
|
||||
#if 0
|
||||
void addFeedItemBlogNew(const RsFeedItem &fi);
|
||||
void addFeedItemBlogMsg(const RsFeedItem &fi);
|
||||
#endif
|
||||
|
||||
void addFeedItemChatNew(const RsFeedItem &fi, bool addWithoutCheck);
|
||||
void addFeedItemMessage(const RsFeedItem &fi);
|
||||
void addFeedItemFilesNew(const RsFeedItem &fi);
|
||||
|
||||
void addFeedItemCircleMembReq(const RsFeedItem &fi);
|
||||
void remFeedItemCircleMembReq(const RsFeedItem &fi);
|
||||
void addFeedItemCircleInvitRec(const RsFeedItem &fi);
|
||||
|
||||
virtual void loadChannelGroup(const uint32_t &token);
|
||||
virtual void loadChannelPost(const uint32_t &token);
|
||||
virtual void loadChannelPublishKey(const uint32_t &token);
|
||||
|
||||
virtual void loadForumGroup(const uint32_t &token);
|
||||
virtual void loadForumMessage(const uint32_t &token);
|
||||
virtual void loadForumPublishKey(const uint32_t &token);
|
||||
|
||||
virtual void loadPostedGroup(const uint32_t &token);
|
||||
virtual void loadPostedMessage(const uint32_t &token);
|
||||
|
||||
virtual void loadCircleGroup(const uint32_t &token);
|
||||
virtual void loadCircleMessage(const uint32_t &token);
|
||||
|
||||
private:
|
||||
TokenQueue *mTokenQueueChannel;
|
||||
TokenQueue *mTokenQueueCircle;
|
||||
TokenQueue *mTokenQueueForum;
|
||||
TokenQueue *mTokenQueuePosted;
|
||||
|
||||
/* UI - from Designer */
|
||||
Ui::NewsFeed *ui;
|
||||
|
||||
RsEventsHandlerId_t mEventHandlerId;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
const RsPostedPost &getPost() const;
|
||||
RsPostedPost &post();
|
||||
|
||||
uint64_t uniqueIdentifier() const override { return hash_64bits("PostedItem " + mMessageId.toStdString()); }
|
||||
protected:
|
||||
/* FeedItem */
|
||||
virtual void doExpand(bool open);
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>825</width>
|
||||
<height>337</height>
|
||||
<height>339</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -529,10 +529,22 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="readAndClearButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>44</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
<width>50</width>
|
||||
<height>44</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@ -549,10 +561,22 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>44</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
<width>50</width>
|
||||
<height>44</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@ -692,9 +716,9 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Posted_images.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="Posted_images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -37,6 +37,8 @@
|
||||
#define POSTED_DEFAULT_LISTING_LENGTH 10
|
||||
#define POSTED_MAX_INDEX 10000
|
||||
|
||||
#define DEBUG_POSTED_LIST_WIDGET
|
||||
|
||||
#define TOPIC_DEFAULT_IMAGE ":/icons/png/posted.png"
|
||||
|
||||
/** Constructor */
|
||||
@ -143,15 +145,19 @@ QScrollArea *PostedListWidget::getScrollArea()
|
||||
|
||||
void PostedListWidget::deleteFeedItem(QWidget */*item*/, uint32_t /*type*/)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::deleteFeedItem() Nah";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void PostedListWidget::openChat(const RsPeerId & /*peerId*/)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::openChat() Nah";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -207,8 +213,10 @@ void PostedListWidget::getRankings(int i)
|
||||
if (groupId().isNull())
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::getRankings()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
int oldSortMethod = mSortMethod;
|
||||
|
||||
@ -268,6 +276,7 @@ void PostedListWidget::submitVote(const RsGxsGrpMsgIdPair &msgId, bool up)
|
||||
vote.mVoteType = GXS_VOTE_DOWN;
|
||||
}//if (up)
|
||||
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::submitVote()";
|
||||
std::cerr << std::endl;
|
||||
|
||||
@ -275,6 +284,7 @@ void PostedListWidget::submitVote(const RsGxsGrpMsgIdPair &msgId, bool up)
|
||||
std::cerr << "ThreadId : " << vote.mMeta.mThreadId << std::endl;
|
||||
std::cerr << "ParentId : " << vote.mMeta.mParentId << std::endl;
|
||||
std::cerr << "AuthorId : " << vote.mMeta.mAuthorId << std::endl;
|
||||
#endif
|
||||
|
||||
uint32_t token;
|
||||
rsPosted->createNewVote(token, vote);
|
||||
@ -464,8 +474,10 @@ static bool CmpPINew(const GxsFeedItem *a, const GxsFeedItem *b)
|
||||
void PostedListWidget::applyRanking()
|
||||
{
|
||||
/* uses current settings to sort posts, then add to layout */
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::applyRanking()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
shallowClearPosts();
|
||||
|
||||
@ -474,25 +486,33 @@ void PostedListWidget::applyRanking()
|
||||
{
|
||||
default:
|
||||
case RsPosted::HotRankType:
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::applyRanking() HOT";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
qSort(mPostItems.begin(), mPostItems.end(), CmpPIHot);
|
||||
break;
|
||||
case RsPosted::NewRankType:
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::applyRanking() NEW";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
qSort(mPostItems.begin(), mPostItems.end(), CmpPINew);
|
||||
break;
|
||||
case RsPosted::TopRankType:
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::applyRanking() TOP";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
qSort(mPostItems.begin(), mPostItems.end(), CmpPITop);
|
||||
break;
|
||||
}
|
||||
mLastSortMethod = mSortMethod;
|
||||
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::applyRanking() Sorted mPostList";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* go through list (skipping out-of-date items) to get */
|
||||
QLayout *alayout = ui->scrollAreaWidgetContents->layout();
|
||||
@ -500,42 +520,54 @@ void PostedListWidget::applyRanking()
|
||||
time_t min_ts = 0;
|
||||
foreach (PostedItem *item, mPostItems)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::applyRanking() Item: " << item;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if (item->getPost().mMeta.mPublishTs < min_ts)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "\t Skipping OLD";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
item->hide();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (counter >= mPostIndex + mPostShow)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "\t END - Counter too high";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
item->hide();
|
||||
}
|
||||
else if (counter >= mPostIndex)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "\t Adding to Layout";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
/* add it in! */
|
||||
alayout->addWidget(item);
|
||||
item->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "\t Skipping to Low";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
item->hide();
|
||||
}
|
||||
++counter;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::applyRanking() Loaded New Order";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
// trigger a redraw.
|
||||
ui->scrollAreaWidgetContents->update();
|
||||
@ -564,7 +596,9 @@ bool PostedListWidget::navigatePostItem(const RsGxsMessageId & /*msgId*/)
|
||||
|
||||
void PostedListWidget::shallowClearPosts()
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::shallowClearPosts()" << std::endl;
|
||||
#endif
|
||||
|
||||
std::list<PostedItem *> postedItems;
|
||||
std::list<PostedItem *>::iterator pit;
|
||||
@ -576,24 +610,30 @@ void PostedListWidget::shallowClearPosts()
|
||||
QLayoutItem *litem = alayout->itemAt(i);
|
||||
if (!litem)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::shallowClearPosts() missing litem";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
PostedItem *item = dynamic_cast<PostedItem *>(litem->widget());
|
||||
if (item)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::shallowClearPosts() item: " << item;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
postedItems.push_back(item);
|
||||
}
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
else
|
||||
{
|
||||
std::cerr << "PostedListWidget::shallowClearPosts() Found Child, which is not a PostedItem???";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for(pit = postedItems.begin(); pit != postedItems.end(); ++pit)
|
||||
@ -646,15 +686,19 @@ void PostedListWidget::insertPosts(const uint32_t &token)
|
||||
// modify post content
|
||||
if(mPosts.find(p.mMeta.mMsgId) != mPosts.end())
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::updateCurrentDisplayComplete() updating MsgId: " << p.mMeta.mMsgId;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mPosts[p.mMeta.mMsgId]->setPost(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::updateCurrentDisplayComplete() loading New MsgId: " << p.mMeta.mMsgId;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
/* insert new entry */
|
||||
loadPost(p);
|
||||
}
|
||||
@ -689,8 +733,10 @@ void PostedListWidget::setAllMessagesReadDo(bool read, uint32_t &token)
|
||||
|
||||
void PostedListWidget::loadRequest(const TokenQueue *queue, const TokenRequest &req)
|
||||
{
|
||||
#ifdef DEBUG_POSTED_LIST_WIDGET
|
||||
std::cerr << "PostedListWidget::loadRequest() UserType: " << req.mUserType;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if (queue == mTokenQueue)
|
||||
{
|
||||
|
@ -578,7 +578,7 @@ RetroShareLink RetroShareLink::createCertificate(const RsPeerId& ssl_id)
|
||||
|
||||
return link;
|
||||
}
|
||||
RetroShareLink RetroShareLink::createUnknwonSslCertificate(const RsPeerId& sslId, const RsPgpId& gpgId)
|
||||
RetroShareLink RetroShareLink::createUnknownSslCertificate(const RsPeerId& sslId, const RsPgpId& gpgId)
|
||||
{
|
||||
RetroShareLink link;
|
||||
link.clear();
|
||||
|
@ -90,7 +90,7 @@ class RetroShareLink
|
||||
static RetroShareLink createMessage(const RsPeerId &peerId, const QString& subject);
|
||||
static RetroShareLink createMessage(const RsGxsId &peerId, const QString& subject);
|
||||
static RetroShareLink createCertificate(const RsPeerId &ssl_id) ;
|
||||
static RetroShareLink createUnknwonSslCertificate(const RsPeerId &sslId, const RsPgpId &gpgId = RsPgpId()) ;
|
||||
static RetroShareLink createUnknownSslCertificate(const RsPeerId &sslId, const RsPgpId &gpgId = RsPgpId()) ;
|
||||
static RetroShareLink createExtraFile(const QString& name, uint64_t size, const QString& hash, const QString& ssl_id);
|
||||
static RetroShareLink createPublicMsgInvite(time_t time_stamp,const QString& pgp_id,const QString& hash) ;
|
||||
static RetroShareLink createIdentity(const RsGxsId& gxs_id,const QString& name,const QString& radix_data) ;
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "RSTreeWidgetItem.h"
|
||||
#include "StatusDefs.h"
|
||||
#include "util/misc.h"
|
||||
#include "util/qtthreadsutils.h"
|
||||
#include "vmessagebox.h"
|
||||
#include "util/QtVersion.h"
|
||||
#include "gui/chat/ChatUserNotify.h"
|
||||
@ -176,6 +177,9 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
|
||||
ui->filterLineEdit->setPlaceholderText(tr("Search")) ;
|
||||
ui->filterLineEdit->showFilterIcon();
|
||||
|
||||
mEventHandlerId=0; // forces initialization
|
||||
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId );
|
||||
|
||||
mModel = new RsFriendListModel();
|
||||
mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this);
|
||||
|
||||
@ -236,8 +240,6 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
|
||||
|
||||
connect(NotifyQt::getInstance(), SIGNAL(friendsChanged()) , this, SLOT(forceUpdateDisplay()),Qt::QueuedConnection);
|
||||
connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)) , this, SLOT(forceUpdateDisplay()),Qt::QueuedConnection);
|
||||
connect(NotifyQt::getInstance(), SIGNAL(peerConnected(const QString&)) , this, SLOT(forceUpdateDisplay()),Qt::QueuedConnection);
|
||||
connect(NotifyQt::getInstance(), SIGNAL(peerDisconnected(const QString&)), this, SLOT(forceUpdateDisplay()),Qt::QueuedConnection);
|
||||
|
||||
connect(ui->actionShowOfflineFriends, SIGNAL(triggered(bool)), this, SLOT(setShowUnconnected(bool)));
|
||||
connect(ui->actionShowState, SIGNAL(triggered(bool)), this, SLOT(setShowState(bool)) );
|
||||
@ -254,6 +256,17 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
|
||||
|
||||
}
|
||||
|
||||
void NewFriendList::handleEvent(std::shared_ptr<const RsEvent> e)
|
||||
{
|
||||
if(e->mType == RsEventType::PEER_CONNECTION)
|
||||
{
|
||||
// /!\ The function we're in is called from a different thread. It's very important
|
||||
// to use this trick in order to avoid data races.
|
||||
|
||||
RsQThreadUtils::postToObject( [=]() { forceUpdateDisplay() ; }, this ) ;
|
||||
}
|
||||
}
|
||||
|
||||
NewFriendList::~NewFriendList()
|
||||
{
|
||||
delete ui;
|
||||
|
@ -95,6 +95,7 @@ private slots:
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
void handleEvent(std::shared_ptr<const RsEvent> e);
|
||||
|
||||
private:
|
||||
Ui::NewFriendList *ui;
|
||||
@ -117,6 +118,7 @@ private:
|
||||
|
||||
// Settings for peer list display
|
||||
bool mShowState;
|
||||
RsEventsHandlerId_t mEventHandlerId;
|
||||
|
||||
std::set<RsNodeGroupId> openGroups;
|
||||
std::set<RsPgpId> openPeers;
|
||||
|
@ -28,7 +28,8 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define COLUMN_FEED 0
|
||||
#define COLUMN_FEED 0
|
||||
#define COLUMN_IDENTIFIER 1
|
||||
|
||||
#define SINGLE_STEP 15
|
||||
|
||||
@ -74,6 +75,8 @@ RSFeedWidget::RSFeedWidget(QWidget *parent)
|
||||
ui->treeWidget->installEventFilter(this);
|
||||
|
||||
ui->treeWidget->setVerticalScrollBar(new RSFeedWidgetScrollBar);
|
||||
ui->treeWidget->setColumnCount(2);
|
||||
ui->treeWidget->setColumnHidden(COLUMN_IDENTIFIER,true);
|
||||
}
|
||||
|
||||
RSFeedWidget::~RSFeedWidget()
|
||||
@ -130,17 +133,14 @@ bool RSFeedWidget::eventFilter(QObject *object, QEvent *event)
|
||||
|
||||
void RSFeedWidget::feedAdded(FeedItem *feedItem, QTreeWidgetItem *treeItem)
|
||||
{
|
||||
mItems.insert(feedItem, treeItem);
|
||||
}
|
||||
|
||||
void RSFeedWidget::feedRemoved(FeedItem *feedItem)
|
||||
{
|
||||
mItems.remove(feedItem);
|
||||
}
|
||||
|
||||
void RSFeedWidget::feedsCleared()
|
||||
{
|
||||
mItems.clear();
|
||||
}
|
||||
|
||||
void RSFeedWidget::connectSignals(FeedItem *feedItem)
|
||||
@ -179,6 +179,7 @@ void RSFeedWidget::addFeedItem(FeedItem *feedItem, Qt::ItemDataRole sortRole, co
|
||||
QTreeWidgetItem *treeItem = new RSTreeWidgetItem(mFeedCompareRole);
|
||||
|
||||
treeItem->setData(COLUMN_FEED, sortRole, value);
|
||||
treeItem->setData(COLUMN_IDENTIFIER, Qt::DisplayRole, QString("%1").arg(feedItem->uniqueIdentifier(),8,16,QChar('0')));
|
||||
|
||||
ui->treeWidget->addTopLevelItem(treeItem);
|
||||
ui->treeWidget->setItemWidget(treeItem, 0, feedItem);
|
||||
@ -206,6 +207,7 @@ void RSFeedWidget::addFeedItem(FeedItem *feedItem, const QMap<Qt::ItemDataRole,
|
||||
for (it = sort.begin(); it != sort.end(); ++it) {
|
||||
treeItem->setData(COLUMN_FEED, it.key(), it.value());
|
||||
}
|
||||
treeItem->setData(COLUMN_IDENTIFIER, Qt::DisplayRole, QString("%1").arg(feedItem->uniqueIdentifier(),8,16,QChar('0')));
|
||||
|
||||
ui->treeWidget->addTopLevelItem(treeItem);
|
||||
ui->treeWidget->setItemWidget(treeItem, 0, feedItem);
|
||||
@ -223,14 +225,13 @@ void RSFeedWidget::addFeedItem(FeedItem *feedItem, const QMap<Qt::ItemDataRole,
|
||||
|
||||
void RSFeedWidget::setSort(FeedItem *feedItem, Qt::ItemDataRole sortRole, const QVariant &value)
|
||||
{
|
||||
if (!feedItem) {
|
||||
if (!feedItem)
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
|
||||
if (!treeItem) {
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem->uniqueIdentifier());
|
||||
|
||||
if (!treeItem)
|
||||
return;
|
||||
}
|
||||
|
||||
treeItem->setData(COLUMN_FEED, sortRole, value);
|
||||
}
|
||||
@ -241,10 +242,9 @@ void RSFeedWidget::setSort(FeedItem *feedItem, const QMap<Qt::ItemDataRole, QVar
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
|
||||
if (!treeItem) {
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem->uniqueIdentifier());
|
||||
if (!treeItem)
|
||||
return;
|
||||
}
|
||||
|
||||
QMap<Qt::ItemDataRole, QVariant>::const_iterator it;
|
||||
for (it = sort.begin(); it != sort.end(); ++it) {
|
||||
@ -388,13 +388,23 @@ void RSFeedWidget::removeFeedItem(FeedItem *feedItem)
|
||||
return;
|
||||
}
|
||||
|
||||
disconnectSignals(feedItem);
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem->uniqueIdentifier());
|
||||
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
|
||||
feedRemoved(feedItem);
|
||||
if (treeItem) {
|
||||
delete(treeItem);
|
||||
}
|
||||
if (treeItem)
|
||||
{
|
||||
int treeItem_index = ui->treeWidget->indexOfTopLevelItem(treeItem);
|
||||
|
||||
if(treeItem_index < 0)
|
||||
{
|
||||
std::cerr << "(EE) Cannot remove designated item \"" << feedItem->uniqueIdentifier() << "\": not found!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
feedRemoved(feedItem);
|
||||
disconnectSignals(feedItem);
|
||||
|
||||
delete ui->treeWidget->takeTopLevelItem(treeItem_index);
|
||||
}
|
||||
|
||||
if (!mCountChangedDisabled) {
|
||||
emit feedCountChanged();
|
||||
@ -418,40 +428,42 @@ void RSFeedWidget::feedItemDestroyed(FeedItem *feedItem)
|
||||
{
|
||||
/* No need to disconnect when object will be destroyed */
|
||||
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
|
||||
feedRemoved(feedItem);
|
||||
if (treeItem) {
|
||||
delete(treeItem);
|
||||
}
|
||||
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem->uniqueIdentifier());
|
||||
|
||||
if (!mCountChangedDisabled) {
|
||||
feedRemoved(feedItem);
|
||||
if (treeItem)
|
||||
delete(treeItem);
|
||||
|
||||
if (!mCountChangedDisabled)
|
||||
emit feedCountChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QTreeWidgetItem *RSFeedWidget::findTreeWidgetItem(FeedItem *feedItem)
|
||||
QTreeWidgetItem *RSFeedWidget::findTreeWidgetItem(uint64_t identifier)
|
||||
{
|
||||
QMap<FeedItem*, QTreeWidgetItem*>::iterator it = mItems.find(feedItem);
|
||||
if (it == mItems.end()) {
|
||||
return NULL;
|
||||
}
|
||||
QList<QTreeWidgetItem*> list = ui->treeWidget->findItems(QString("%1").arg(identifier,8,16,QChar('0')),Qt::MatchExactly,COLUMN_IDENTIFIER);
|
||||
|
||||
return it.value();
|
||||
if(list.empty())
|
||||
return nullptr;
|
||||
else if(list.size() == 1)
|
||||
return list.front();
|
||||
else
|
||||
{
|
||||
std::cerr << "(EE) More than a single item with identifier \"" << identifier << "\" in the feed tree widget. This shouldn't happen!" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool RSFeedWidget::scrollTo(FeedItem *feedItem, bool focus)
|
||||
{
|
||||
QTreeWidgetItem *item = findTreeWidgetItem(feedItem);
|
||||
if (!feedItem) {
|
||||
QTreeWidgetItem *item = findTreeWidgetItem(feedItem->uniqueIdentifier());
|
||||
if (!feedItem)
|
||||
return false;
|
||||
}
|
||||
|
||||
ui->treeWidget->scrollToItem(item);
|
||||
ui->treeWidget->setCurrentItem(item);
|
||||
|
||||
if (focus) {
|
||||
if (focus)
|
||||
ui->treeWidget->setFocus();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -476,25 +488,24 @@ void RSFeedWidget::withAll(RSFeedWidgetCallbackFunction callback, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
FeedItem *RSFeedWidget::findFeedItem(RSFeedWidgetFindCallbackFunction callback, void *data)
|
||||
FeedItem *RSFeedWidget::findFeedItem(uint64_t identifier)
|
||||
{
|
||||
if (!callback) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QTreeWidgetItemIterator it(ui->treeWidget);
|
||||
QTreeWidgetItem *treeItem;
|
||||
QTreeWidgetItem *treeItem=NULL;
|
||||
|
||||
// this search could probably be automatised by giving the tree items the identifier as data for some specific role, then calling QTreeWidget::findItems()
|
||||
#warning TODO
|
||||
while ((treeItem = *it) != NULL) {
|
||||
++it;
|
||||
|
||||
FeedItem *feedItem = feedItemFromTreeItem(treeItem);
|
||||
if (!feedItem) {
|
||||
if (!feedItem)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (callback(feedItem, data)) {
|
||||
uint64_t id = feedItem->uniqueIdentifier();
|
||||
|
||||
if (id == identifier)
|
||||
return feedItem;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
bool scrollTo(FeedItem *feedItem, bool focus);
|
||||
|
||||
void withAll(RSFeedWidgetCallbackFunction callback, void *data);
|
||||
FeedItem *findFeedItem(RSFeedWidgetFindCallbackFunction callback, void *data);
|
||||
FeedItem *findFeedItem(uint64_t identifier);
|
||||
|
||||
void selectedFeedItems(QList<FeedItem*> &feedItems);
|
||||
|
||||
@ -98,7 +98,7 @@ private:
|
||||
void connectSignals(FeedItem *feedItem);
|
||||
void disconnectSignals(FeedItem *feedItem);
|
||||
FeedItem *feedItemFromTreeItem(QTreeWidgetItem *treeItem);
|
||||
QTreeWidgetItem *findTreeWidgetItem(FeedItem *feedItem);
|
||||
QTreeWidgetItem *findTreeWidgetItem(uint64_t identifier);
|
||||
void filterItems();
|
||||
void filterItem(QTreeWidgetItem *treeItem, FeedItem *feedItem);
|
||||
|
||||
@ -117,9 +117,6 @@ private:
|
||||
/* Options */
|
||||
int mCountChangedDisabled;
|
||||
|
||||
/* Items */
|
||||
QMap<FeedItem*, QTreeWidgetItem*> mItems;
|
||||
|
||||
Ui::RSFeedWidget *ui;
|
||||
};
|
||||
|
||||
|
@ -337,24 +337,49 @@ void ConnectFriendWizard::setCertificate(const QString &certificate, bool friend
|
||||
|
||||
void ConnectFriendWizard::setGpgId(const RsPgpId &gpgId, const RsPeerId &sslId, bool friendRequest)
|
||||
{
|
||||
if (!rsPeers->getGPGDetails(gpgId, peerDetails)) {
|
||||
setField("errorMessage", tr("Cannot get peer details of PGP key %1").arg(QString::fromStdString(gpgId.toStdString())));
|
||||
if(sslId == rsPeers->getOwnId())
|
||||
{
|
||||
setField("errorMessage", tr("This is your own certificate! You would not want to make friend with yourself. Wouldn't you?") ) ;
|
||||
setStartId(Page_ErrorMessage);
|
||||
return;
|
||||
error = false;
|
||||
}
|
||||
|
||||
/* Set ssl id when available */
|
||||
peerDetails.id = sslId;
|
||||
if (!rsPeers->getGPGDetails(gpgId, peerDetails))
|
||||
{
|
||||
mIsShortInvite = true;
|
||||
|
||||
//setStartId(friendRequest ? Page_FriendRequest : Page_Conclusion);
|
||||
setStartId(Page_Conclusion);
|
||||
if (friendRequest){
|
||||
ui->cp_Label->show();
|
||||
ui->requestinfolabel->show();
|
||||
setTitleText(ui->ConclusionPage,tr("Friend request"));
|
||||
ui->ConclusionPage->setSubTitle(tr("Details about the request"));
|
||||
setButtonText(QWizard::FinishButton , tr("Accept"));
|
||||
}
|
||||
peerDetails.id = sslId;
|
||||
peerDetails.gpg_id = gpgId;
|
||||
peerDetails.skip_pgp_signature_validation = true;
|
||||
|
||||
mCertificate.clear();
|
||||
|
||||
setStartId(Page_Conclusion);
|
||||
|
||||
if (friendRequest){
|
||||
ui->cp_Label->show();
|
||||
ui->requestinfolabel->show();
|
||||
setTitleText(ui->ConclusionPage, tr("Friend request"));
|
||||
ui->ConclusionPage->setSubTitle(tr("Details about the request"));
|
||||
setButtonText(QWizard::FinishButton , tr("Accept"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set ssl id when available */
|
||||
peerDetails.id = sslId;
|
||||
mIsShortInvite = false;
|
||||
|
||||
//setStartId(friendRequest ? Page_FriendRequest : Page_Conclusion);
|
||||
setStartId(Page_Conclusion);
|
||||
if (friendRequest){
|
||||
ui->cp_Label->show();
|
||||
ui->requestinfolabel->show();
|
||||
setTitleText(ui->ConclusionPage,tr("Friend request"));
|
||||
ui->ConclusionPage->setSubTitle(tr("Details about the request"));
|
||||
setButtonText(QWizard::FinishButton , tr("Accept"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConnectFriendWizard::~ConnectFriendWizard()
|
||||
@ -507,7 +532,7 @@ void ConnectFriendWizard::initializePage(int id)
|
||||
ui->cp_Label->setText(tr("You have a friend request from") + " " + QString::fromUtf8(peerDetails.name.c_str()));
|
||||
ui->nameEdit->setText(QString::fromUtf8(peerDetails.name.c_str()));
|
||||
ui->trustEdit->setText(trustString);
|
||||
ui->emailEdit->setText(QString::fromUtf8(peerDetails.email.c_str()));
|
||||
ui->profileIdEdit->setText(QString::fromStdString(peerDetails.gpg_id.toStdString()));
|
||||
QString loc = QString::fromUtf8(peerDetails.location.c_str());
|
||||
if (!loc.isEmpty())
|
||||
{
|
||||
@ -540,12 +565,19 @@ void ConnectFriendWizard::initializePage(int id)
|
||||
ui->ipLabel->setPixmap(QPixmap(":/images/anonymous_128_blue.png").scaledToHeight(S*2,Qt::SmoothTransformation));
|
||||
ui->ipLabel->setToolTip("This is a Hidden node - you need tor/i2p proxy to connect");
|
||||
}
|
||||
|
||||
if(peerDetails.email.empty())
|
||||
if(mIsShortInvite)
|
||||
{
|
||||
ui->emailLabel->hide(); // is it ever used?
|
||||
ui->emailEdit->hide();
|
||||
ui->nameEdit->setText(tr("[Unknown]"));
|
||||
ui->addKeyToKeyring_CB->setChecked(false);
|
||||
ui->addKeyToKeyring_CB->setEnabled(false);
|
||||
ui->signersEdit->hide();
|
||||
ui->signersLabel->hide();
|
||||
ui->signGPGCheckBox->setChecked(false);
|
||||
ui->signGPGCheckBox->setEnabled(false);
|
||||
ui->acceptNoSignGPGCheckBox->setChecked(true);
|
||||
ui->acceptNoSignGPGCheckBox->setEnabled(false);
|
||||
}
|
||||
|
||||
ui->ipEdit->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>437</height>
|
||||
<width>1139</width>
|
||||
<height>1171</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -480,14 +480,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="emailLabel">
|
||||
<widget class="QLabel" name="profileIdLabel">
|
||||
<property name="text">
|
||||
<string>Email:</string>
|
||||
<string>Profile ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="emailEdit">
|
||||
<widget class="QLabel" name="profileIdEdit">
|
||||
<property name="text">
|
||||
<string notr="true">Email</string>
|
||||
</property>
|
||||
@ -794,8 +794,8 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
|
||||
void updateItemStatic();
|
||||
|
||||
virtual uint64_t uniqueIdentifier() const override { return hash_64bits("ChatMsgItem " + mPeerId.toStdString()); }
|
||||
protected:
|
||||
/* FeedItem */
|
||||
virtual void doExpand(bool /*open*/) {}
|
||||
|
@ -18,10 +18,11 @@
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include "FeedItem.h"
|
||||
|
||||
/** Constructor */
|
||||
FeedItem::FeedItem(QWidget *parent) : QWidget(parent)
|
||||
FeedItem::FeedItem(QWidget *parent) : QWidget(parent), mHash(0)
|
||||
{
|
||||
mWasExpanded = false;
|
||||
}
|
||||
@ -43,3 +44,16 @@ void FeedItem::expand(bool open)
|
||||
mWasExpanded = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t FeedItem::hash_64bits(const std::string& s) const
|
||||
{
|
||||
if(mHash == 0)
|
||||
{
|
||||
mHash = 0x01110bbfa09;
|
||||
|
||||
for(uint32_t i=0;i<s.size();++i)
|
||||
mHash = ~(((mHash << 31) ^ (mHash >> 3)) + s[i]*0x217898fbba7 + 0x0294379);
|
||||
}
|
||||
|
||||
return mHash;
|
||||
}
|
||||
|
@ -36,16 +36,24 @@ public:
|
||||
bool wasExpanded() { return mWasExpanded; }
|
||||
void expand(bool open);
|
||||
|
||||
/*!
|
||||
* \brief uniqueIdentifier
|
||||
* \return returns a string that is unique to this specific item. The string will be used to search for an existing item that
|
||||
* would contain the same information. It should therefore sumarise the data represented by the item.
|
||||
*/
|
||||
virtual uint64_t uniqueIdentifier() const =0;
|
||||
protected:
|
||||
virtual void doExpand(bool open) = 0;
|
||||
virtual void expandFill(bool /*first*/) {}
|
||||
|
||||
uint64_t hash_64bits(const std::string& s) const;
|
||||
signals:
|
||||
void sizeChanged(FeedItem *feedItem);
|
||||
void feedItemDestroyed(FeedItem *feedItem);
|
||||
|
||||
private:
|
||||
bool mWasExpanded;
|
||||
mutable uint64_t mHash;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
~GxsChannelGroupItem();
|
||||
|
||||
bool setGroup(const RsGxsChannelGroup &group);
|
||||
|
||||
uint64_t uniqueIdentifier() const override { return hash_64bits("GxsChannelGroupItem " + groupId().toStdString()) ; }
|
||||
protected:
|
||||
/* FeedItem */
|
||||
virtual void doExpand(bool open);
|
||||
|
@ -71,6 +71,7 @@ void GxsChannelPostItem::init(const RsGxsMessageId& messageId,const std::set<RsG
|
||||
|
||||
setup();
|
||||
|
||||
mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded
|
||||
mLoaded = false ;
|
||||
}
|
||||
|
||||
@ -183,6 +184,7 @@ void GxsChannelPostItem::setup()
|
||||
|
||||
connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(download()));
|
||||
// HACK FOR NOW.
|
||||
ui->commentButton->hide();// hidden until properly enabled.
|
||||
connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments()));
|
||||
|
||||
connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void)));
|
||||
|
@ -53,6 +53,8 @@ public:
|
||||
//GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, bool isHome, bool autoUpdate);
|
||||
virtual ~GxsChannelPostItem();
|
||||
|
||||
uint64_t uniqueIdentifier() const override { hash_64bits("GxsChannelPostItem " + mPost.mMeta.mMsgId.toStdString()) ; }
|
||||
|
||||
bool setGroup(const RsGxsChannelGroup &group, bool doFill = true);
|
||||
bool setPost(const RsGxsChannelPost &post, bool doFill = true);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1140</width>
|
||||
<width>1359</width>
|
||||
<height>342</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -57,18 +57,6 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>82</width>
|
||||
<height>108</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>156</width>
|
||||
<height>107</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@ -138,12 +126,6 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Short Description</string>
|
||||
</property>
|
||||
@ -570,8 +552,8 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -91,12 +91,18 @@ void GxsCircleItem::setup()
|
||||
ui->iconLabel->setPixmap(pixmap);
|
||||
ui->gxsIdLabel->setId(mGxsId);
|
||||
|
||||
|
||||
|
||||
ui->acceptButton->setToolTip(tr("Grant membership request"));
|
||||
ui->revokeButton->setToolTip(tr("Revoke membership request"));
|
||||
connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(grantCircleMembership()));
|
||||
connect(ui->revokeButton, SIGNAL(clicked()), this, SLOT(revokeCircleMembership()));
|
||||
if(circleDetails.mAmIAdmin)
|
||||
{
|
||||
ui->acceptButton->setToolTip(tr("Grant membership request"));
|
||||
ui->revokeButton->setToolTip(tr("Revoke membership request"));
|
||||
connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(grantCircleMembership()));
|
||||
connect(ui->revokeButton, SIGNAL(clicked()), this, SLOT(revokeCircleMembership()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->acceptButton->setEnabled(false);
|
||||
ui->revokeButton->setEnabled(false);
|
||||
}
|
||||
}
|
||||
else if (mType == RS_FEED_ITEM_CIRCLE_INVIT_REC)
|
||||
{
|
||||
@ -110,7 +116,43 @@ void GxsCircleItem::setup()
|
||||
connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(acceptCircleSubscription()));
|
||||
ui->revokeButton->setHidden(true);
|
||||
}
|
||||
else if (mType == RS_FEED_ITEM_CIRCLE_MEMB_LEAVE)
|
||||
{
|
||||
ui->titleLabel->setText(idName + tr(" has left this circle you belong to."));
|
||||
ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str()));
|
||||
ui->gxsIdLabel->setText(idName);
|
||||
ui->iconLabel->setPixmap(pixmap);
|
||||
ui->gxsIdLabel->setId(mGxsId);
|
||||
|
||||
ui->acceptButton->setHidden(true);
|
||||
ui->revokeButton->setHidden(true);
|
||||
}
|
||||
else if (mType == RS_FEED_ITEM_CIRCLE_MEMB_JOIN)
|
||||
{
|
||||
ui->titleLabel->setText(idName + tr(" has join this circle you also belong to."));
|
||||
ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str()));
|
||||
ui->gxsIdLabel->setText(idName);
|
||||
ui->iconLabel->setPixmap(pixmap);
|
||||
ui->gxsIdLabel->setId(mGxsId);
|
||||
|
||||
ui->acceptButton->setHidden(true);
|
||||
ui->revokeButton->setHidden(true);
|
||||
}
|
||||
else if (mType == RS_FEED_ITEM_CIRCLE_MEMB_REVOQUED)
|
||||
{
|
||||
if(rsIdentity->isOwnId(mGxsId))
|
||||
ui->titleLabel->setText(tr("Your identity %1 has been revoqued from this circle.").arg(idName));
|
||||
else
|
||||
ui->titleLabel->setText(tr("Identity %1 has been revoqued from this circle you belong to.").arg(idName));
|
||||
|
||||
ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str()));
|
||||
ui->gxsIdLabel->setText(idName);
|
||||
ui->iconLabel->setPixmap(pixmap);
|
||||
ui->gxsIdLabel->setId(mGxsId);
|
||||
|
||||
ui->acceptButton->setHidden(true);
|
||||
ui->revokeButton->setHidden(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -125,14 +167,9 @@ void GxsCircleItem::setup()
|
||||
|
||||
}
|
||||
|
||||
bool GxsCircleItem::isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type)
|
||||
uint64_t GxsCircleItem::uniqueIdentifier() const
|
||||
{
|
||||
if ((mCircleId == circleId) && (mGxsId == gxsId) && (mType == type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return hash_64bits("GxsCircle " + mCircleId.toStdString() + " " + mGxsId.toStdString() + " " + QString::number(mType).toStdString());
|
||||
}
|
||||
|
||||
void GxsCircleItem::removeItem()
|
||||
|
@ -52,8 +52,7 @@ public:
|
||||
GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type);
|
||||
virtual ~GxsCircleItem();
|
||||
|
||||
bool isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type);
|
||||
|
||||
uint64_t uniqueIdentifier() const override;
|
||||
void loadRequest(const TokenQueue *queue, const TokenRequest &req);
|
||||
|
||||
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
|
||||
bool setGroup(const RsGxsForumGroup &group);
|
||||
|
||||
uint64_t uniqueIdentifier() const override { return hash_64bits("GxsForumGroupItem " + groupId().toStdString()) ; }
|
||||
protected:
|
||||
/* FeedItem */
|
||||
virtual void doExpand(bool open);
|
||||
|
@ -43,6 +43,8 @@
|
||||
GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate) :
|
||||
GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsForums, autoUpdate)
|
||||
{
|
||||
mMessage.mMeta.mMsgId = messageId; // useful for uniqueIdentifier() before the post is actually loaded
|
||||
mMessage.mMeta.mGroupId = groupId;
|
||||
setup();
|
||||
|
||||
requestGroup();
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
bool setGroup(const RsGxsForumGroup &group, bool doFill = true);
|
||||
bool setMessage(const RsGxsForumMsg &msg, bool doFill = true);
|
||||
|
||||
uint64_t uniqueIdentifier() const override { return hash_64bits("GxsForumMsgItem " + mMessage.mMeta.mMsgId.toStdString()) ; }
|
||||
protected:
|
||||
/* FeedItem */
|
||||
virtual void doExpand(bool open);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user