mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 16:39:29 -05:00
commit
fffc516b72
@ -1 +1 @@
|
|||||||
Subproject commit c064abd74b27e1cc440917e9dbac800316bb8470
|
Subproject commit 879d5dfe8dcd8995be753120cf1b8bab4dd2ec82
|
@ -136,7 +136,13 @@ void HashStorage::threadTick()
|
|||||||
stopHashThread();
|
stopHashThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_FINISH, "") ;
|
if(rsEvents)
|
||||||
|
{
|
||||||
|
auto ev = std::make_shared<RsSharedDirectoriesEvent>();
|
||||||
|
ev->mEventCode = RsSharedDirectoriesEventCode::DIRECTORY_SWEEP_ENDED;
|
||||||
|
rsEvents->postEvent(ev);
|
||||||
|
}
|
||||||
|
//RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_FINISH, "") ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -181,7 +187,14 @@ void HashStorage::threadTick()
|
|||||||
else
|
else
|
||||||
rs_sprintf(tmpout, "%lu/%lu (%s - %d%%) : %s", (unsigned long int)mHashCounter+1, (unsigned long int)mTotalFilesToHash, friendlyUnit(mTotalHashedSize).c_str(), int(mTotalHashedSize/double(mTotalSizeToHash)*100.0), job.full_path.c_str()) ;
|
rs_sprintf(tmpout, "%lu/%lu (%s - %d%%) : %s", (unsigned long int)mHashCounter+1, (unsigned long int)mTotalFilesToHash, friendlyUnit(mTotalHashedSize).c_str(), int(mTotalHashedSize/double(mTotalSizeToHash)*100.0), job.full_path.c_str()) ;
|
||||||
|
|
||||||
RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_HASH_FILE, tmpout) ;
|
//RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_HASH_FILE, tmpout) ;
|
||||||
|
if(rsEvents)
|
||||||
|
{
|
||||||
|
auto ev = std::make_shared<RsSharedDirectoriesEvent>();
|
||||||
|
ev->mEventCode = RsSharedDirectoriesEventCode::HASHING_FILE;
|
||||||
|
ev->mMessage = tmpout;
|
||||||
|
rsEvents->postEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
double seconds_origin = rstime::RsScopeTimer::currentTime() ;
|
double seconds_origin = rstime::RsScopeTimer::currentTime() ;
|
||||||
|
|
||||||
|
@ -816,10 +816,13 @@ bool ftController::completeFile(const RsFileHash& hash)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Notify GUI */
|
/* Notify GUI */
|
||||||
RsServer::notify()->AddPopupMessage(RS_POPUP_DOWNLOAD, hash.toStdString(), name, "");
|
if(rsEvents)
|
||||||
|
{
|
||||||
RsServer::notify()->notifyDownloadComplete(hash.toStdString());
|
auto ev = std::make_shared<RsFileTransferEvent>();
|
||||||
RsServer::notify()->notifyDownloadCompleteCount(completeCount);
|
ev->mHash = hash;
|
||||||
|
ev->mFileTransferEventCode = RsFileTransferEventCode::DOWNLOAD_COMPLETE;
|
||||||
|
rsEvents->postEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
rsFiles->ForceDirectoryCheck(true) ;
|
rsFiles->ForceDirectoryCheck(true) ;
|
||||||
|
|
||||||
@ -1412,7 +1415,12 @@ bool ftController::FileClearCompleted()
|
|||||||
IndicateConfigChanged();
|
IndicateConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
RsServer::notify()->notifyDownloadCompleteCount(0);
|
if(rsEvents)
|
||||||
|
{
|
||||||
|
auto ev = std::make_shared<RsFileTransferEvent>();
|
||||||
|
ev->mFileTransferEventCode = RsFileTransferEventCode::COMPLETED_FILES_REMOVED;
|
||||||
|
rsEvents->postEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||||
*
|
*
|
||||||
* SPDX-FileCopyrightText: 2004-2019 RetroShare Team <contact@retroshare.cc>
|
* SPDX-FileCopyrightText: 2004-2020 RetroShare Team <contact@retroshare.cc>
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -73,6 +73,8 @@ JsonApiServer::corsOptionsHeaders =
|
|||||||
{ "Content-Length", "0" }
|
{ "Content-Length", "0" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* static */ const RsJsonApiErrorCategory RsJsonApiErrorCategory::instance;
|
||||||
|
|
||||||
#define INITIALIZE_API_CALL_JSON_CONTEXT \
|
#define INITIALIZE_API_CALL_JSON_CONTEXT \
|
||||||
RsGenericSerializer::SerializeContext cReq( \
|
RsGenericSerializer::SerializeContext cReq( \
|
||||||
nullptr, 0, \
|
nullptr, 0, \
|
||||||
@ -124,32 +126,45 @@ JsonApiServer::corsOptionsHeaders =
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JsonApiServer::unProtectedRestart()
|
||||||
|
{
|
||||||
|
/* Extremely sensitive stuff!
|
||||||
|
* Make sure you read documentation in header before changing or use!! */
|
||||||
|
|
||||||
|
fullstop();
|
||||||
|
RsThread::start("JSON API Server");
|
||||||
|
}
|
||||||
|
|
||||||
bool RsJsonApi::parseToken(
|
bool RsJsonApi::parseToken(
|
||||||
const std::string& clear_token, std::string& user,std::string& passwd )
|
const std::string& clear_token, std::string& user,std::string& passwd )
|
||||||
{
|
{
|
||||||
uint32_t colonIndex = 0;
|
auto colonIndex = std::string::npos;
|
||||||
uint32_t colonCounter = 0;
|
|
||||||
const auto tkLen = clear_token.length();
|
const auto tkLen = clear_token.length();
|
||||||
|
|
||||||
for(uint32_t i=0; i < tkLen && colonCounter < 2; ++i)
|
for(uint32_t i=0; i < tkLen; ++i)
|
||||||
if(clear_token[i] == ':') { ++colonCounter; colonIndex = i; }
|
if(clear_token[i] == ':') { colonIndex = i; break; }
|
||||||
else if(!librs::util::is_alphanumeric(clear_token[i])) return false;
|
|
||||||
|
|
||||||
if(colonCounter != 1) return false;
|
user = clear_token.substr(0, colonIndex);
|
||||||
|
|
||||||
user = clear_token.substr(0, colonIndex);
|
if(colonIndex < tkLen)
|
||||||
passwd = clear_token.substr(colonIndex + 1);
|
passwd = clear_token.substr(colonIndex + 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
||||||
mService(std::make_shared<restbed::Service>()),
|
mService(nullptr),
|
||||||
mServiceMutex("JsonApiServer restbed ptr"),
|
|
||||||
mListeningPort(RsJsonApi::DEFAULT_PORT),
|
mListeningPort(RsJsonApi::DEFAULT_PORT),
|
||||||
mBindingAddress(RsJsonApi::DEFAULT_BINDING_ADDRESS)
|
mBindingAddress(RsJsonApi::DEFAULT_BINDING_ADDRESS),
|
||||||
|
mRestartReqTS(0)
|
||||||
{
|
{
|
||||||
|
#if defined(RS_THREAD_FORCE_STOP) && defined(RS_JSONAPI_DEBUG_SERVICE_STOP)
|
||||||
|
/* When called in bursts it seems that Restbed::Service::stop() doesn't
|
||||||
|
* always does the job, to debug those cases it has been useful to ask
|
||||||
|
* RsThread to force it to stop for us. */
|
||||||
|
RsThread::setStopTimeout(10);
|
||||||
|
#endif
|
||||||
|
|
||||||
registerHandler("/rsLoginHelper/createLocation",
|
registerHandler("/rsLoginHelper/createLocation",
|
||||||
[this](const std::shared_ptr<rb::Session> session)
|
[this](const std::shared_ptr<rb::Session> session)
|
||||||
{
|
{
|
||||||
@ -248,7 +263,13 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
|||||||
{
|
{
|
||||||
INITIALIZE_API_CALL_JSON_CONTEXT;
|
INITIALIZE_API_CALL_JSON_CONTEXT;
|
||||||
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
||||||
rsControl->rsGlobalShutDown();
|
|
||||||
|
/* Wrap inside RsThread::async because this call
|
||||||
|
* RsThread::fullstop() also on JSON API server thread.
|
||||||
|
* Calling RsThread::fullstop() from it's own thread should never
|
||||||
|
* happen and if it happens an error message is printed
|
||||||
|
* accordingly by RsThread::fullstop() */
|
||||||
|
RsThread::async([](){ rsControl->rsGlobalShutDown(); });
|
||||||
} );
|
} );
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
@ -388,6 +409,41 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
|
|||||||
session->yield(message.str());
|
session->yield(message.str());
|
||||||
} );
|
} );
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
registerHandler("/rsJsonApi/restart",
|
||||||
|
[this](const std::shared_ptr<rb::Session> session)
|
||||||
|
{
|
||||||
|
auto reqSize = session->get_request()->get_header("Content-Length", 0);
|
||||||
|
session->fetch( static_cast<size_t>(reqSize), [this](
|
||||||
|
const std::shared_ptr<rb::Session> session,
|
||||||
|
const rb::Bytes& body )
|
||||||
|
{
|
||||||
|
INITIALIZE_API_CALL_JSON_CONTEXT;
|
||||||
|
|
||||||
|
std::error_condition retval;
|
||||||
|
|
||||||
|
const auto now = time(nullptr);
|
||||||
|
if(mRestartReqTS.exchange(now) + RESTART_BURST_PROTECTION > now)
|
||||||
|
retval = RsJsonApiErrorNum::NOT_A_MACHINE_GUN;
|
||||||
|
|
||||||
|
// serialize out parameters and return value to JSON
|
||||||
|
{
|
||||||
|
RsGenericSerializer::SerializeContext& ctx(cAns);
|
||||||
|
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
|
||||||
|
RS_SERIAL_PROCESS(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
||||||
|
|
||||||
|
/* Wrap inside RsThread::async because this call fullstop() on
|
||||||
|
* JSON API server thread.
|
||||||
|
* Calling RsThread::fullstop() from it's own thread should never
|
||||||
|
* happen and if it happens an error message is printed
|
||||||
|
* accordingly by RsThread::fullstop() */
|
||||||
|
if(!retval) RsThread::async([this](){ unProtectedRestart(); });
|
||||||
|
} );
|
||||||
|
}, true);
|
||||||
|
|
||||||
// Generated at compile time
|
// Generated at compile time
|
||||||
#include "jsonapi-wrappers.inl"
|
#include "jsonapi-wrappers.inl"
|
||||||
}
|
}
|
||||||
@ -405,10 +461,22 @@ void JsonApiServer::registerHandler(
|
|||||||
|
|
||||||
if(requiresAutentication)
|
if(requiresAutentication)
|
||||||
resource->set_authentication_handler(
|
resource->set_authentication_handler(
|
||||||
[this](
|
[this, path](
|
||||||
const std::shared_ptr<rb::Session> session,
|
const std::shared_ptr<rb::Session> session,
|
||||||
const std::function<void (const std::shared_ptr<rb::Session>)>& callback )
|
const std::function<void (const std::shared_ptr<rb::Session>)>& callback )
|
||||||
{
|
{
|
||||||
|
const auto authFail =
|
||||||
|
[&path, &session](int status) -> RsWarn::stream_type&
|
||||||
|
{
|
||||||
|
/* Capture session by reference as it is cheaper then copying
|
||||||
|
* shared_ptr by value which is not needed in this case */
|
||||||
|
|
||||||
|
session->close(status, corsOptionsHeaders);
|
||||||
|
return RsWarn() << "JsonApiServer authentication handler "
|
||||||
|
"blocked an attempt to call JSON API "
|
||||||
|
"authenticated method: " << path;
|
||||||
|
};
|
||||||
|
|
||||||
if(session->get_request()->get_method() == "OPTIONS")
|
if(session->get_request()->get_method() == "OPTIONS")
|
||||||
{
|
{
|
||||||
callback(session);
|
callback(session);
|
||||||
@ -417,7 +485,8 @@ void JsonApiServer::registerHandler(
|
|||||||
|
|
||||||
if(!rsLoginHelper->isLoggedIn())
|
if(!rsLoginHelper->isLoggedIn())
|
||||||
{
|
{
|
||||||
session->close(rb::CONFLICT, corsOptionsHeaders);
|
authFail(rb::CONFLICT) << " before RetroShare login"
|
||||||
|
<< std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,15 +498,24 @@ void JsonApiServer::registerHandler(
|
|||||||
|
|
||||||
if(authToken != "Basic")
|
if(authToken != "Basic")
|
||||||
{
|
{
|
||||||
session->close(rb::UNAUTHORIZED, corsOptionsHeaders);
|
authFail(rb::UNAUTHORIZED)
|
||||||
|
<< " with wrong Authorization header: "
|
||||||
|
<< authHeader.str() << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::getline(authHeader, authToken, ' ');
|
std::getline(authHeader, authToken, ' ');
|
||||||
authToken = decodeToken(authToken);
|
authToken = decodeToken(authToken);
|
||||||
|
|
||||||
if(isAuthTokenValid(authToken)) callback(session);
|
std::error_condition ec;
|
||||||
else session->close(rb::UNAUTHORIZED, corsOptionsHeaders);
|
if(isAuthTokenValid(authToken, ec)) callback(session);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string tUser;
|
||||||
|
parseToken(authToken, tUser, RS_DEFAULT_STORAGE_PARAM(std::string));
|
||||||
|
authFail(rb::UNAUTHORIZED)
|
||||||
|
<< " user: " << tUser << ec << std::endl;
|
||||||
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
mResources.push_back(resource);
|
mResources.push_back(resource);
|
||||||
@ -447,24 +525,62 @@ void JsonApiServer::setNewAccessRequestCallback(
|
|||||||
const std::function<bool (const std::string&, const std::string&)>& callback )
|
const std::function<bool (const std::string&, const std::string&)>& callback )
|
||||||
{ mNewAccessRequestCallback = callback; }
|
{ mNewAccessRequestCallback = callback; }
|
||||||
|
|
||||||
bool JsonApiServer::requestNewTokenAutorization(
|
/*static*/ std::error_condition JsonApiServer::badApiCredientalsFormat(
|
||||||
const std::string& user, const std::string& passwd )
|
const std::string& user, const std::string& passwd )
|
||||||
{
|
{
|
||||||
if(rsLoginHelper->isLoggedIn() && mNewAccessRequestCallback(user, passwd))
|
if(user.find(':') < std::string::npos)
|
||||||
return authorizeUser(user, passwd);
|
return RsJsonApiErrorNum::API_USER_CONTAIN_COLON;
|
||||||
|
|
||||||
return false;
|
if(user.empty())
|
||||||
|
RsWarn() << __PRETTY_FUNCTION__ << " User is empty, are you sure "
|
||||||
|
<< "this what you wanted?" << std::endl;
|
||||||
|
|
||||||
|
if(passwd.empty())
|
||||||
|
RsWarn() << __PRETTY_FUNCTION__ << " Password is empty, are you sure "
|
||||||
|
<< "this what you wanted?" << std::endl;
|
||||||
|
|
||||||
|
return std::error_condition();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonApiServer::isAuthTokenValid(const std::string& token)
|
std::error_condition JsonApiServer::requestNewTokenAutorization(
|
||||||
|
const std::string& user, const std::string& passwd )
|
||||||
|
{
|
||||||
|
auto ec = badApiCredientalsFormat(user, passwd);
|
||||||
|
if(ec) return ec;
|
||||||
|
|
||||||
|
if(!rsLoginHelper->isLoggedIn())
|
||||||
|
return RsJsonApiErrorNum::CANNOT_EXECUTE_BEFORE_RS_LOGIN;
|
||||||
|
|
||||||
|
if(mNewAccessRequestCallback(user, passwd))
|
||||||
|
return authorizeUser(user, passwd);
|
||||||
|
|
||||||
|
return RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonApiServer::isAuthTokenValid(
|
||||||
|
const std::string& token, std::error_condition& error )
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(configMutex);
|
RS_STACK_MUTEX(configMutex);
|
||||||
|
|
||||||
|
const auto failure = [&error](RsJsonApiErrorNum e) -> bool
|
||||||
|
{
|
||||||
|
error = e;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto success = [&error]()
|
||||||
|
{
|
||||||
|
error.clear();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
std::string user,passwd;
|
std::string user,passwd;
|
||||||
if(!parseToken(token,user,passwd)) return false;
|
if(!parseToken(token, user, passwd))
|
||||||
|
return failure(RsJsonApiErrorNum::TOKEN_FORMAT_INVALID);
|
||||||
|
|
||||||
auto it = mAuthTokenStorage.mAuthorizedTokens.find(user);
|
auto it = mAuthTokenStorage.mAuthorizedTokens.find(user);
|
||||||
if(it == mAuthTokenStorage.mAuthorizedTokens.end()) return false;
|
if(it == mAuthTokenStorage.mAuthorizedTokens.end())
|
||||||
|
return failure(RsJsonApiErrorNum::UNKNOWN_API_USER);
|
||||||
|
|
||||||
// attempt avoiding +else CRYPTO_memcmp+ being optimized away
|
// attempt avoiding +else CRYPTO_memcmp+ being optimized away
|
||||||
int noOptimiz = 1;
|
int noOptimiz = 1;
|
||||||
@ -476,12 +592,16 @@ bool JsonApiServer::isAuthTokenValid(const std::string& token)
|
|||||||
if( passwd.size() == it->second.size() &&
|
if( passwd.size() == it->second.size() &&
|
||||||
( noOptimiz = CRYPTO_memcmp(
|
( noOptimiz = CRYPTO_memcmp(
|
||||||
passwd.data(), it->second.data(), it->second.size() ) ) == 0 )
|
passwd.data(), it->second.data(), it->second.size() ) ) == 0 )
|
||||||
return true;
|
return success();
|
||||||
// Make token size guessing harder
|
// Make token size guessing harder
|
||||||
else noOptimiz = CRYPTO_memcmp(passwd.data(), passwd.data(), passwd.size());
|
else noOptimiz = CRYPTO_memcmp(passwd.data(), passwd.data(), passwd.size());
|
||||||
|
|
||||||
// attempt avoiding +else CRYPTO_memcmp+ being optimized away
|
/* At this point we are sure password is wrong, and one could think to
|
||||||
return static_cast<uint32_t>(noOptimiz) + 1 == 0;
|
* plainly `return false` still this ugly and apparently unuseful extra
|
||||||
|
* calculation is here to avoid `else CRYPTO_memcmp` being optimized away,
|
||||||
|
* so a pontential attacker cannot guess password size based on timing */
|
||||||
|
return static_cast<uint32_t>(noOptimiz) + 1 == 0 ?
|
||||||
|
success() : failure(RsJsonApiErrorNum::WRONG_API_PASSWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> JsonApiServer::getAuthorizedTokens()
|
std::map<std::string, std::string> JsonApiServer::getAuthorizedTokens()
|
||||||
@ -509,22 +629,11 @@ void JsonApiServer::connectToConfigManager(p3ConfigMgr& cfgmgr)
|
|||||||
loadConfiguration(hash);
|
loadConfiguration(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonApiServer::authorizeUser(
|
std::error_condition JsonApiServer::authorizeUser(
|
||||||
const std::string& user, const std::string& passwd )
|
const std::string& user, const std::string& passwd )
|
||||||
{
|
{
|
||||||
if(!librs::util::is_alphanumeric(user))
|
auto ec = badApiCredientalsFormat(user, passwd);
|
||||||
{
|
if(ec) return ec;
|
||||||
RsErr() << __PRETTY_FUNCTION__ << " User name is not alphanumeric"
|
|
||||||
<< std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(passwd.empty())
|
|
||||||
{
|
|
||||||
RsWarn() << __PRETTY_FUNCTION__ << " Password is empty, are you sure "
|
|
||||||
<< "this what you wanted?" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RS_STACK_MUTEX(configMutex);
|
RS_STACK_MUTEX(configMutex);
|
||||||
|
|
||||||
@ -534,7 +643,7 @@ bool JsonApiServer::authorizeUser(
|
|||||||
p = passwd;
|
p = passwd;
|
||||||
IndicateConfigChanged();
|
IndicateConfigChanged();
|
||||||
}
|
}
|
||||||
return true;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ std::string JsonApiServer::decodeToken(const std::string& radix64_token)
|
/*static*/ std::string JsonApiServer::decodeToken(const std::string& radix64_token)
|
||||||
@ -600,21 +709,21 @@ std::vector<std::shared_ptr<rb::Resource> > JsonApiServer::getResources() const
|
|||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonApiServer::restart()
|
std::error_condition JsonApiServer::restart()
|
||||||
{
|
{
|
||||||
/* It is important to wrap into async(...) because fullstop() method can't
|
const auto now = time(nullptr);
|
||||||
* be called from same thread of execution hence from JSON API thread! */
|
if(mRestartReqTS.exchange(now) + RESTART_BURST_PROTECTION > now)
|
||||||
RsThread::async([this]()
|
return RsJsonApiErrorNum::NOT_A_MACHINE_GUN;
|
||||||
{
|
|
||||||
fullstop();
|
unProtectedRestart();
|
||||||
RsThread::start("JSON API Server");
|
return std::error_condition();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonApiServer::onStopRequested()
|
void JsonApiServer::onStopRequested()
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mServiceMutex);
|
auto tService = std::atomic_exchange(
|
||||||
mService->stop();
|
&mService, std::shared_ptr<rb::Service>(nullptr) );
|
||||||
|
if(tService) tService->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t JsonApiServer::listeningPort() const { return mListeningPort; }
|
uint16_t JsonApiServer::listeningPort() const { return mListeningPort; }
|
||||||
@ -630,14 +739,9 @@ void JsonApiServer::run()
|
|||||||
settings->set_bind_address(mBindingAddress);
|
settings->set_bind_address(mBindingAddress);
|
||||||
settings->set_default_header("Connection", "close");
|
settings->set_default_header("Connection", "close");
|
||||||
|
|
||||||
/* re-allocating mService is important because it deletes the existing
|
auto tService = std::make_shared<restbed::Service>();
|
||||||
* service and therefore leaves the listening port open */
|
|
||||||
{
|
|
||||||
RS_STACK_MUTEX(mServiceMutex);
|
|
||||||
mService = std::make_shared<restbed::Service>();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& r: getResources()) mService->publish(r);
|
for(auto& r: getResources()) tService->publish(r);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -645,7 +749,20 @@ void JsonApiServer::run()
|
|||||||
.setPort(mListeningPort);
|
.setPort(mListeningPort);
|
||||||
RsInfo() << __PRETTY_FUNCTION__ << " JSON API server listening on "
|
RsInfo() << __PRETTY_FUNCTION__ << " JSON API server listening on "
|
||||||
<< apiUrl.toString() << std::endl;
|
<< apiUrl.toString() << std::endl;
|
||||||
mService->start(settings);
|
|
||||||
|
/* re-allocating mService is important because it deletes the existing
|
||||||
|
* service and therefore leaves the listening port open */
|
||||||
|
auto tExpected = std::shared_ptr<rb::Service>(nullptr);
|
||||||
|
if(atomic_compare_exchange_strong(&mService, &tExpected, tService))
|
||||||
|
tService->start(settings);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " mService was expected to be "
|
||||||
|
<< " null, instead we got: " << tExpected
|
||||||
|
<< " something wrong happened JsonApiServer won't start"
|
||||||
|
<< std::endl;
|
||||||
|
print_stacktrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
@ -668,3 +785,19 @@ void JsonApiServer::run()
|
|||||||
extra = RS_EXTRA_VERSION;
|
extra = RS_EXTRA_VERSION;
|
||||||
human = RS_HUMAN_READABLE_VERSION;
|
human = RS_HUMAN_READABLE_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::error_condition RsJsonApiErrorCategory::default_error_condition(int ev) const noexcept
|
||||||
|
{
|
||||||
|
switch(static_cast<RsJsonApiErrorNum>(ev))
|
||||||
|
{
|
||||||
|
case RsJsonApiErrorNum::TOKEN_FORMAT_INVALID: // fallthrough
|
||||||
|
case RsJsonApiErrorNum::UNKNOWN_API_USER: // fallthrough
|
||||||
|
case RsJsonApiErrorNum::WRONG_API_PASSWORD: // fallthrough
|
||||||
|
case RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED:
|
||||||
|
return std::errc::permission_denied;
|
||||||
|
case RsJsonApiErrorNum::API_USER_CONTAIN_COLON:
|
||||||
|
return std::errc::invalid_argument;
|
||||||
|
default:
|
||||||
|
return std::error_condition(ev, *this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
#include "pqi/p3cfgmgr.h"
|
#include "pqi/p3cfgmgr.h"
|
||||||
@ -40,6 +41,7 @@
|
|||||||
|
|
||||||
namespace rb = restbed;
|
namespace rb = restbed;
|
||||||
|
|
||||||
|
/** Interface to provide addotional resources to JsonApiServer */
|
||||||
class JsonApiResourceProvider
|
class JsonApiResourceProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -66,7 +68,7 @@ public:
|
|||||||
void fullstop() override { RsThread::fullstop(); }
|
void fullstop() override { RsThread::fullstop(); }
|
||||||
|
|
||||||
/// @see RsJsonApi
|
/// @see RsJsonApi
|
||||||
void restart() override;
|
std::error_condition restart() override;
|
||||||
|
|
||||||
/// @see RsJsonApi
|
/// @see RsJsonApi
|
||||||
void askForStop() override { RsThread::askForStop(); }
|
void askForStop() override { RsThread::askForStop(); }
|
||||||
@ -90,9 +92,8 @@ public:
|
|||||||
void connectToConfigManager(p3ConfigMgr& cfgmgr) override;
|
void connectToConfigManager(p3ConfigMgr& cfgmgr) override;
|
||||||
|
|
||||||
/// @see RsJsonApi
|
/// @see RsJsonApi
|
||||||
virtual bool authorizeUser(
|
virtual std::error_condition authorizeUser(
|
||||||
const std::string& alphanumeric_user,
|
const std::string& user, const std::string& passwd ) override;
|
||||||
const std::string& alphanumeric_passwd ) override;
|
|
||||||
|
|
||||||
/// @see RsJsonApi
|
/// @see RsJsonApi
|
||||||
std::map<std::string,std::string> getAuthorizedTokens() override;
|
std::map<std::string,std::string> getAuthorizedTokens() override;
|
||||||
@ -101,10 +102,13 @@ public:
|
|||||||
bool revokeAuthToken(const std::string& user) override;
|
bool revokeAuthToken(const std::string& user) override;
|
||||||
|
|
||||||
/// @see RsJsonApi
|
/// @see RsJsonApi
|
||||||
bool isAuthTokenValid(const std::string& token) override;
|
bool isAuthTokenValid(
|
||||||
|
const std::string& token,
|
||||||
|
std::error_condition& error = RS_DEFAULT_STORAGE_PARAM(std::error_condition)
|
||||||
|
) override;
|
||||||
|
|
||||||
/// @see RsJsonAPI
|
/// @see RsJsonAPI
|
||||||
bool requestNewTokenAutorization(
|
std::error_condition requestNewTokenAutorization(
|
||||||
const std::string& user, const std::string& password ) override;
|
const std::string& user, const std::string& password ) override;
|
||||||
|
|
||||||
/// @see RsJsonApi
|
/// @see RsJsonApi
|
||||||
@ -147,6 +151,11 @@ protected:
|
|||||||
/// @see RsThread
|
/// @see RsThread
|
||||||
void onStopRequested() override;
|
void onStopRequested() override;
|
||||||
|
|
||||||
|
static const RsJsonApiErrorCategory sErrorCategory;
|
||||||
|
|
||||||
|
static std::error_condition badApiCredientalsFormat(
|
||||||
|
const std::string& user, const std::string& passwd );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @see RsThread
|
/// @see RsThread
|
||||||
void run() override;
|
void run() override;
|
||||||
@ -195,13 +204,33 @@ private:
|
|||||||
std::reference_wrapper<const JsonApiResourceProvider>,
|
std::reference_wrapper<const JsonApiResourceProvider>,
|
||||||
std::less<const JsonApiResourceProvider> > mResourceProviders;
|
std::less<const JsonApiResourceProvider> > mResourceProviders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This pointer should be accessed via std::atomic_* operations, up until
|
||||||
|
* now only very critical operations like reallocation, are done that way,
|
||||||
|
* but this is not still 100% thread safe, but seems to handle all of the
|
||||||
|
* test cases (no crash, no deadlock), once we switch to C++20 we shoud
|
||||||
|
* change this into std::atomic<std::shared_ptr<restbed::Service>> which
|
||||||
|
* will automatically handle atomic access properly all the times
|
||||||
|
*/
|
||||||
std::shared_ptr<restbed::Service> mService;
|
std::shared_ptr<restbed::Service> mService;
|
||||||
/** Protect service only during very critical operation like resetting the
|
|
||||||
* pointer, still not 100% thread safe, but hopefully we can avoid
|
|
||||||
* crashes/freeze with this */
|
|
||||||
RsMutex mServiceMutex;
|
|
||||||
|
|
||||||
uint16_t mListeningPort;
|
uint16_t mListeningPort;
|
||||||
std::string mBindingAddress;
|
std::string mBindingAddress;
|
||||||
|
|
||||||
|
/// @see unProtectedRestart()
|
||||||
|
std::atomic<rstime_t> mRestartReqTS;
|
||||||
|
|
||||||
|
/// @see unProtectedRestart()
|
||||||
|
constexpr static rstime_t RESTART_BURST_PROTECTION = 7;
|
||||||
|
|
||||||
|
/** It is very important to protect this method from being called in bursts,
|
||||||
|
* because Restbed::Service::stop() together with
|
||||||
|
* Restbed::Service::start(...), which are called internally, silently fails
|
||||||
|
* if combined in bursts, probably because they have to deal with
|
||||||
|
* listening/releasing TCP port.
|
||||||
|
* @see JsonApiServer::restart() and @see JsonApiServer::JsonApiServer()
|
||||||
|
* implementation to understand how correctly use this.
|
||||||
|
*/
|
||||||
|
void unProtectedRestart();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,7 +88,13 @@ enum class RsEventType : uint32_t
|
|||||||
/// @see RsGxsPostedEvent
|
/// @see RsGxsPostedEvent
|
||||||
GXS_IDENTITY = 12,
|
GXS_IDENTITY = 12,
|
||||||
|
|
||||||
MAX /// Used to detect invalid event type passed
|
/// @see RsFiles
|
||||||
|
SHARED_DIRECTORIES = 13,
|
||||||
|
|
||||||
|
/// @see RsFiles
|
||||||
|
FILE_TRANSFER = 14,
|
||||||
|
|
||||||
|
MAX /// Used to detect invalid event type passed
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "serialiser/rsserializable.h"
|
#include "serialiser/rsserializable.h"
|
||||||
#include "rsturtle.h"
|
#include "rsturtle.h"
|
||||||
#include "util/rstime.h"
|
#include "util/rstime.h"
|
||||||
|
#include "retroshare/rsevents.h"
|
||||||
|
|
||||||
class RsFiles;
|
class RsFiles;
|
||||||
|
|
||||||
@ -114,6 +115,55 @@ const TransferRequestFlags RS_FILE_REQ_NO_SEARCH ( 0x02000000 ); // di
|
|||||||
|
|
||||||
const uint32_t RS_FILE_EXTRA_DELETE = 0x0010;
|
const uint32_t RS_FILE_EXTRA_DELETE = 0x0010;
|
||||||
|
|
||||||
|
enum class RsSharedDirectoriesEventCode: uint8_t {
|
||||||
|
UNKNOWN = 0x00,
|
||||||
|
STARTING_DIRECTORY_SWEEP = 0x01, // (void)
|
||||||
|
HASHING_FILE = 0x02, // mMessage: full path and hashing speed of the file being hashed
|
||||||
|
DIRECTORY_SWEEP_ENDED = 0x03, // (void)
|
||||||
|
SAVING_FILE_INDEX = 0x04, // (void)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RsFileTransferEventCode: uint8_t {
|
||||||
|
UNKNOWN = 0x00,
|
||||||
|
DOWNLOAD_COMPLETE = 0x01, // mHash: hash of the complete file
|
||||||
|
COMPLETED_FILES_REMOVED = 0x02, //
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RsSharedDirectoriesEvent: RsEvent
|
||||||
|
{
|
||||||
|
RsSharedDirectoriesEvent() : RsEvent(RsEventType::SHARED_DIRECTORIES), mEventCode(RsSharedDirectoriesEventCode::UNKNOWN) {}
|
||||||
|
~RsSharedDirectoriesEvent() override = default;
|
||||||
|
|
||||||
|
///* @see RsEvent @see RsSerializable
|
||||||
|
void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override
|
||||||
|
{
|
||||||
|
RsEvent::serial_process(j, ctx);
|
||||||
|
|
||||||
|
RS_SERIAL_PROCESS(mEventCode);
|
||||||
|
RS_SERIAL_PROCESS(mMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
RsSharedDirectoriesEventCode mEventCode;
|
||||||
|
std::string mMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RsFileTransferEvent: RsEvent
|
||||||
|
{
|
||||||
|
RsFileTransferEvent() : RsEvent(RsEventType::FILE_TRANSFER), mFileTransferEventCode(RsFileTransferEventCode::UNKNOWN) {}
|
||||||
|
~RsFileTransferEvent() override = default;
|
||||||
|
|
||||||
|
///* @see RsEvent @see RsSerializable
|
||||||
|
void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override
|
||||||
|
{
|
||||||
|
RsEvent::serial_process(j, ctx);
|
||||||
|
|
||||||
|
RS_SERIAL_PROCESS(mFileTransferEventCode);
|
||||||
|
RS_SERIAL_PROCESS(mHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
RsFileTransferEventCode mFileTransferEventCode;
|
||||||
|
RsFileHash mHash;
|
||||||
|
};
|
||||||
struct SharedDirInfo : RsSerializable
|
struct SharedDirInfo : RsSerializable
|
||||||
{
|
{
|
||||||
static bool sameLists(const std::list<RsNodeGroupId>& l1,const std::list<RsNodeGroupId>& l2)
|
static bool sameLists(const std::list<RsNodeGroupId>& l1,const std::list<RsNodeGroupId>& l2)
|
||||||
|
@ -105,27 +105,15 @@ struct RsGxsChannelPost : RsSerializable
|
|||||||
|
|
||||||
enum class RsChannelEventCode: uint8_t
|
enum class RsChannelEventCode: uint8_t
|
||||||
{
|
{
|
||||||
UNKNOWN = 0x00,
|
UNKNOWN = 0x00,
|
||||||
NEW_CHANNEL = 0x01, /// emitted when new channel is received
|
NEW_CHANNEL = 0x01, // emitted when new channel is received
|
||||||
|
UPDATED_CHANNEL = 0x02, // emitted when existing channel is updated
|
||||||
/// emitted when existing channel is updated
|
NEW_MESSAGE = 0x03, // new message reeived in a particular channel (group and msg id)
|
||||||
UPDATED_CHANNEL = 0x02,
|
UPDATED_MESSAGE = 0x04, // existing message has been updated in a particular channel
|
||||||
|
RECEIVED_PUBLISH_KEY = 0x05, // publish key for this channel has been received
|
||||||
/// new message reeived in a particular channel (group and msg id)
|
SUBSCRIBE_STATUS_CHANGED = 0x06, // subscription for channel mChannelGroupId changed.
|
||||||
NEW_MESSAGE = 0x03,
|
READ_STATUS_CHANGED = 0x07, // existing message has been read or set to unread
|
||||||
|
RECEIVED_DISTANT_SEARCH_RESULT = 0x08, // result for the given group id available for the given turtle request id
|
||||||
/// 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,
|
|
||||||
|
|
||||||
/// existing message has been read or set to unread
|
|
||||||
READ_STATUS_CHANGED = 0x07,
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RsGxsChannelEvent: RsEvent
|
struct RsGxsChannelEvent: RsEvent
|
||||||
@ -137,6 +125,7 @@ struct RsGxsChannelEvent: RsEvent
|
|||||||
RsChannelEventCode mChannelEventCode;
|
RsChannelEventCode mChannelEventCode;
|
||||||
RsGxsGroupId mChannelGroupId;
|
RsGxsGroupId mChannelGroupId;
|
||||||
RsGxsMessageId mChannelMsgId;
|
RsGxsMessageId mChannelMsgId;
|
||||||
|
TurtleRequestId mDistantSearchRequestId;
|
||||||
|
|
||||||
///* @see RsEvent @see RsSerializable
|
///* @see RsEvent @see RsSerializable
|
||||||
void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override
|
void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override
|
||||||
@ -146,6 +135,7 @@ struct RsGxsChannelEvent: RsEvent
|
|||||||
RS_SERIAL_PROCESS(mChannelEventCode);
|
RS_SERIAL_PROCESS(mChannelEventCode);
|
||||||
RS_SERIAL_PROCESS(mChannelGroupId);
|
RS_SERIAL_PROCESS(mChannelGroupId);
|
||||||
RS_SERIAL_PROCESS(mChannelMsgId);
|
RS_SERIAL_PROCESS(mChannelMsgId);
|
||||||
|
RS_SERIAL_PROCESS(mDistantSearchRequestId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,7 +40,14 @@ typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsMsgMetaData> > GxsMsgRelatedMe
|
|||||||
struct RsGxsNotify
|
struct RsGxsNotify
|
||||||
{
|
{
|
||||||
enum NotifyType
|
enum NotifyType
|
||||||
{ TYPE_PUBLISHED, TYPE_RECEIVED_NEW, TYPE_PROCESSED, TYPE_RECEIVED_PUBLISHKEY, TYPE_RECEIVED_DISTANT_SEARCH_RESULTS };
|
{
|
||||||
|
TYPE_UNKNOWN = 0x00,
|
||||||
|
TYPE_PUBLISHED = 0x01,
|
||||||
|
TYPE_RECEIVED_NEW = 0x02,
|
||||||
|
TYPE_PROCESSED = 0x03,
|
||||||
|
TYPE_RECEIVED_PUBLISHKEY = 0x04,
|
||||||
|
TYPE_RECEIVED_DISTANT_SEARCH_RESULTS = 0x05
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~RsGxsNotify() {}
|
virtual ~RsGxsNotify() {}
|
||||||
virtual NotifyType getType() = 0;
|
virtual NotifyType getType() = 0;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* RetroShare JSON API public header
|
* RetroShare JSON API public header
|
||||||
*
|
*
|
||||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio.eigenlab.org>
|
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio.eigenlab.org>
|
||||||
* Copyright (C) 2019 Cyril Soler <csoler@users.sourceforge.net>
|
* Copyright (C) 2019 Cyril Soler <csoler@users.sourceforge.net>
|
||||||
|
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under
|
* 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
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
@ -25,9 +26,11 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
#include "util/rsmemory.h"
|
||||||
|
|
||||||
class p3ConfigMgr;
|
|
||||||
class JsonApiResourceProvider;
|
|
||||||
class RsJsonApi;
|
class RsJsonApi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,6 +39,71 @@ class RsJsonApi;
|
|||||||
*/
|
*/
|
||||||
extern RsJsonApi* rsJsonApi;
|
extern RsJsonApi* rsJsonApi;
|
||||||
|
|
||||||
|
enum class RsJsonApiErrorNum : int32_t
|
||||||
|
{
|
||||||
|
TOKEN_FORMAT_INVALID = 2004,
|
||||||
|
UNKNOWN_API_USER = 2005,
|
||||||
|
WRONG_API_PASSWORD = 2006,
|
||||||
|
API_USER_CONTAIN_COLON = 2007,
|
||||||
|
AUTHORIZATION_REQUEST_DENIED = 2008,
|
||||||
|
CANNOT_EXECUTE_BEFORE_RS_LOGIN = 2009,
|
||||||
|
NOT_A_MACHINE_GUN = 2010
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RsJsonApiErrorCategory: std::error_category
|
||||||
|
{
|
||||||
|
const char* name() const noexcept override
|
||||||
|
{ return "RetroShare JSON API"; }
|
||||||
|
|
||||||
|
std::string message(int ev) const override
|
||||||
|
{
|
||||||
|
switch (static_cast<RsJsonApiErrorNum>(ev))
|
||||||
|
{
|
||||||
|
case RsJsonApiErrorNum::TOKEN_FORMAT_INVALID:
|
||||||
|
return "Invalid token format, must be alphanumeric_user:password";
|
||||||
|
case RsJsonApiErrorNum::UNKNOWN_API_USER:
|
||||||
|
return "Unknown API user";
|
||||||
|
case RsJsonApiErrorNum::WRONG_API_PASSWORD:
|
||||||
|
return "Wrong API password";
|
||||||
|
case RsJsonApiErrorNum::API_USER_CONTAIN_COLON:
|
||||||
|
return "API user cannot contain colon character";
|
||||||
|
case RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED:
|
||||||
|
return "User denied new token autorization";
|
||||||
|
case RsJsonApiErrorNum::CANNOT_EXECUTE_BEFORE_RS_LOGIN:
|
||||||
|
return "This operation cannot be executed bedore RetroShare login";
|
||||||
|
case RsJsonApiErrorNum::NOT_A_MACHINE_GUN:
|
||||||
|
return "Method must not be called in burst";
|
||||||
|
default:
|
||||||
|
return "Error message for error: " + std::to_string(ev) +
|
||||||
|
" not available in category: " + name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_condition default_error_condition(int ev) const noexcept override;
|
||||||
|
|
||||||
|
const static RsJsonApiErrorCategory instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
/** Register RsJsonApiErrorNum as an error condition enum, must be in std
|
||||||
|
* namespace */
|
||||||
|
template<> struct is_error_condition_enum<RsJsonApiErrorNum> : true_type {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in
|
||||||
|
* same namespace of RsJsonApiErrorNum */
|
||||||
|
inline std::error_condition make_error_condition(RsJsonApiErrorNum e) noexcept
|
||||||
|
{
|
||||||
|
return std::error_condition(
|
||||||
|
static_cast<int>(e), RsJsonApiErrorCategory::instance );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class p3ConfigMgr;
|
||||||
|
class JsonApiResourceProvider;
|
||||||
|
|
||||||
class RsJsonApi
|
class RsJsonApi
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -43,10 +111,12 @@ public:
|
|||||||
static const std::string DEFAULT_BINDING_ADDRESS; // 127.0.0.1
|
static const std::string DEFAULT_BINDING_ADDRESS; // 127.0.0.1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Restart RsJsonApi server asynchronously.
|
* @brief Restart RsJsonApi server.
|
||||||
* @jsonapi{development}
|
* This method is asyncronous when called from JSON API.
|
||||||
|
* @jsonapi{development,manualwrapper}
|
||||||
|
* @return Success or error details
|
||||||
*/
|
*/
|
||||||
virtual void restart() = 0;
|
virtual std::error_condition restart() = 0;
|
||||||
|
|
||||||
/** @brief Request RsJsonApi to stop and wait until it has stopped.
|
/** @brief Request RsJsonApi to stop and wait until it has stopped.
|
||||||
* Do not expose this method to JSON API as fullstop must not be called from
|
* Do not expose this method to JSON API as fullstop must not be called from
|
||||||
@ -124,9 +194,9 @@ public:
|
|||||||
* @jsonapi{development,unauthenticated}
|
* @jsonapi{development,unauthenticated}
|
||||||
* @param[in] user user name to authorize
|
* @param[in] user user name to authorize
|
||||||
* @param[in] password password for the new user
|
* @param[in] password password for the new user
|
||||||
* @return true if authorization succeded, false otherwise.
|
* @return if an error occurred details about it.
|
||||||
*/
|
*/
|
||||||
virtual bool requestNewTokenAutorization(
|
virtual std::error_condition requestNewTokenAutorization(
|
||||||
const std::string& user, const std::string& password) = 0;
|
const std::string& user, const std::string& password) = 0;
|
||||||
|
|
||||||
/** Split a token in USER:PASSWORD format into user and password */
|
/** Split a token in USER:PASSWORD format into user and password */
|
||||||
@ -135,14 +205,13 @@ public:
|
|||||||
std::string& user, std::string& passwd );
|
std::string& user, std::string& passwd );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new API auth (user,passwd) token to the authorized set.
|
* Add new API auth user, passwd to the authorized set.
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
* @param[in] user user name to autorize, must be alphanumerinc
|
* @param[in] user user name to autorize, must not contain ':'
|
||||||
* @param[in] password password for the user, must be alphanumerinc
|
* @param[in] password password for the user
|
||||||
* @return true if the token has been added to authorized, false if error
|
* @return if some error occurred return details about it
|
||||||
* occurred
|
|
||||||
*/
|
*/
|
||||||
virtual bool authorizeUser(
|
virtual std::error_condition authorizeUser(
|
||||||
const std::string& user, const std::string& password ) = 0;
|
const std::string& user, const std::string& password ) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,9 +233,13 @@ public:
|
|||||||
* @brief Check if given JSON API auth token is authorized
|
* @brief Check if given JSON API auth token is authorized
|
||||||
* @jsonapi{development,unauthenticated}
|
* @jsonapi{development,unauthenticated}
|
||||||
* @param[in] token decoded
|
* @param[in] token decoded
|
||||||
* @return tru if authorized, false otherwise
|
* @param[out] error optional storage for error details
|
||||||
|
* @return true if authorized, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool isAuthTokenValid(const std::string& token) = 0;
|
virtual bool isAuthTokenValid(
|
||||||
|
const std::string& token,
|
||||||
|
std::error_condition& error = RS_DEFAULT_STORAGE_PARAM(std::error_condition)
|
||||||
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Write version information to given paramethers
|
* @brief Write version information to given paramethers
|
||||||
@ -182,3 +255,4 @@ public:
|
|||||||
|
|
||||||
virtual ~RsJsonApi() = default;
|
virtual ~RsJsonApi() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -397,8 +397,8 @@ int RsInit::InitRetroShare(const RsConfigOptions& conf)
|
|||||||
|
|
||||||
#ifdef RS_JSONAPI
|
#ifdef RS_JSONAPI
|
||||||
// We create the JsonApiServer this early, because it is needed *before* login
|
// We create the JsonApiServer this early, because it is needed *before* login
|
||||||
RsInfo() << __PRETTY_FUNCTION__
|
RsDbg() << __PRETTY_FUNCTION__
|
||||||
<< "Allocating jsonAPI server (not launched yet)" << std::endl;
|
<< " Allocating JSON API server (not launched yet)" << std::endl;
|
||||||
JsonApiServer* jas = new JsonApiServer();
|
JsonApiServer* jas = new JsonApiServer();
|
||||||
jas->setListeningPort(conf.jsonApiPort);
|
jas->setListeningPort(conf.jsonApiPort);
|
||||||
jas->setBindingAddress(conf.jsonApiBindAddress);
|
jas->setBindingAddress(conf.jsonApiBindAddress);
|
||||||
|
@ -768,3 +768,37 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RsTypeSerializer::ErrConditionWrapper::serial_process(
|
||||||
|
RsGenericSerializer::SerializeJob j,
|
||||||
|
RsGenericSerializer::SerializeContext& ctx )
|
||||||
|
{
|
||||||
|
switch(j)
|
||||||
|
{
|
||||||
|
case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough
|
||||||
|
case RsGenericSerializer::DESERIALIZE: // fallthrough
|
||||||
|
case RsGenericSerializer::SERIALIZE: // fallthrough
|
||||||
|
case RsGenericSerializer::FROM_JSON:
|
||||||
|
RsFatal() << __PRETTY_FUNCTION__ << " SerializeJob: " << j
|
||||||
|
<< "is not supported on std::error_condition " << std::endl;
|
||||||
|
print_stacktrace();
|
||||||
|
exit(-2);
|
||||||
|
case RsGenericSerializer::PRINT: // fallthrough
|
||||||
|
case RsGenericSerializer::TO_JSON:
|
||||||
|
{
|
||||||
|
constexpr RsGenericSerializer::SerializeJob rj =
|
||||||
|
RsGenericSerializer::TO_JSON;
|
||||||
|
|
||||||
|
int32_t tNum = mec.value();
|
||||||
|
RsTypeSerializer::serial_process(rj, ctx, tNum, "errorNumber");
|
||||||
|
|
||||||
|
std::string tStr = mec.category().name();
|
||||||
|
RsTypeSerializer::serial_process(rj, ctx, tStr, "errorCategory");
|
||||||
|
|
||||||
|
tStr = mec.message();
|
||||||
|
RsTypeSerializer::serial_process(rj, ctx, tStr, "errorMessage");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: RsTypeSerializer::fatalUnknownSerialJob(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,12 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <typeinfo> // for typeid
|
||||||
|
#include <type_traits>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
|
||||||
#include "serialiser/rsserial.h"
|
#include "serialiser/rsserial.h"
|
||||||
#include "serialiser/rstlvbase.h"
|
#include "serialiser/rstlvbase.h"
|
||||||
#include "serialiser/rstlvlist.h"
|
#include "serialiser/rstlvlist.h"
|
||||||
@ -34,11 +40,6 @@
|
|||||||
#include "util/rsjson.h"
|
#include "util/rsjson.h"
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
#include <typeinfo> // for typeid
|
|
||||||
#include <type_traits>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
|
/* INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
|
||||||
* Can't use a template function because T is needed for const_cast */
|
* Can't use a template function because T is needed for const_cast */
|
||||||
#define RsTypeSerializer_PRIVATE_TO_JSON_ARRAY() do \
|
#define RsTypeSerializer_PRIVATE_TO_JSON_ARRAY() do \
|
||||||
@ -132,7 +133,12 @@ struct RsTypeSerializer
|
|||||||
|
|
||||||
/// Generic types
|
/// Generic types
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename std::enable_if<std::is_same<RsTlvItem,T>::value || !(std::is_base_of<RsSerializable,T>::value || std::is_enum<T>::value || std::is_base_of<RsTlvItem,T>::value )>::type
|
typename
|
||||||
|
std::enable_if< std::is_same<RsTlvItem,T>::value || !(
|
||||||
|
std::is_base_of<RsSerializable,T>::value ||
|
||||||
|
std::is_enum<T>::value ||
|
||||||
|
std::is_base_of<RsTlvItem,T>::value ||
|
||||||
|
std::is_same<std::error_condition,T>::value ) >::type
|
||||||
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
|
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
|
||||||
RsGenericSerializer::SerializeContext& ctx,
|
RsGenericSerializer::SerializeContext& ctx,
|
||||||
T& member, const std::string& member_name )
|
T& member, const std::string& member_name )
|
||||||
@ -160,11 +166,7 @@ struct RsTypeSerializer
|
|||||||
ctx.mOk &= (ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
|
ctx.mOk &= (ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
|
||||||
&& from_JSON(member_name, member, ctx.mJson);
|
&& from_JSON(member_name, member, ctx.mJson);
|
||||||
break;
|
break;
|
||||||
default:
|
default: fatalUnknownSerialJob(j);
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
|
||||||
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
|
|
||||||
<< std::endl;
|
|
||||||
exit(EINVAL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,11 +202,7 @@ struct RsTypeSerializer
|
|||||||
(ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
|
(ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
|
||||||
&& from_JSON(member_name, type_id, member, ctx.mJson);
|
&& from_JSON(member_name, type_id, member, ctx.mJson);
|
||||||
break;
|
break;
|
||||||
default:
|
default: fatalUnknownSerialJob(j);
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
|
||||||
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
|
|
||||||
<< std::endl;
|
|
||||||
exit(EINVAL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,11 +360,7 @@ struct RsTypeSerializer
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: fatalUnknownSerialJob(j);
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
|
||||||
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
|
|
||||||
<< std::endl;
|
|
||||||
exit(EINVAL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,12 +435,7 @@ struct RsTypeSerializer
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: fatalUnknownSerialJob(j);
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
|
||||||
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
|
|
||||||
<< std::endl;
|
|
||||||
exit(EINVAL);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +494,7 @@ struct RsTypeSerializer
|
|||||||
case RsGenericSerializer::FROM_JSON:
|
case RsGenericSerializer::FROM_JSON:
|
||||||
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
|
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: fatalUnknownSerialJob(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,7 +553,7 @@ struct RsTypeSerializer
|
|||||||
case RsGenericSerializer::FROM_JSON:
|
case RsGenericSerializer::FROM_JSON:
|
||||||
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(insert);
|
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(insert);
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: fatalUnknownSerialJob(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,7 +609,7 @@ struct RsTypeSerializer
|
|||||||
case RsGenericSerializer::FROM_JSON:
|
case RsGenericSerializer::FROM_JSON:
|
||||||
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
|
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: fatalUnknownSerialJob(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,7 +652,7 @@ struct RsTypeSerializer
|
|||||||
&& (v = t_RsFlags32<N>(f), true);
|
&& (v = t_RsFlags32<N>(f), true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: fatalUnknownSerialJob(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,18 +761,15 @@ struct RsTypeSerializer
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: fatalUnknownSerialJob(j);
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
|
|
||||||
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
|
|
||||||
<< std::endl;
|
|
||||||
exit(EINVAL);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RsTlvItem derivatives only
|
/// RsTlvItem derivatives only
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename std::enable_if<std::is_base_of<RsTlvItem,T>::value && !std::is_same<RsTlvItem,T>::value>::type
|
typename std::enable_if<
|
||||||
|
std::is_base_of<RsTlvItem,T>::value && !std::is_same<RsTlvItem,T>::value
|
||||||
|
>::type
|
||||||
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
|
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
|
||||||
RsGenericSerializer::SerializeContext& ctx,
|
RsGenericSerializer::SerializeContext& ctx,
|
||||||
T& member,
|
T& member,
|
||||||
@ -792,6 +778,21 @@ struct RsTypeSerializer
|
|||||||
serial_process(j, ctx, static_cast<RsTlvItem&>(member), memberName);
|
serial_process(j, ctx, static_cast<RsTlvItem&>(member), memberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** std::error_condition
|
||||||
|
* supports only TO_JSON ErrConditionWrapper::serial_process will explode
|
||||||
|
* at runtime if a different SerializeJob is passed down */
|
||||||
|
template<typename T>
|
||||||
|
typename std::enable_if< std::is_base_of<std::error_condition,T>::value >::type
|
||||||
|
static /*void*/ serial_process(
|
||||||
|
RsGenericSerializer::SerializeJob j,
|
||||||
|
RsGenericSerializer::SerializeContext& ctx,
|
||||||
|
const T& cond,
|
||||||
|
const std::string& member_name )
|
||||||
|
{
|
||||||
|
ErrConditionWrapper ew(cond);
|
||||||
|
serial_process(j, ctx, ew, member_name);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
//============================================================================//
|
//============================================================================//
|
||||||
@ -909,6 +910,27 @@ protected:
|
|||||||
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
|
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
|
||||||
RsJson& jDoc );
|
RsJson& jDoc );
|
||||||
|
|
||||||
|
[[noreturn]] static void fatalUnknownSerialJob(int j)
|
||||||
|
{
|
||||||
|
RsFatal() << " Unknown serial job: " << j << std::endl;
|
||||||
|
print_stacktrace();
|
||||||
|
exit(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ErrConditionWrapper : RsSerializable
|
||||||
|
{
|
||||||
|
ErrConditionWrapper(const std::error_condition& ec): mec(ec) {}
|
||||||
|
|
||||||
|
/** supports only TO_JSON if a different SerializeJob is passed it will
|
||||||
|
* explode at runtime */
|
||||||
|
void serial_process(
|
||||||
|
RsGenericSerializer::SerializeJob j,
|
||||||
|
RsGenericSerializer::SerializeContext& ctx ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::error_condition& mec;
|
||||||
|
};
|
||||||
|
|
||||||
RS_SET_CONTEXT_DEBUG_LEVEL(1)
|
RS_SET_CONTEXT_DEBUG_LEVEL(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -245,6 +245,7 @@ void p3GxsChannels::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
|||||||
for(it = changes.begin(); it != changes.end(); ++it)
|
for(it = changes.begin(); it != changes.end(); ++it)
|
||||||
{
|
{
|
||||||
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
|
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
|
||||||
|
|
||||||
if (msgChange)
|
if (msgChange)
|
||||||
{
|
{
|
||||||
if (msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW|| msgChange->getType() == RsGxsNotify::TYPE_PUBLISHED)
|
if (msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW|| msgChange->getType() == RsGxsNotify::TYPE_PUBLISHED)
|
||||||
@ -294,75 +295,84 @@ void p3GxsChannels::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
RsGxsGroupChange *grpChange = dynamic_cast<RsGxsGroupChange*>(*it);
|
||||||
|
|
||||||
|
if (grpChange && rsEvents)
|
||||||
{
|
{
|
||||||
if (rsEvents)
|
switch (grpChange->getType())
|
||||||
{
|
{
|
||||||
RsGxsGroupChange *grpChange = dynamic_cast<RsGxsGroupChange*>(*it);
|
default:
|
||||||
if (grpChange)
|
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)
|
||||||
{
|
{
|
||||||
switch (grpChange->getType())
|
auto ev = std::make_shared<RsGxsChannelEvent>();
|
||||||
{
|
ev->mChannelGroupId = *git;
|
||||||
default:
|
ev->mChannelEventCode = RsChannelEventCode::SUBSCRIBE_STATUS_CHANGED;
|
||||||
case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed
|
rsEvents->postEvent(ev);
|
||||||
{
|
|
||||||
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::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(mKnownChannelsMutex);
|
|
||||||
for (git = grpList.begin(); git != grpList.end(); ++git)
|
|
||||||
{
|
|
||||||
if(mKnownChannels.find(*git) == mKnownChannels.end())
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if(mKnownChannels.find(*git) == mKnownChannels.end())
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsGxsDistantSearchResultChange *dsrChange = dynamic_cast<RsGxsDistantSearchResultChange*>(*it);
|
||||||
|
|
||||||
|
if(dsrChange && rsEvents)
|
||||||
|
{
|
||||||
|
auto ev = std::make_shared<RsGxsChannelEvent>();
|
||||||
|
ev->mChannelGroupId = dsrChange->mGroupId;
|
||||||
|
ev->mChannelEventCode = RsChannelEventCode::RECEIVED_DISTANT_SEARCH_RESULT;
|
||||||
|
ev->mDistantSearchRequestId = dsrChange->mRequestId;
|
||||||
|
|
||||||
|
rsEvents->postEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/* shouldn't need to worry about groups - as they need to be subscribed to */
|
/* shouldn't need to worry about groups - as they need to be subscribed to */
|
||||||
delete *it;
|
delete *it;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2004-2008 by Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2004-2008 by Robert Fernie <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 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 *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
@ -21,11 +23,25 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
#include "util/rsthreads.h"
|
|
||||||
#include "util/rsdir.h"
|
std::ostream &operator<<(std::ostream& out, const std::error_condition& err)
|
||||||
|
{
|
||||||
|
return out << " error: " << err.value() << " " << err.message()
|
||||||
|
<< " category: " << err.category().name();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// All the following lines are DEPRECATED!!
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "util/rsthreads.h"
|
||||||
|
#include "util/rsdir.h"
|
||||||
#include "util/rstime.h"
|
#include "util/rstime.h"
|
||||||
|
|
||||||
const int RS_DEBUG_STDERR = 1; /* stuff goes to stderr */
|
const int RS_DEBUG_STDERR = 1; /* stuff goes to stderr */
|
||||||
@ -186,6 +202,3 @@ void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg
|
|||||||
lineCount++;
|
lineCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
* RetroShare debugging utilities *
|
* RetroShare debugging utilities *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2004-2008 Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2004-2008 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2019-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 *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
@ -21,6 +22,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
/** Stream helper for std::error_condition */
|
||||||
|
std::ostream &operator<<(std::ostream& out, const std::error_condition& err);
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
# include <android/log.h>
|
# include <android/log.h>
|
||||||
@ -41,12 +46,14 @@ struct t_RsLogger
|
|||||||
{
|
{
|
||||||
inline t_RsLogger() = default;
|
inline t_RsLogger() = default;
|
||||||
|
|
||||||
|
typedef t_RsLogger stream_type;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline t_RsLogger& operator<<(const T& val)
|
inline stream_type& operator<<(const T& val)
|
||||||
{ ostr << val; return *this; }
|
{ ostr << val; return *this; }
|
||||||
|
|
||||||
/// needed for manipulators and things like std::endl
|
/// needed for manipulators and things like std::endl
|
||||||
t_RsLogger& operator<<(std::ostream& (*pf)(std::ostream&))
|
stream_type& operator<<(std::ostream& (*pf)(std::ostream&))
|
||||||
{
|
{
|
||||||
if(pf == static_cast<std::ostream& (*)(std::ostream&)>(
|
if(pf == static_cast<std::ostream& (*)(std::ostream&)>(
|
||||||
&std::endl< char, std::char_traits<char> > ))
|
&std::endl< char, std::char_traits<char> > ))
|
||||||
@ -84,8 +91,10 @@ struct t_RsLogger
|
|||||||
{
|
{
|
||||||
inline t_RsLogger() = default;
|
inline t_RsLogger() = default;
|
||||||
|
|
||||||
|
typedef decltype(std::cerr) stream_type;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::ostream& operator<<(const T& val)
|
inline stream_type& operator<<(const T& val)
|
||||||
{
|
{
|
||||||
return std::cerr << static_cast<char>(CATEGORY) << " " << time(nullptr)
|
return std::cerr << static_cast<char>(CATEGORY) << " " << time(nullptr)
|
||||||
<< " " << val;
|
<< " " << val;
|
||||||
@ -97,7 +106,7 @@ struct t_RsLogger
|
|||||||
/**
|
/**
|
||||||
* Comfortable debug message loggin, supports chaining like std::cerr but can
|
* Comfortable debug message loggin, supports chaining like std::cerr but can
|
||||||
* be easly and selectively disabled at compile time to reduce generated binary
|
* be easly and selectively disabled at compile time to reduce generated binary
|
||||||
* size and performance impact without too many #ifdef around.
|
* size and performance impact without too many \#ifdef around.
|
||||||
*
|
*
|
||||||
* To selectively debug your context you can just add something like this in
|
* To selectively debug your context you can just add something like this in
|
||||||
* in that context, as an example for a class you can just add a line like this
|
* in that context, as an example for a class you can just add a line like this
|
||||||
|
@ -205,6 +205,7 @@ bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool is_alphanumeric(char c)
|
bool is_alphanumeric(char c)
|
||||||
{
|
{
|
||||||
return (c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z');
|
return (c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z');
|
||||||
@ -216,6 +217,7 @@ bool is_alphanumeric(const std::string& s)
|
|||||||
if(!is_alphanumeric(s[i])) return false;
|
if(!is_alphanumeric(s[i])) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} } // librs::util
|
} } // librs::util
|
||||||
|
|
||||||
|
@ -30,10 +30,10 @@ namespace librs {
|
|||||||
|
|
||||||
bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest);
|
bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest);
|
||||||
bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest);
|
bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest);
|
||||||
|
#if 0
|
||||||
bool is_alphanumeric(char c) ;
|
bool is_alphanumeric(char c) ;
|
||||||
bool is_alphanumeric(const std::string& s);
|
bool is_alphanumeric(const std::string& s);
|
||||||
|
#endif
|
||||||
} } // librs::util
|
} } // librs::util
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2004-2007 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) 2016-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net> *
|
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
@ -23,7 +23,7 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <time.h>
|
#include <ctime>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@ -95,6 +95,9 @@ void RsThread::resetTid()
|
|||||||
}
|
}
|
||||||
|
|
||||||
RsThread::RsThread() : mHasStopped(true), mShouldStop(false), mLastTid()
|
RsThread::RsThread() : mHasStopped(true), mShouldStop(false), mLastTid()
|
||||||
|
#ifdef RS_THREAD_FORCE_STOP
|
||||||
|
, mStopTimeout(0)
|
||||||
|
#endif
|
||||||
{ resetTid(); }
|
{ resetTid(); }
|
||||||
|
|
||||||
bool RsThread::isRunning() { return !mHasStopped; }
|
bool RsThread::isRunning() { return !mHasStopped; }
|
||||||
@ -117,6 +120,10 @@ void RsThread::wrapRun()
|
|||||||
|
|
||||||
void RsThread::fullstop()
|
void RsThread::fullstop()
|
||||||
{
|
{
|
||||||
|
#ifdef RS_THREAD_FORCE_STOP
|
||||||
|
const rstime_t stopRequTS = time(nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
askForStop();
|
askForStop();
|
||||||
|
|
||||||
const pthread_t callerTid = pthread_self();
|
const pthread_t callerTid = pthread_self();
|
||||||
@ -141,6 +148,32 @@ void RsThread::fullstop()
|
|||||||
RsDbg() << __PRETTY_FUNCTION__ << " " << i*0.2 << " seconds passed"
|
RsDbg() << __PRETTY_FUNCTION__ << " " << i*0.2 << " seconds passed"
|
||||||
<< " waiting for thread: " << std::hex << mLastTid
|
<< " waiting for thread: " << std::hex << mLastTid
|
||||||
<< std::dec << " " << mFullName << " to stop" << std::endl;
|
<< std::dec << " " << mFullName << " to stop" << std::endl;
|
||||||
|
|
||||||
|
#ifdef RS_THREAD_FORCE_STOP
|
||||||
|
if(mStopTimeout && time(nullptr) > stopRequTS + mStopTimeout)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " thread mLastTid: " << std::hex
|
||||||
|
<< mLastTid << " mTid: " << mTid << std::dec << " "
|
||||||
|
<< mFullName
|
||||||
|
<< " ignored our nice stop request for more then "
|
||||||
|
<< mStopTimeout
|
||||||
|
<< " seconds, will be forcefully stopped. "
|
||||||
|
<< "Please submit a report to RetroShare developers"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
const auto terr = pthread_cancel(mTid);
|
||||||
|
if(terr == 0) mHasStopped = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " pthread_cancel("
|
||||||
|
<< std::hex << mTid << std::dec <<") returned "
|
||||||
|
<< terr << " " << rsErrnoName(terr) << std::endl;
|
||||||
|
print_stacktrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // def RS_THREAD_FORCE_STOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
#include "util/rsmemory.h"
|
#include "util/rsmemory.h"
|
||||||
#include "util/rsdeprecate.h"
|
#include "util/rsdeprecate.h"
|
||||||
|
|
||||||
|
#ifdef RS_THREAD_FORCE_STOP
|
||||||
|
# include "util/rstime.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
//#define RSMUTEX_DEBUG
|
//#define RSMUTEX_DEBUG
|
||||||
|
|
||||||
@ -249,6 +252,13 @@ protected:
|
|||||||
* of this method, @see JsonApiServer for an usage example. */
|
* of this method, @see JsonApiServer for an usage example. */
|
||||||
virtual void onStopRequested() {}
|
virtual void onStopRequested() {}
|
||||||
|
|
||||||
|
#ifdef RS_THREAD_FORCE_STOP
|
||||||
|
/** Set last resort timeout to forcefully kill thread if it didn't stop
|
||||||
|
* nicely, one should never use this, still we needed to introduce this
|
||||||
|
* to investigate some bugs in external libraries */
|
||||||
|
void setStopTimeout(rstime_t timeout) { mStopTimeout = timeout; }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Call @see run() setting the appropriate flags around it*/
|
/** Call @see run() setting the appropriate flags around it*/
|
||||||
void wrapRun();
|
void wrapRun();
|
||||||
@ -277,6 +287,11 @@ private:
|
|||||||
* and that might happens concurrently (or just before) a debug message
|
* and that might happens concurrently (or just before) a debug message
|
||||||
* being printed, thus causing the debug message to print a mangled value.*/
|
* being printed, thus causing the debug message to print a mangled value.*/
|
||||||
pthread_t mLastTid;
|
pthread_t mLastTid;
|
||||||
|
|
||||||
|
#ifdef RS_THREAD_FORCE_STOP
|
||||||
|
/// @see setStopTimeout
|
||||||
|
rstime_t mStopTimeout;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "retroshare/rsfiles.h"
|
||||||
#include "TransferUserNotify.h"
|
#include "TransferUserNotify.h"
|
||||||
#include "gui/notifyqt.h"
|
#include "gui/notifyqt.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
@ -27,7 +28,7 @@ TransferUserNotify::TransferUserNotify(QObject *parent) :
|
|||||||
{
|
{
|
||||||
newTransferCount = 0;
|
newTransferCount = 0;
|
||||||
|
|
||||||
connect(NotifyQt::getInstance(), SIGNAL(downloadCompleteCountChanged(int)), this, SLOT(downloadCountChanged(int)));
|
// connect(NotifyQt::getInstance(), SIGNAL(downloadCompleteCountChanged(int)), this, SLOT(downloadCountChanged(int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TransferUserNotify::hasSetting(QString *name, QString *group)
|
bool TransferUserNotify::hasSetting(QString *name, QString *group)
|
||||||
@ -50,7 +51,17 @@ QIcon TransferUserNotify::getMainIcon(bool hasNew)
|
|||||||
|
|
||||||
unsigned int TransferUserNotify::getNewCount()
|
unsigned int TransferUserNotify::getNewCount()
|
||||||
{
|
{
|
||||||
return newTransferCount;
|
std::list<RsFileHash> hashs;
|
||||||
|
rsFiles->FileDownloads(hashs);
|
||||||
|
FileInfo info;
|
||||||
|
|
||||||
|
newTransferCount = 0;
|
||||||
|
|
||||||
|
for(auto hash: hashs)
|
||||||
|
if(rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info) && info.downloadStatus==FT_STATE_COMPLETE)
|
||||||
|
++newTransferCount;
|
||||||
|
|
||||||
|
return newTransferCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TransferUserNotify::getTrayMessage(bool plural)
|
QString TransferUserNotify::getTrayMessage(bool plural)
|
||||||
@ -68,8 +79,3 @@ void TransferUserNotify::iconClicked()
|
|||||||
MainWindow::showWindow(MainWindow::Transfers);
|
MainWindow::showWindow(MainWindow::Transfers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferUserNotify::downloadCountChanged(int count)
|
|
||||||
{
|
|
||||||
newTransferCount = count;
|
|
||||||
updateIcon();
|
|
||||||
}
|
|
||||||
|
@ -32,9 +32,6 @@ public:
|
|||||||
|
|
||||||
virtual bool hasSetting(QString *name, QString *group);
|
virtual bool hasSetting(QString *name, QString *group);
|
||||||
|
|
||||||
private slots:
|
|
||||||
void downloadCountChanged(int count);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual QIcon getIcon();
|
virtual QIcon getIcon();
|
||||||
virtual QIcon getMainIcon(bool hasNew);
|
virtual QIcon getMainIcon(bool hasNew);
|
||||||
|
@ -1091,10 +1091,34 @@ TransfersDialog::TransfersDialog(QWidget *parent)
|
|||||||
|
|
||||||
|
|
||||||
registerHelpButton(ui.helpButton,help_str,"TransfersDialog") ;
|
registerHelpButton(ui.helpButton,help_str,"TransfersDialog") ;
|
||||||
|
|
||||||
|
mEventHandlerId=0;
|
||||||
|
rsEvents->registerEventsHandler(RsEventType::FILE_TRANSFER, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransfersDialog::handleEvent(std::shared_ptr<const RsEvent> event)
|
||||||
|
{
|
||||||
|
if(event->mType != RsEventType::FILE_TRANSFER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const RsFileTransferEvent *fe = dynamic_cast<const RsFileTransferEvent*>(event.get());
|
||||||
|
if(!fe)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (fe->mFileTransferEventCode)
|
||||||
|
{
|
||||||
|
case RsFileTransferEventCode::DOWNLOAD_COMPLETE:
|
||||||
|
case RsFileTransferEventCode::COMPLETED_FILES_REMOVED:
|
||||||
|
getUserNotify()->updateIcon();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TransfersDialog::~TransfersDialog()
|
TransfersDialog::~TransfersDialog()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
|
|
||||||
// save settings
|
// save settings
|
||||||
processSettings(false);
|
processSettings(false);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <retroshare/rstypes.h>
|
#include <retroshare/rstypes.h>
|
||||||
|
#include <retroshare/rsevents.h>
|
||||||
#include "RsAutoUpdatePage.h"
|
#include "RsAutoUpdatePage.h"
|
||||||
|
|
||||||
#include "ui_TransfersDialog.h"
|
#include "ui_TransfersDialog.h"
|
||||||
@ -259,6 +260,7 @@ private:
|
|||||||
bool controlTransferFile(uint32_t flags);
|
bool controlTransferFile(uint32_t flags);
|
||||||
void changePriority(int priority);
|
void changePriority(int priority);
|
||||||
void setChunkStrategy(FileChunksInfo::ChunkStrategy s) ;
|
void setChunkStrategy(FileChunksInfo::ChunkStrategy s) ;
|
||||||
|
void handleEvent(std::shared_ptr<const RsEvent> event);
|
||||||
|
|
||||||
QTreeView *downloadList;
|
QTreeView *downloadList;
|
||||||
|
|
||||||
@ -273,6 +275,7 @@ private:
|
|||||||
/** Qt Designer generated object */
|
/** Qt Designer generated object */
|
||||||
Ui::TransfersDialog ui;
|
Ui::TransfersDialog ui;
|
||||||
|
|
||||||
|
RsEventsHandlerId_t mEventHandlerId;
|
||||||
public slots:
|
public slots:
|
||||||
// these four functions add entries to the transfers dialog, and return the row id of the entry modified/added
|
// these four functions add entries to the transfers dialog, and return the row id of the entry modified/added
|
||||||
// int addDLItem(int row, const FileInfo &fileInfo);
|
// int addDLItem(int row, const FileInfo &fileInfo);
|
||||||
|
@ -1377,6 +1377,9 @@ void IdDialog::circle_selected()
|
|||||||
|
|
||||||
IdDialog::~IdDialog()
|
IdDialog::~IdDialog()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId_identity);
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId_circles);
|
||||||
|
|
||||||
// save settings
|
// save settings
|
||||||
processSettings(false);
|
processSettings(false);
|
||||||
|
|
||||||
@ -2057,9 +2060,11 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
|||||||
return tr("Admin signature verification in service %1").arg(service_name);
|
return tr("Admin signature verification in service %1").arg(service_name);
|
||||||
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION: // not typically used, since most services do not require group author signatures
|
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION: // not typically used, since most services do not require group author signatures
|
||||||
return tr("Creation of author signature in service %1").arg(service_name);
|
return tr("Creation of author signature in service %1").arg(service_name);
|
||||||
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION:
|
|
||||||
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION: // most common use case. Messages are signed by authors in e.g. forums.
|
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION: // most common use case. Messages are signed by authors in e.g. forums.
|
||||||
|
return tr("Message signature creation in group %1 of service %2").arg(QString::fromStdString(u.mGrpId.toStdString())).arg(service_name);
|
||||||
case RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand.
|
case RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand.
|
||||||
|
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION:
|
||||||
|
return tr("Group author for group %1 in service %2").arg(QString::fromStdString(u.mGrpId.toStdString())).arg(service_name);
|
||||||
break ;
|
break ;
|
||||||
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION:
|
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION:
|
||||||
case RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand.
|
case RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand.
|
||||||
@ -2103,18 +2108,9 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
|||||||
{
|
{
|
||||||
return tr("Generic signature.");
|
return tr("Generic signature.");
|
||||||
}
|
}
|
||||||
case RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION:
|
case RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION: return tr("Generic encryption.");
|
||||||
{
|
case RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION: return tr("Generic decryption.");
|
||||||
return tr("Generic encryption.");
|
case RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK: return tr("Membership verification in circle %1.").arg(QString::fromStdString(u.mGrpId.toStdString()));
|
||||||
}
|
|
||||||
case RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION:
|
|
||||||
{
|
|
||||||
return tr("Generic decryption.");
|
|
||||||
}
|
|
||||||
case RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK:
|
|
||||||
{
|
|
||||||
return tr("Membership verification in circle %1.").arg(QString::fromStdString(u.mGrpId.toStdString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#warning TODO! csoler 2017-01-03: Add the different strings and translations here.
|
#warning TODO! csoler 2017-01-03: Add the different strings and translations here.
|
||||||
default:
|
default:
|
||||||
|
@ -83,6 +83,7 @@ void PostedDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
|
|||||||
|
|
||||||
PostedDialog::~PostedDialog()
|
PostedDialog::~PostedDialog()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserNotify *PostedDialog::createUserNotify(QObject *parent)
|
UserNotify *PostedDialog::createUserNotify(QObject *parent)
|
||||||
|
@ -266,6 +266,7 @@ void NewFriendList::handleEvent(std::shared_ptr<const RsEvent> e)
|
|||||||
|
|
||||||
NewFriendList::~NewFriendList()
|
NewFriendList::~NewFriendList()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +155,6 @@ private:
|
|||||||
|
|
||||||
void initUi();
|
void initUi();
|
||||||
|
|
||||||
void updateSearchResults();
|
|
||||||
|
|
||||||
void openGroupInNewTab(const RsGxsGroupId &groupId);
|
void openGroupInNewTab(const RsGxsGroupId &groupId);
|
||||||
void groupSubscribe(bool subscribe);
|
void groupSubscribe(bool subscribe);
|
||||||
|
|
||||||
@ -185,6 +183,8 @@ private:
|
|||||||
// void loadGroupSummary_CurrentGroup(const uint32_t &token);
|
// void loadGroupSummary_CurrentGroup(const uint32_t &token);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void updateSearchResults();
|
||||||
|
|
||||||
bool mCountChildMsgs; // Count unread child messages?
|
bool mCountChildMsgs; // Count unread child messages?
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -42,11 +42,6 @@ void RsGxsUpdateBroadcastPage::setUpdateWhenInvisible(bool update)
|
|||||||
mBase->setUpdateWhenInvisible(update);
|
mBase->setUpdateWhenInvisible(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<TurtleRequestId>& RsGxsUpdateBroadcastPage::getSearchResults()
|
|
||||||
{
|
|
||||||
return mBase->getSearchResults();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::set<RsGxsGroupId> &RsGxsUpdateBroadcastPage::getGrpIdsMeta()
|
const std::set<RsGxsGroupId> &RsGxsUpdateBroadcastPage::getGrpIdsMeta()
|
||||||
{
|
{
|
||||||
return mBase->getGrpIdsMeta();
|
return mBase->getGrpIdsMeta();
|
||||||
|
@ -51,7 +51,8 @@ public:
|
|||||||
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIds();
|
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIds();
|
||||||
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIdsMeta();
|
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIdsMeta();
|
||||||
void getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds);
|
void getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds);
|
||||||
const std::set<TurtleRequestId>& getSearchResults();
|
|
||||||
|
virtual const std::set<TurtleRequestId> getSearchResults() const { return std::set<TurtleRequestId>(); } // overload this for subclasses that provide distant search
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void showEvent(QShowEvent *event);
|
virtual void showEvent(QShowEvent *event);
|
||||||
|
@ -76,6 +76,11 @@ void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> ev
|
|||||||
updateMessageSummaryList(e->mChannelGroupId);
|
updateMessageSummaryList(e->mChannelGroupId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RsChannelEventCode::RECEIVED_DISTANT_SEARCH_RESULT:
|
||||||
|
mSearchResults.insert(e->mDistantSearchRequestId);
|
||||||
|
updateSearchResults();
|
||||||
|
break;
|
||||||
|
|
||||||
case RsChannelEventCode::NEW_CHANNEL: // [[fallthrough]];
|
case RsChannelEventCode::NEW_CHANNEL: // [[fallthrough]];
|
||||||
case RsChannelEventCode::SUBSCRIBE_STATUS_CHANGED:
|
case RsChannelEventCode::SUBSCRIBE_STATUS_CHANGED:
|
||||||
updateDisplay(true);
|
updateDisplay(true);
|
||||||
@ -88,6 +93,7 @@ void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> ev
|
|||||||
|
|
||||||
GxsChannelDialog::~GxsChannelDialog()
|
GxsChannelDialog::~GxsChannelDialog()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GxsChannelDialog::getHelpString() const
|
QString GxsChannelDialog::getHelpString() const
|
||||||
|
@ -48,6 +48,7 @@ protected:
|
|||||||
virtual QString getHelpString() const ;
|
virtual QString getHelpString() const ;
|
||||||
virtual void groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, GroupItemInfo &groupItemInfo, const RsUserdata *userdata);
|
virtual void groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, GroupItemInfo &groupItemInfo, const RsUserdata *userdata);
|
||||||
virtual bool getDistantSearchResults(TurtleRequestId id, std::map<RsGxsGroupId,RsGxsGroupSummary>& group_infos);
|
virtual bool getDistantSearchResults(TurtleRequestId id, std::map<RsGxsGroupId,RsGxsGroupSummary>& group_infos);
|
||||||
|
virtual const std::set<TurtleRequestId> getSearchResults() const override { return mSearchResults ; }
|
||||||
|
|
||||||
virtual TurtleRequestId distantSearch(const QString& search_string) ;
|
virtual TurtleRequestId distantSearch(const QString& search_string) ;
|
||||||
virtual void checkRequestGroup(const RsGxsGroupId& grpId) ;
|
virtual void checkRequestGroup(const RsGxsGroupId& grpId) ;
|
||||||
@ -76,6 +77,8 @@ private:
|
|||||||
|
|
||||||
void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
|
void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
|
||||||
|
|
||||||
|
std::set<TurtleRequestId> mSearchResults;
|
||||||
|
|
||||||
RsEventsHandlerId_t mEventHandlerId;
|
RsEventsHandlerId_t mEventHandlerId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@ void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEven
|
|||||||
|
|
||||||
GxsChannelPostsWidget::~GxsChannelPostsWidget()
|
GxsChannelPostsWidget::~GxsChannelPostsWidget()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
// save settings
|
// save settings
|
||||||
processSettings(false);
|
processSettings(false);
|
||||||
|
|
||||||
|
@ -490,6 +490,7 @@ void GxsForumThreadWidget::blank()
|
|||||||
|
|
||||||
GxsForumThreadWidget::~GxsForumThreadWidget()
|
GxsForumThreadWidget::~GxsForumThreadWidget()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
// save settings
|
// save settings
|
||||||
processSettings(false);
|
processSettings(false);
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ void GxsForumsDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> eve
|
|||||||
|
|
||||||
GxsForumsDialog::~GxsForumsDialog()
|
GxsForumsDialog::~GxsForumsDialog()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GxsForumsDialog::getHelpString() const
|
QString GxsForumsDialog::getHelpString() const
|
||||||
|
@ -349,6 +349,7 @@ void NotifyQt::notifyDiscInfoChanged()
|
|||||||
emit discInfoChanged() ;
|
emit discInfoChanged() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TO_REMOVE
|
||||||
void NotifyQt::notifyDownloadComplete(const std::string& fileHash)
|
void NotifyQt::notifyDownloadComplete(const std::string& fileHash)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -376,6 +377,7 @@ void NotifyQt::notifyDownloadCompleteCount(uint32_t count)
|
|||||||
|
|
||||||
emit downloadCompleteCountChanged(count);
|
emit downloadCompleteCountChanged(count);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void NotifyQt::notifyDiskFull(uint32_t loc,uint32_t size_in_mb)
|
void NotifyQt::notifyDiskFull(uint32_t loc,uint32_t size_in_mb)
|
||||||
{
|
{
|
||||||
@ -582,6 +584,7 @@ void NotifyQt::notifyTurtleSearchResult(const RsPeerId& pid,uint32_t search_id,c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TO_REMOVE
|
||||||
void NotifyQt::notifyHashingInfo(uint32_t type, const std::string& fileinfo)
|
void NotifyQt::notifyHashingInfo(uint32_t type, const std::string& fileinfo)
|
||||||
{
|
{
|
||||||
QString info;
|
QString info;
|
||||||
@ -608,6 +611,7 @@ void NotifyQt::notifyHashingInfo(uint32_t type, const std::string& fileinfo)
|
|||||||
|
|
||||||
emit hashingInfoChanged(info);
|
emit hashingInfoChanged(info);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void NotifyQt::notifyHistoryChanged(uint32_t msgId, int type)
|
void NotifyQt::notifyHistoryChanged(uint32_t msgId, int type)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,9 @@ class NotifyQt: public QObject, public NotifyClient
|
|||||||
virtual void notifyChatStatus(const ChatId &chat_id,const std::string& status_string);
|
virtual void notifyChatStatus(const ChatId &chat_id,const std::string& status_string);
|
||||||
virtual void notifyChatCleared(const ChatId &chat_id);
|
virtual void notifyChatCleared(const ChatId &chat_id);
|
||||||
virtual void notifyCustomState(const std::string& peer_id, const std::string& status_string);
|
virtual void notifyCustomState(const std::string& peer_id, const std::string& status_string);
|
||||||
|
#ifdef TO_REMOVE
|
||||||
virtual void notifyHashingInfo(uint32_t type, const std::string& fileinfo);
|
virtual void notifyHashingInfo(uint32_t type, const std::string& fileinfo);
|
||||||
|
#endif
|
||||||
virtual void notifyTurtleSearchResult(const RsPeerId &pid, uint32_t search_id, const std::list<TurtleFileInfo>& found_files);
|
virtual void notifyTurtleSearchResult(const RsPeerId &pid, uint32_t search_id, const std::list<TurtleFileInfo>& found_files);
|
||||||
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleGxsInfo>& found_groups);
|
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleGxsInfo>& found_groups);
|
||||||
virtual void notifyPeerHasNewAvatar(std::string peer_id) ;
|
virtual void notifyPeerHasNewAvatar(std::string peer_id) ;
|
||||||
@ -85,8 +87,10 @@ class NotifyQt: public QObject, public NotifyClient
|
|||||||
virtual void notifyHistoryChanged(uint32_t msgId, int type);
|
virtual void notifyHistoryChanged(uint32_t msgId, int type);
|
||||||
|
|
||||||
virtual void notifyDiscInfoChanged() ;
|
virtual void notifyDiscInfoChanged() ;
|
||||||
|
#ifdef TO_REMOVE
|
||||||
virtual void notifyDownloadComplete(const std::string& fileHash);
|
virtual void notifyDownloadComplete(const std::string& fileHash);
|
||||||
virtual void notifyDownloadCompleteCount(uint32_t count);
|
virtual void notifyDownloadCompleteCount(uint32_t count);
|
||||||
|
#endif
|
||||||
virtual bool askForPassword(const std::string& title, const std::string& key_details, bool prev_is_bad, std::string& password, bool &cancelled);
|
virtual bool askForPassword(const std::string& title, const std::string& key_details, bool prev_is_bad, std::string& password, bool &cancelled);
|
||||||
virtual bool askForPluginConfirmation(const std::string& plugin_filename, const std::string& plugin_file_hash,bool first_time);
|
virtual bool askForPluginConfirmation(const std::string& plugin_filename, const std::string& plugin_file_hash,bool first_time);
|
||||||
|
|
||||||
@ -153,8 +157,6 @@ class NotifyQt: public QObject, public NotifyClient
|
|||||||
void chatMessageReceived(ChatMessage msg);
|
void chatMessageReceived(ChatMessage msg);
|
||||||
void groupsChanged(int type) const ;
|
void groupsChanged(int type) const ;
|
||||||
void discInfoChanged() const ;
|
void discInfoChanged() const ;
|
||||||
void downloadComplete(const QString& /* fileHash */);
|
|
||||||
void downloadCompleteCountChanged(int /* count */);
|
|
||||||
#ifdef REMOVE
|
#ifdef REMOVE
|
||||||
void forumMsgReadSatusChanged(const QString& forumId, const QString& msgId, int status);
|
void forumMsgReadSatusChanged(const QString& forumId, const QString& msgId, int status);
|
||||||
void channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status);
|
void channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status);
|
||||||
|
@ -112,28 +112,41 @@ QString JsonApiPage::helpText() const { return ""; }
|
|||||||
|
|
||||||
bool JsonApiPage::checkStartJsonApi()
|
bool JsonApiPage::checkStartJsonApi()
|
||||||
{
|
{
|
||||||
if(!Settings->getJsonApiEnabled())
|
if(!Settings->getJsonApiEnabled()) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
rsJsonApi->setListeningPort(Settings->getJsonApiPort());
|
rsJsonApi->setListeningPort(Settings->getJsonApiPort());
|
||||||
rsJsonApi->setBindingAddress(Settings->getJsonApiListenAddress().toStdString());
|
rsJsonApi->setBindingAddress(Settings->getJsonApiListenAddress().toStdString());
|
||||||
rsJsonApi->restart();
|
|
||||||
|
const auto rErr = rsJsonApi->restart();
|
||||||
|
if(rErr == RsJsonApiErrorNum::NOT_A_MACHINE_GUN)
|
||||||
|
{
|
||||||
|
RsDbg() << __PRETTY_FUNCTION__ << " apparently the user is attempting "
|
||||||
|
<< "to restart JSON API service in a burst. Re-scheduling "
|
||||||
|
<< "restart in a while..." << std::endl;
|
||||||
|
RsThread::async([]()
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||||
|
rsJsonApi->restart();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if(rErr)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << rErr << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void JsonApiPage::checkShutdownJsonApi()
|
/*static*/ void JsonApiPage::checkShutdownJsonApi()
|
||||||
{
|
{
|
||||||
if(!rsJsonApi->isRunning()) return;
|
|
||||||
rsJsonApi->fullstop(); // this is a blocks until the thread is terminated.
|
rsJsonApi->fullstop(); // this is a blocks until the thread is terminated.
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonApiPage::onApplyClicked()
|
void JsonApiPage::onApplyClicked()
|
||||||
{
|
{
|
||||||
// restart
|
// restart
|
||||||
|
checkStartJsonApi();
|
||||||
checkShutdownJsonApi();
|
|
||||||
checkStartJsonApi();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonApiPage::checkToken(QString s)
|
void JsonApiPage::checkToken(QString s)
|
||||||
|
@ -52,11 +52,42 @@ HashingStatus::HashingStatus(QWidget *parent)
|
|||||||
hashloader->hide();
|
hashloader->hide();
|
||||||
statusHashing->hide();
|
statusHashing->hide();
|
||||||
|
|
||||||
connect(NotifyQt::getInstance(), SIGNAL(hashingInfoChanged(const QString&)), SLOT(updateHashingInfo(const QString&)));
|
mEventHandlerId=0;
|
||||||
|
rsEvents->registerEventsHandler(RsEventType::SHARED_DIRECTORIES, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HashingStatus::handleEvent(std::shared_ptr<const RsEvent> event)
|
||||||
|
{
|
||||||
|
if(event->mType != RsEventType::SHARED_DIRECTORIES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const RsSharedDirectoriesEvent *fe = dynamic_cast<const RsSharedDirectoriesEvent*>(event.get());
|
||||||
|
if(!fe)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString info;
|
||||||
|
|
||||||
|
switch (fe->mEventCode)
|
||||||
|
{
|
||||||
|
case RsSharedDirectoriesEventCode::STARTING_DIRECTORY_SWEEP:
|
||||||
|
info = tr("Examining shared files...");
|
||||||
|
break;
|
||||||
|
case RsSharedDirectoriesEventCode::DIRECTORY_SWEEP_ENDED:
|
||||||
|
break;
|
||||||
|
case RsSharedDirectoriesEventCode::HASHING_FILE:
|
||||||
|
info = tr("Hashing file") + " " + QString::fromUtf8(fe->mMessage.c_str());
|
||||||
|
break;
|
||||||
|
case RsSharedDirectoriesEventCode::SAVING_FILE_INDEX:
|
||||||
|
info = tr("Saving file index...");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHashingInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashingStatus::~HashingStatus()
|
HashingStatus::~HashingStatus()
|
||||||
{
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
delete(movie);
|
delete(movie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define HASHINGSTATUS_H
|
#define HASHINGSTATUS_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include "retroshare/rsevents.h"
|
||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class ElidedLabel;
|
class ElidedLabel;
|
||||||
@ -37,15 +38,16 @@ public:
|
|||||||
void setCompactMode(bool compact) {_compactMode = compact; }
|
void setCompactMode(bool compact) {_compactMode = compact; }
|
||||||
void mousePressEvent(QMouseEvent *);
|
void mousePressEvent(QMouseEvent *);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void updateHashingInfo(const QString&) ;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateHashingInfo(const QString& s);
|
||||||
|
void handleEvent(std::shared_ptr<const RsEvent> event);
|
||||||
|
|
||||||
ElidedLabel *statusHashing;
|
ElidedLabel *statusHashing;
|
||||||
QLabel *hashloader;
|
QLabel *hashloader;
|
||||||
QString mLastText ;
|
QString mLastText ;
|
||||||
QMovie *movie;
|
QMovie *movie;
|
||||||
bool _compactMode;
|
bool _compactMode;
|
||||||
|
RsEventsHandlerId_t mEventHandlerId;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +45,11 @@ RsGxsUpdateBroadcast::RsGxsUpdateBroadcast(RsGxsIfaceHelper *ifaceImpl) :
|
|||||||
}, mEventHandlerId );
|
}, mEventHandlerId );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsGxsUpdateBroadcast::~RsGxsUpdateBroadcast()
|
||||||
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
|
}
|
||||||
|
|
||||||
void RsGxsUpdateBroadcast::cleanup()
|
void RsGxsUpdateBroadcast::cleanup()
|
||||||
{
|
{
|
||||||
QMap<RsGxsIfaceHelper*, RsGxsUpdateBroadcast*>::iterator it;
|
QMap<RsGxsIfaceHelper*, RsGxsUpdateBroadcast*>::iterator it;
|
||||||
|
@ -40,6 +40,9 @@ public:
|
|||||||
|
|
||||||
static RsGxsUpdateBroadcast *get(RsGxsIfaceHelper* ifaceImpl);
|
static RsGxsUpdateBroadcast *get(RsGxsIfaceHelper* ifaceImpl);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~RsGxsUpdateBroadcast();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void changed();
|
void changed();
|
||||||
void msgsChanged(const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIds, const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIdsMeta);
|
void msgsChanged(const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIds, const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIdsMeta);
|
||||||
|
Loading…
Reference in New Issue
Block a user