Merge pull request #1520 from G10h4ck/broadcast_discovery

Broadcast Domain friends IP:Port Discovery
This commit is contained in:
G10h4ck 2019-04-23 17:18:54 +02:00 committed by GitHub
commit 9a7ce1ae72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1118 additions and 108 deletions

4
.gitmodules vendored
View File

@ -7,3 +7,7 @@
[submodule "build_scripts/OBS"]
path = build_scripts/OBS
url = https://github.com/RetroShare/OBS.git
[submodule "supportlibs/udp-discovery-cpp"]
path = supportlibs/udp-discovery-cpp
url = https://github.com/truvorskameikin/udp-discovery-cpp.git
branch = develop

View File

@ -47,8 +47,9 @@ addons:
branch_pattern: coverity_scan
before_script:
- if [ $TRAVIS_OS_NAME == linux ]; then qmake QMAKE_CC=$CC QMAKE_CXX=$CXX; fi
- if [ $TRAVIS_OS_NAME == osx ]; then qmake QMAKE_CC=$CC QMAKE_CXX=$CXX CONFIG+=rs_macos10.14 CONFIG+=no_retroshare_plugins INCLUDEPATH+=/usr/local/opt/openssl/include/ INCLUDEPATH+=/usr/local/Cellar/sqlcipher/4.0.1/include INCLUDEPATH+=/usr/local/Cellar/libmicrohttpd/0.9.62_1/include QMAKE_LIBDIR+=/usr/local/opt/openssl/lib/ QMAKE_LIBDIR+=/usr/local/Cellar/libmicrohttpd/0.9.62_1/lib QMAKE_LIBDIR+=/usr/local/Cellar/sqlcipher/4.0.1/lib; fi
- env
- if [ $TRAVIS_OS_NAME == linux ]; then qmake; fi
- if [ $TRAVIS_OS_NAME == osx ]; then qmake CONFIG+=rs_macos10.14 INCLUDEPATH+=/usr/local/opt/openssl/include/ INCLUDEPATH+=/usr/local/Cellar/sqlcipher/4.0.1/include INCLUDEPATH+=/usr/local/Cellar/libmicrohttpd/0.9.62_1/include QMAKE_LIBDIR+=/usr/local/opt/openssl/lib/ QMAKE_LIBDIR+=/usr/local/Cellar/libmicrohttpd/0.9.62_1/lib QMAKE_LIBDIR+=/usr/local/Cellar/sqlcipher/4.0.1/lib; fi
script:
- if [ $TRAVIS_OS_NAME == osx ] && [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make -j4; fi

View File

@ -136,6 +136,7 @@ before_package:
# to run your custom scripts instead of automatic MSBuild
build_script:
- env
- qmake -Wall -spec win32-g++ "CONFIG=debug"
- mingw32-make -j3

View File

@ -40,6 +40,9 @@ define_default_value QT_ANDROID_INSTALLER_SHA256 a214084e2295c9a9f8727e8a0131c37
define_default_value RESTBED_SOURCE_VERSION "4.6"
define_default_value UDP_DISCOVERY_CPP_SOURCE "https://github.com/truvorskameikin/udp-discovery-cpp.git"
define_default_value UDP_DISCOVERY_CPP_VERSION "develop"
define_default_value XAPIAN_SOURCE_VERSION "1.4.7"
define_default_value XAPIAN_SOURCE_SHA256 13f08a0b649c7afa804fa0e85678d693fd6069dd394c9b9e7d41973d74a3b5d3
@ -203,7 +206,7 @@ build_bzlib()
rm -rf $B_dir
verified_download $B_dir.tar.gz $BZIP2_SOURCE_SHA256 \
http://trumpetti.atm.tut.fi/gentoo/distfiles/bzip2-${BZIP2_SOURCE_VERSION}.tar.gz
http://distfiles.gentoo.org/distfiles/bzip2-${BZIP2_SOURCE_VERSION}.tar.gz
tar -xf $B_dir.tar.gz
cd $B_dir
@ -342,6 +345,23 @@ build_restbed()
cd ..
}
build_udp-discovery-cpp()
{
S_dir="udp-discovery-cpp"
[ -d $S_dir ] || git clone $UDP_DISCOVERY_CPP_SOURCE $S_dir
cd $S_dir
git checkout $UDP_DISCOVERY_CPP_VERSION
cd ..
B_dir="udp-discovery-cpp-build"
rm -rf ${B_dir}; mkdir ${B_dir}; cd ${B_dir}
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -H../udp-discovery-cpp
make -j${HOST_NUM_CPU}
cp libudp-discovery.a "${PREFIX}/lib/"
cp ../$S_dir/*.hpp "${PREFIX}/include/"
cd ..
}
build_xapian()
{
B_dir="xapian-core-${XAPIAN_SOURCE_VERSION}"
@ -372,6 +392,7 @@ build_sqlcipher
build_libupnp
build_rapidjson
build_restbed
build_udp-discovery-cpp
build_xapian
delete_copied_includes

View File

@ -7,6 +7,10 @@ Files: openpgpsdk/*
Copyright: 2005-2008 Ben Laurie, Rachel Willmer, Retroshare Team <retroshare.team@gmail.com>
License: Apache-2.0
Files: jsonapi-generator/* libretroshare/src/jsonapi/*
Copyright: 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org>
License: AGPL-3+
Files: libretroshare/*
Copyright: 2007-2018, Retroshare Team <retroshare.team@gmail.com>
License: LGPL-3+

View File

@ -1,20 +1,22 @@
/*
* RetroShare JSON API
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* RetroShare JSON API *
* *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* 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/>. *
* *
*******************************************************************************/
registerHandler("$%apiPath%$",
[$%captureVars%$](const std::shared_ptr<rb::Session> session)
@ -41,8 +43,12 @@ $%paramsDeclaration%$
$%inputParamsDeserialization%$
$%callbackName%$ = [session]($%callbackParams%$)
const std::weak_ptr<rb::Session> weakSession(session);
$%callbackName%$ = [weakSession]($%callbackParams%$)
{
auto session = weakSession.lock();
if(!session || session->is_closed()) return;
$%callbackParamsSerialization%$
std::stringstream message;

View File

@ -1,20 +1,22 @@
/*
* RetroShare JSON API
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* RetroShare JSON API *
* *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* 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/>. *
* *
*******************************************************************************/
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>

View File

@ -1,20 +1,22 @@
/*
* RetroShare JSON API
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* RetroShare JSON API *
* *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* 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/>. *
* *
*******************************************************************************/
registerHandler("$%apiPath%$",
[$%captureVars%$](const std::shared_ptr<rb::Session> session)

View File

@ -1,20 +1,19 @@
/*******************************************************************************
* libretroshare/src/gxs: jsonapi.cpp *
* *
* RetroShare JSON API *
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser 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/>. *
* *
*******************************************************************************/
@ -38,6 +37,7 @@
#include "retroshare/rsinit.h"
#include "util/rsurl.h"
#include "util/rstime.h"
#include "retroshare/rsevents.h"
// Generated at compile time
#include "jsonapi-includes.inl"
@ -96,7 +96,7 @@ JsonApiServer::corsOptionsHeaders =
/*static*/ bool JsonApiServer::checkRsServicePtrReady(
void* serviceInstance, const std::string& serviceName,
const void* serviceInstance, const std::string& serviceName,
RsGenericSerializer::SerializeContext& ctx,
const std::shared_ptr<restbed::Session> session)
{
@ -279,6 +279,64 @@ JsonApiServer::JsonApiServer(uint16_t port, const std::string& bindAddress,
} );
}, true);
registerHandler("/rsEvents/registerEventsHandler",
[this](const std::shared_ptr<rb::Session> session)
{
const std::multimap<std::string, std::string> headers
{
{ "Connection", "keep-alive" },
{ "Content-Type", "text/event-stream" }
};
session->yield(rb::OK, headers);
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
session->fetch( reqSize, [this](
const std::shared_ptr<rb::Session> session,
const rb::Bytes& body )
{
INITIALIZE_API_CALL_JSON_CONTEXT;
if( !checkRsServicePtrReady(
rsEvents, "rsEvents", cAns, session ) )
return;
const std::weak_ptr<rb::Session> weakSession(session);
RsEventsHandlerId_t hId = rsEvents->generateUniqueHandlerId();
std::function<void(const RsEvent&)> multiCallback =
[weakSession, hId](const RsEvent& event)
{
auto session = weakSession.lock();
if(!session || session->is_closed())
{
if(rsEvents) rsEvents->unregisterEventsHandler(hId);
return;
}
RsGenericSerializer::SerializeContext ctx;
RsTypeSerializer::serial_process(
RsGenericSerializer::TO_JSON, ctx,
const_cast<RsEvent&>(event), "event" );
std::stringstream message;
message << "data: " << compactJSON << ctx.mJson << "\n\n";
session->yield(message.str());
};
bool retval = rsEvents->registerEventsHandler(multiCallback, hId);
{
RsGenericSerializer::SerializeContext& ctx(cAns);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
RS_SERIAL_PROCESS(retval);
}
// return them to the API caller
std::stringstream message;
message << "data: " << compactJSON << cAns.mJson << "\n\n";
session->yield(message.str());
} );
}, true);
// Generated at compile time
#include "jsonapi-wrappers.inl"
}

View File

@ -1,24 +1,22 @@
/*******************************************************************************
* libretroshare/src/gxs: jsonapi.h *
* *
* RetroShare JSON API *
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser 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/>. *
* *
*******************************************************************************/
#pragma once
#include <string>
@ -199,8 +197,18 @@ private:
static void handleCorsOptions(const std::shared_ptr<rb::Session> session);
static bool checkRsServicePtrReady(
void* serviceInstance, const std::string& serviceName,
const void* serviceInstance, const std::string& serviceName,
RsGenericSerializer::SerializeContext& ctx,
const std::shared_ptr<restbed::Session> session );
static inline bool checkRsServicePtrReady(
const std::shared_ptr<const void> serviceInstance,
const std::string& serviceName,
RsGenericSerializer::SerializeContext& ctx,
const std::shared_ptr<restbed::Session> session )
{
return checkRsServicePtrReady(
serviceInstance.get(), serviceName, ctx, session );
}
};

View File

@ -1,24 +1,22 @@
/*******************************************************************************
* libretroshare/src/gxs: jsonapiitems.h *
* *
* RetroShare JSON API *
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser 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/>. *
* *
*******************************************************************************/
#pragma once
#include <string>

View File

@ -134,6 +134,7 @@ SOURCES += tcponudp/udppeer.cc \
PUBLIC_HEADERS = retroshare/rsdisc.h \
retroshare/rsevents.h \
retroshare/rsexpr.h \
retroshare/rsfiles.h \
retroshare/rshistory.h \
@ -459,6 +460,7 @@ HEADERS += rsitems/rsitem.h \
rsitems/rsserviceinfoitems.h \
HEADERS += services/autoproxy/p3i2pbob.h \
services/rseventsservice.h \
services/autoproxy/rsautoproxymonitor.h \
services/p3msgservice.h \
services/p3service.h \
@ -609,6 +611,7 @@ SOURCES += serialiser/rsbaseserial.cc \
SOURCES += services/autoproxy/rsautoproxymonitor.cc \
services/rseventsservice.cc \
services/autoproxy/p3i2pbob.cc \
services/p3msgservice.cc \
services/p3service.cc \
@ -840,22 +843,26 @@ rs_jsonapi {
DUMMYRESTBEDINPUT = FORCE
CMAKE_GENERATOR_OVERRIDE=""
win32-g++:CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\""
genrestbedlib.name = Generating libresbed.
genrestbedlib.name = Generating librestbed.
genrestbedlib.input = DUMMYRESTBEDINPUT
genrestbedlib.output = $$clean_path($${RESTBED_BUILD_PATH}/librestbed.a)
genrestbedlib.CONFIG += target_predeps combine
genrestbedlib.variable_out = PRE_TARGETDEPS
genrestbedlib.commands = \
cd $${RS_SRC_PATH} && \
git submodule update --init --recommend-shallow supportlibs/restbed && \
cd $${RESTBED_SRC_PATH} && \
git submodule update --init --recommend-shallow dependency/asio && \
git submodule update --init --recommend-shallow dependency/catch && \
git submodule update --init --recommend-shallow dependency/kashmir && \
mkdir -p $${RESTBED_BUILD_PATH}; cd $${RESTBED_BUILD_PATH} && \
cmake -DCMAKE_CXX_COMPILER=$$QMAKE_CXX $${CMAKE_GENERATOR_OVERRIDE} -DBUILD_SSL=OFF \
-DCMAKE_INSTALL_PREFIX=. -B. -H$$shell_path($${RESTBED_SRC_PATH}) && \
make
cd $${RS_SRC_PATH} && ( \
git submodule update --init --recommend-shallow supportlibs/restbed ; \
cd $${RESTBED_SRC_PATH} ; \
git submodule update --init --recommend-shallow dependency/asio ; \
git submodule update --init --recommend-shallow dependency/catch ; \
git submodule update --init --recommend-shallow dependency/kashmir ; \
true ) && \
mkdir -p $${RESTBED_BUILD_PATH} && cd $${RESTBED_BUILD_PATH} && \
cmake -DCMAKE_C_COMPILER=$$fixQmakeCC($$QMAKE_CC) \
-DCMAKE_CXX_COMPILER=$$QMAKE_CXX \
$${CMAKE_GENERATOR_OVERRIDE} -DBUILD_SSL=OFF \
-DCMAKE_INSTALL_PREFIX=. -B. \
-H$$shell_path($${RESTBED_SRC_PATH}) && \
$(MAKE)
QMAKE_EXTRA_COMPILERS += genrestbedlib
RESTBED_HEADER_FILE=$$clean_path($${RESTBED_BUILD_PATH}/include/restbed)
@ -864,7 +871,7 @@ rs_jsonapi {
genrestbedheader.output = $${RESTBED_HEADER_FILE}
genrestbedheader.CONFIG += target_predeps combine no_link
genrestbedheader.variable_out = HEADERS
genrestbedheader.commands = cd $${RESTBED_BUILD_PATH} && make install
genrestbedheader.commands = cd $${RESTBED_BUILD_PATH} && $(MAKE) install
QMAKE_EXTRA_COMPILERS += genrestbedheader
}
@ -900,6 +907,37 @@ rs_deep_search {
HEADERS += deep_search/deep_search.h
}
rs_broadcast_discovery {
HEADERS += retroshare/rsbroadcastdiscovery.h \
services/broadcastdiscoveryservice.h
SOURCES += services/broadcastdiscoveryservice.cc
no_rs_cross_compiling {
DUMMYQMAKECOMPILERINPUT = FORCE
CMAKE_GENERATOR_OVERRIDE=""
win32-g++:CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\""
udpdiscoverycpplib.name = Generating libudp-discovery.a.
udpdiscoverycpplib.input = DUMMYQMAKECOMPILERINPUT
udpdiscoverycpplib.output = $$clean_path($${UDP_DISCOVERY_BUILD_PATH}/libudp-discovery.a)
udpdiscoverycpplib.CONFIG += target_predeps combine
udpdiscoverycpplib.variable_out = PRE_TARGETDEPS
udpdiscoverycpplib.commands = \
cd $${RS_SRC_PATH} && ( \
git submodule update --init --recommend-shallow supportlibs/udp-discovery-cpp || \
true ) && \
mkdir -p $${UDP_DISCOVERY_BUILD_PATH} && \
cd $${UDP_DISCOVERY_BUILD_PATH} && \
cmake -DCMAKE_C_COMPILER=$$fixQmakeCC($$QMAKE_CC) \
-DCMAKE_CXX_COMPILER=$$QMAKE_CXX \
$${CMAKE_GENERATOR_OVERRIDE} \
-DBUILD_EXAMPLE=OFF -DBUILD_TOOL=OFF \
-DCMAKE_INSTALL_PREFIX=. -B. \
-H$$shell_path($${UDP_DISCOVERY_SRC_PATH}) && \
$(MAKE)
QMAKE_EXTRA_COMPILERS += udpdiscoverycpplib
}
}
###########################################################################################################
# OLD CONFIG OPTIONS.
# Not used much - but might be useful one day.

View File

@ -0,0 +1,111 @@
/*******************************************************************************
* RetroShare Broadcast Domain Discovery *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <functional>
#include <memory>
#include <vector>
#include <string>
#include "retroshare/rsids.h"
#include "retroshare/rstypes.h"
#include "serialiser/rsserializable.h"
#include "util/rstime.h"
#include "util/rsurl.h"
#include "util/rsmemory.h"
#include "retroshare/rsevents.h"
class RsBroadcastDiscovery;
/**
* Pointer to global instance of RsBroadcastDiscovery service implementation
* @jsonapi{development}
*
* TODO: this should become std::weak_ptr once we have a reasonable services
* management.
*/
extern std::shared_ptr<RsBroadcastDiscovery> rsBroadcastDiscovery;
struct RsBroadcastDiscoveryResult : RsSerializable
{
PGPFingerprintType mPgpFingerprint;
RsPeerId mSslId;
std::string mProfileName;
RsUrl locator;
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx) override
{
RS_SERIAL_PROCESS(mPgpFingerprint);
RS_SERIAL_PROCESS(mSslId);
RS_SERIAL_PROCESS(mProfileName);
RS_SERIAL_PROCESS(locator);
}
RsBroadcastDiscoveryResult() = default;
RsBroadcastDiscoveryResult (const RsBroadcastDiscoveryResult&) = default;
~RsBroadcastDiscoveryResult() override;
};
/**
* @brief Event emitted when a non friend new peer is found in the local network
* @see RsEvents
*/
struct RsBroadcastDiscoveryPeerFoundEvent : RsEvent
{
RsBroadcastDiscoveryPeerFoundEvent(
const RsBroadcastDiscoveryResult& eventData ) :
RsEvent(RsEventType::BROADCAST_DISCOVERY_PEER_FOUND), mData(eventData) {}
RsBroadcastDiscoveryResult mData;
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx) override
{
RsEvent::serial_process(j, ctx);
RS_SERIAL_PROCESS(mData);
}
~RsBroadcastDiscoveryPeerFoundEvent() override;
};
/**
* Announce own RetroShare instace and look friends and peers in own broadcast
* domain (aka LAN).
* Emit event @see RsBroadcastDiscoveryPeerFoundEvent when a new peer (not
* friend yet) is found.
*/
class RsBroadcastDiscovery
{
public:
/**
* @brief Get potential peers that have been discovered up until now
* @jsonapi{development}
* @return vector containing discovered peers, may be empty.
*/
virtual std::vector<RsBroadcastDiscoveryResult> getDiscoveredPeers() = 0;
virtual ~RsBroadcastDiscovery();
};

View File

@ -0,0 +1,154 @@
/*******************************************************************************
* Retroshare events service *
* *
* libretroshare: retroshare core library *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <memory>
#include <cstdint>
#include "util/rsmemory.h"
#include "serialiser/rsserializable.h"
#include "serialiser/rstypeserializer.h"
class RsEvents;
/**
* Pointer to global instance of RsEvents service implementation
* @jsonapi{development}
*
* TODO: this should become std::weak_ptr once we have a reasonable services
* management.
*/
extern std::shared_ptr<RsEvents> rsEvents;
/**
* @brief Events types.
* When creating a new type of event, add a new type here and use that to
* initialize mType in the constructor of your derivative of @see RsEvent
*/
enum class RsEventType : uint32_t
{
NONE = 0, /// Used to detect uninitialized event
BROADCAST_DISCOVERY_PEER_FOUND = 1, /// @see RsBroadcastDiscovery
MAX /// Used to detect invalid event type passed
};
/**
* This struct is not meant to be used directly, you should create events type
* deriving from it.
*/
struct RsEvent : RsSerializable
{
protected:
RsEvent(RsEventType type) :
mType(type), mTimePoint(std::chrono::system_clock::now()) {}
RsEvent() = delete;
public:
RsEventType mType;
std::chrono::system_clock::time_point mTimePoint;
/**
* Derived types must call this method at beginning of their implementation
* of serial_process
* @see RsSerializable
*/
virtual void serial_process(RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx)
{
RS_SERIAL_PROCESS(mType);
rstime_t mTime = std::chrono::system_clock::to_time_t(mTimePoint);
RS_SERIAL_PROCESS(mTime);
mTimePoint = std::chrono::system_clock::from_time_t(mTime);
}
virtual ~RsEvent();
};
typedef uint32_t RsEventsHandlerId_t;
class RsEvents
{
public:
/**
* @brief Post event to the event queue.
* @param[in] event
* @param[out] errorMessage Optional storage for error messsage, meaningful
* only on failure.
* @return False on error, true otherwise.
*/
virtual bool postEvent(
std::unique_ptr<RsEvent> event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) = 0;
/**
* @brief Send event directly to handlers. Blocking API
* The handlers get exectuded on the caller thread, ensuring the function
* returns only after the event has been handled.
* @param[in] event
* @param[out] errorMessage Optional storage for error messsage, meaningful
* only on failure.
* @return False on error, true otherwise.
*/
virtual bool sendEvent(
const RsEvent& event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) = 0;
/**
* @brief Generate unique handler identifier
* @return generate Id
*/
virtual RsEventsHandlerId_t generateUniqueHandlerId() = 0;
/**
* @brief Register events handler
* Every time an event is dispatced the registered events handlers will get
* their method handleEvent called with the event passed as paramether.
* @jsonapi{development,manualwrapper}
* @param multiCallback Function that will be called each time an event
* is dispatched.
* @param[inout] hId Optional storage for handler id, useful to
* eventually unregister the handler later. The
* value may be provided to the function call but
* must habe been generated with
* @see generateUniqueHandlerId()
* @return False on error, true otherwise.
*/
virtual bool registerEventsHandler(
std::function<void(const RsEvent&)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
) = 0;
/**
* @brief Unregister event handler
* @param[in] hId Id of the event handler to unregister
* @return True if the handler id has been found, false otherwise.
*/
virtual bool unregisterEventsHandler(RsEventsHandlerId_t hId) = 0;
virtual ~RsEvents();
};

View File

@ -39,6 +39,9 @@ int rsserverzone = 101;
#include "util/rsdebug.h"
#include "retroshare/rsevents.h"
#include "services/rseventsservice.h"
/****
#define DEBUG_TICK 1
@ -81,6 +84,12 @@ RsServer::RsServer() :
coreMutex("RsServer"), mShutdownCallback([](int){}),
coreReady(false)
{
{
RsEventsService* tmpRsEvtPtr = new RsEventsService();
rsEvents.reset(tmpRsEvtPtr);
startServiceThread(tmpRsEvtPtr, "RsEventsService");
}
// This is needed asap.
//
mNotify = new p3Notify() ;

View File

@ -34,7 +34,7 @@
#ifdef __ANDROID__
# include <QFile> // To install bdboot.txt
# include <QString> // for String::fromStdString(...)
# include <QString> // for QString::fromStdString(...)
#endif
#include "util/argstream.h"
@ -98,6 +98,11 @@ RsDht *rsDht = NULL ;
# include "jsonapi/jsonapi.h"
#endif
#ifdef RS_BROADCAST_DISCOVERY
# include "retroshare/rsbroadcastdiscovery.h"
# include "services/broadcastdiscoveryservice.h"
#endif // def RS_BROADCAST_DISCOVERY
// #define GPG_DEBUG
// #define AUTHSSL_DEBUG
// #define FIM_DEBUG
@ -1454,6 +1459,12 @@ int RsServer::StartupRetroShare()
mHistoryMgr, *mGxsTrans );
mStatusSrv = new p3StatusService(serviceCtrl);
#ifdef RS_BROADCAST_DISCOVERY
rsBroadcastDiscovery.reset(new BroadcastDiscoveryService(*rsPeers));
BroadcastDiscoveryService& tBroadcastDiscoveryService =
static_cast<BroadcastDiscoveryService&>(*rsBroadcastDiscovery);
#endif // def RS_BROADCAST_DISCOVERY
#ifdef ENABLE_GROUTER
p3GRouter *gr = new p3GRouter(serviceCtrl,mGxsIdService) ;
rsGRouter = gr ;
@ -1841,10 +1852,14 @@ int RsServer::StartupRetroShare()
# ifdef RS_GXS_TRANS
startServiceThread(mGxsTrans, "gxs trans");
startServiceThread(gxstrans_ns, "gxs trans ns");
# endif // RS_GXS_TRANS
# endif // def RS_GXS_TRANS
#endif // RS_ENABLE_GXS
#ifdef RS_BROADCAST_DISCOVERY
startServiceThread(&tBroadcastDiscoveryService, "Broadcast Discovery");
#endif // def RS_BROADCAST_DISCOVERY
ftserver->StartupThreads();
ftserver->ResumeTransfers();

View File

@ -0,0 +1,227 @@
/*******************************************************************************
* RetroShare Broadcast Domain Discovery *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <functional>
#include <set>
#include <thread>
#include <chrono>
#include <vector>
#include <iostream>
#include "services/broadcastdiscoveryservice.h"
#include "retroshare/rspeers.h"
#include "serialiser/rsserializable.h"
#include "serialiser/rsserializer.h"
#include "retroshare/rsevents.h"
#ifdef RS_BROADCAST_DISCOVERY_DEBUG
# include "util/radix64.h"
#endif
/*extern*/ std::shared_ptr<RsBroadcastDiscovery> rsBroadcastDiscovery(nullptr);
RsBroadcastDiscovery::~RsBroadcastDiscovery() { /* Beware of Rs prefix! */ }
RsBroadcastDiscoveryResult::~RsBroadcastDiscoveryResult() {}
RsBroadcastDiscoveryPeerFoundEvent::~RsBroadcastDiscoveryPeerFoundEvent() {}
struct BroadcastDiscoveryPack : RsSerializable
{
BroadcastDiscoveryPack() : mLocalPort(0) {}
PGPFingerprintType mPgpFingerprint;
RsPeerId mSslId;
uint16_t mLocalPort;
std::string mProfileName;
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override
{
RS_SERIAL_PROCESS(mPgpFingerprint);
RS_SERIAL_PROCESS(mSslId);
RS_SERIAL_PROCESS(mLocalPort);
RS_SERIAL_PROCESS(mProfileName);
}
static BroadcastDiscoveryPack fromPeerDetails(const RsPeerDetails& pd)
{
BroadcastDiscoveryPack bdp;
bdp.mPgpFingerprint = pd.fpr;
bdp.mSslId = pd.id;
bdp.mLocalPort = pd.localPort;
bdp.mProfileName = pd.name;
return bdp;
}
static BroadcastDiscoveryPack fromSerializedString(const std::string& st)
{
RsGenericSerializer::SerializeContext ctx(
reinterpret_cast<uint8_t*>(const_cast<char*>(st.data())),
static_cast<uint32_t>(st.size()) );
BroadcastDiscoveryPack bdp;
bdp.serial_process(RsGenericSerializer::DESERIALIZE, ctx);
return bdp;
}
std::string serializeToString()
{
/* After some experiments it seems very unlikely that UDP broadcast
* packets bigger then this could get trought a network */
std::vector<uint8_t> buffer(512, 0);
RsGenericSerializer::SerializeContext ctx(
buffer.data(), static_cast<uint32_t>(buffer.size()) );
serial_process(RsGenericSerializer::SERIALIZE, ctx);
return std::string(reinterpret_cast<char*>(buffer.data()), ctx.mOffset);
}
BroadcastDiscoveryPack(const BroadcastDiscoveryPack&) = default;
~BroadcastDiscoveryPack() override;
};
BroadcastDiscoveryPack::~BroadcastDiscoveryPack() {};
BroadcastDiscoveryService::BroadcastDiscoveryService(
RsPeers& pRsPeers ) :
mDiscoveredDataMutex("BroadcastDiscoveryService discovered data mutex"),
mRsPeers(pRsPeers)
{
if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return;
mUdcParameters.set_can_discover(true);
mUdcParameters.set_can_be_discovered(true);
mUdcParameters.set_port(port);
mUdcParameters.set_application_id(appId);
mUdcEndpoint.Start(mUdcParameters, "");
updatePublishedData();
}
BroadcastDiscoveryService::~BroadcastDiscoveryService()
{ mUdcEndpoint.Stop(true); }
std::vector<RsBroadcastDiscoveryResult>
BroadcastDiscoveryService::getDiscoveredPeers()
{
std::vector<RsBroadcastDiscoveryResult> ret;
RS_STACK_MUTEX(mDiscoveredDataMutex);
for(auto&& pp: mDiscoveredData)
ret.push_back(createResult(pp.first, pp.second));
return ret;
}
void BroadcastDiscoveryService::updatePublishedData()
{
RsPeerDetails od;
mRsPeers.getPeerDetails(mRsPeers.getOwnId(), od);
mUdcEndpoint.SetUserData(
BroadcastDiscoveryPack::fromPeerDetails(od).serializeToString());
}
void BroadcastDiscoveryService::data_tick()
{
auto nextRunAt = std::chrono::system_clock::now() + std::chrono::seconds(5);
if( mUdcParameters.can_discover() &&
!mRsPeers.isHiddenNode(mRsPeers.getOwnId()) )
{
auto newEndpoints = mUdcEndpoint.ListDiscovered();
std::set< std::pair<UDC::IpPort, std::string> > mChangedData;
mDiscoveredDataMutex.lock();
for(auto&& dEndpoint: newEndpoints)
{
auto findIt = mDiscoveredData.find(dEndpoint.ip_port());
if( !dEndpoint.user_data().empty() && (
findIt == mDiscoveredData.end() ||
(*findIt).second != dEndpoint.user_data() ) )
{
mDiscoveredData[dEndpoint.ip_port()] = dEndpoint.user_data();
mChangedData.insert(std::make_pair(
dEndpoint.ip_port(),
dEndpoint.user_data() ));
}
}
mDiscoveredDataMutex.unlock();
if(!mChangedData.empty())
{
for (auto&& pp : mChangedData)
{
#ifdef RS_BROADCAST_DISCOVERY_DEBUG
{
std::string b64Data;
Radix64::encode(
reinterpret_cast<const unsigned char*>(pp.second.data()),
static_cast<int>(pp.second.size()), b64Data );
std::cerr << __PRETTY_FUNCTION__ << " Got: " << b64Data
<< " Base64 from: " << UDC::IpToString(pp.first.ip())
<< ":" << pp.first.port() << std::endl;
}
#endif // def RS_BROADCAST_DISCOVERY_DEBUG
RsBroadcastDiscoveryResult rbdr =
createResult(pp.first, pp.second);
if( rbdr.locator.hasPort() && mRsPeers.isFriend(rbdr.mSslId) &&
!mRsPeers.isOnline(rbdr.mSslId) )
{
mRsPeers.setLocalAddress(
rbdr.mSslId, rbdr.locator.host(),
rbdr.locator.port() );
mRsPeers.connectAttempt(rbdr.mSslId);
}
else
{
typedef RsBroadcastDiscoveryPeerFoundEvent Evt_t;
// Ensure rsEvents is not deleted while we use it
std::shared_ptr<RsEvents> lockedRsEvents = rsEvents;
if(lockedRsEvents)
lockedRsEvents->postEvent(
std::unique_ptr<Evt_t>(new Evt_t(rbdr)) );
}
}
}
}
/* Probably this would be better if done only on actual change */
if( mUdcParameters.can_be_discovered() &&
!mRsPeers.isHiddenNode(mRsPeers.getOwnId()) ) updatePublishedData();
std::this_thread::sleep_until(nextRunAt);
}
RsBroadcastDiscoveryResult BroadcastDiscoveryService::createResult(
const udpdiscovery::IpPort& ipp, const std::string& uData )
{
BroadcastDiscoveryPack bdp =
BroadcastDiscoveryPack::fromSerializedString(uData);
RsBroadcastDiscoveryResult rbdr;
rbdr.mPgpFingerprint = bdp.mPgpFingerprint;
rbdr.mSslId = bdp.mSslId;
rbdr.mProfileName = bdp.mProfileName;
rbdr.locator.
setScheme("ipv4").
setHost(UDC::IpToString(ipp.ip())).
setPort(bdp.mLocalPort);
return rbdr;
}

View File

@ -0,0 +1,65 @@
/*******************************************************************************
* RetroShare Broadcast Domain Discovery *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <cstdint>
#include <map>
#include <iostream>
#include <endpoint.hpp>
#include <memory>
#include <forward_list>
#include "retroshare/rsbroadcastdiscovery.h"
#include "util/rsthreads.h"
namespace UDC = udpdiscovery;
class RsPeers;
class BroadcastDiscoveryService :
public RsBroadcastDiscovery, public RsTickingThread
{
public:
// TODO: std::shared_ptr<RsPeers> mRsPeers;
BroadcastDiscoveryService(RsPeers& pRsPeers);
virtual ~BroadcastDiscoveryService() override;
/// @see RsBroadcastDiscovery
std::vector<RsBroadcastDiscoveryResult> getDiscoveredPeers() override;
/// @see RsTickingThread
void data_tick() override;
protected:
constexpr static uint16_t port = 36405;
constexpr static uint32_t appId = 904571;
void updatePublishedData();
UDC::EndpointParameters mUdcParameters;
UDC::Endpoint mUdcEndpoint;
std::map<UDC::IpPort, std::string> mDiscoveredData;
RsMutex mDiscoveredDataMutex;
RsPeers& mRsPeers; // TODO: std::shared_ptr<RsPeers> mRsPeers;
RsBroadcastDiscoveryResult createResult(
const UDC::IpPort& ipp, const std::string& uData );
};

View File

@ -0,0 +1,171 @@
/*******************************************************************************
* Retroshare events service *
* *
* libretroshare: retroshare core library *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <string>
#include "services/rseventsservice.h"
/*extern*/ std::shared_ptr<RsEvents> rsEvents(nullptr);
RsEvent::~RsEvent() {};
RsEvents::~RsEvents() {};
bool isEventValid(const RsEvent& event, std::string& errorMessage)
{
if(event.mType <= RsEventType::NONE)
{
errorMessage = "Event has type NONE: " +
std::to_string(
static_cast<std::underlying_type<RsEventType>::type >(
event.mType ) );
return false;
}
if(event.mType >= RsEventType::MAX)
{
errorMessage = "Event has type >= RsEventType::MAX: " +
std::to_string(
static_cast<std::underlying_type<RsEventType>::type >(
event.mType ) );
}
return true;
}
bool RsEventsService::postEvent( std::unique_ptr<RsEvent> event,
std::string& errorMessage )
{
if(!isEventValid(*event, errorMessage))
{
std::cerr << __PRETTY_FUNCTION__ << " Error: "<< errorMessage
<< std::endl;
return false;
}
RS_STACK_MUTEX(mEventQueueMtx);
mEventQueue.push_back(std::move(event));
return true;
}
bool RsEventsService::sendEvent( const RsEvent& event,
std::string& errorMessage )
{
if(!isEventValid(event, errorMessage))
{
std::cerr << __PRETTY_FUNCTION__ << " Error: "<< errorMessage
<< std::endl;
return false;
}
handleEvent(event);
return true;
}
RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId()
{
RS_STACK_MUTEX(mHandlerMapMtx);
return generateUniqueHandlerId_unlocked();
}
RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked()
{
if(++mLastHandlerId) return mLastHandlerId; // Avoid 0 after overflow
return 1;
}
bool RsEventsService::registerEventsHandler(
std::function<void(const RsEvent&)> multiCallback,
RsEventsHandlerId_t& hId )
{
RS_STACK_MUTEX(mHandlerMapMtx);
if(!hId) hId = generateUniqueHandlerId_unlocked();
mHandlerMap[hId] = std::move(multiCallback);
return true;
}
bool RsEventsService::unregisterEventsHandler(RsEventsHandlerId_t hId)
{
RS_STACK_MUTEX(mHandlerMapMtx);
auto it = mHandlerMap.find(hId);
if(it == mHandlerMap.end()) return false;
mHandlerMap.erase(it);
return true;
}
void RsEventsService::data_tick()
{
auto nextRunAt = std::chrono::system_clock::now() +
std::chrono::milliseconds(1);
std::unique_ptr<RsEvent> eventPtr(nullptr);
size_t futureEventsCounter = 0;
dispatchEventFromQueueLock:
mEventQueueMtx.lock();
if(mEventQueue.size() > futureEventsCounter)
{
eventPtr = std::move(mEventQueue.front());
mEventQueue.pop_front();
if(eventPtr->mTimePoint >= nextRunAt)
{
mEventQueue.push_back(std::move(eventPtr));
++futureEventsCounter;
}
}
mEventQueueMtx.unlock();
if(eventPtr)
{
/* It is relevant that this stays out of mEventQueueMtx */
handleEvent(*eventPtr);
eventPtr.reset(nullptr); // ensure memory is freed before sleep
goto dispatchEventFromQueueLock;
}
std::this_thread::sleep_until(nextRunAt);
}
void RsEventsService::handleEvent(const RsEvent& event)
{
std::function<void(const RsEvent&)> mCallback;
mHandlerMapMtx.lock();
auto cbpt = mHandlerMap.begin();
mHandlerMapMtx.unlock();
getHandlerFromMapLock:
mHandlerMapMtx.lock();
if(cbpt != mHandlerMap.end())
{
mCallback = cbpt->second;
++cbpt;
}
mHandlerMapMtx.unlock();
if(mCallback)
{
mCallback(event); // It is relevant that this happens outside mutex
mCallback = std::function<void(const RsEvent&)>(nullptr);
goto getHandlerFromMapLock;
}
}

View File

@ -0,0 +1,77 @@
/*******************************************************************************
* Retroshare events service *
* *
* libretroshare: retroshare core library *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <memory>
#include <cstdint>
#include <deque>
#include "retroshare/rsevents.h"
#include "util/rsthreads.h"
class RsEventsService :
public RsEvents, public RsTickingThread
{
public:
RsEventsService():
mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1),
mEventQueueMtx("RsEventsService::mEventQueueMtx") {}
/// @see RsEvents
bool postEvent(
std::unique_ptr<RsEvent> event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) override;
/// @see RsEvents
bool sendEvent(
const RsEvent& event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) override;
/// @see RsEvents
RsEventsHandlerId_t generateUniqueHandlerId() override;
/// @see RsEvents
bool registerEventsHandler(
std::function<void(const RsEvent&)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
) override;
/// @see RsEvents
bool unregisterEventsHandler(RsEventsHandlerId_t hId) override;
protected:
RsMutex mHandlerMapMtx;
RsEventsHandlerId_t mLastHandlerId;
std::map< RsEventsHandlerId_t, std::function<void(const RsEvent&)> >
mHandlerMap;
RsMutex mEventQueueMtx;
std::deque< std::unique_ptr<RsEvent> > mEventQueue;
/// @see RsTickingThread
void data_tick() override;
void handleEvent(const RsEvent& event);
RsEventsHandlerId_t generateUniqueHandlerId_unlocked();
};

View File

@ -15,13 +15,16 @@
# You should have received a copy of the GNU Lesser General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
################################################################################
DEPENDPATH *= $$clean_path($${PWD}/../../libretroshare/src/)
INCLUDEPATH *= $$clean_path($${PWD}/../../libretroshare/src)
LIBS *= -L$$clean_path($${OUT_PWD}/../../libretroshare/src/lib/) -lretroshare
RS_SRC_PATH=$$clean_path($${PWD}/../../)
RS_BUILD_PATH=$$clean_path($${OUT_PWD}/../../)
DEPENDPATH *= $$clean_path($${RS_SRC_PATH}/libretroshare/src/)
INCLUDEPATH *= $$clean_path($${RS_SRC_PATH}/libretroshare/src)
LIBS *= -L$$clean_path($${RS_BUILD_PATH}/libretroshare/src/lib/) -lretroshare
equals(TARGET, retroshare):equals(TEMPLATE, lib){
} else {
PRE_TARGETDEPS *= $$clean_path($$OUT_PWD/../../libretroshare/src/lib/libretroshare.a)
PRE_TARGETDEPS *= $$clean_path($${RS_BUILD_PATH}/libretroshare/src/lib/libretroshare.a)
}
!include("../../openpgpsdk/src/use_openpgpsdk.pri"):error("Including")
@ -48,9 +51,6 @@ mLibs = $$RS_SQL_LIB ssl crypto $$RS_THREAD_LIB $$RS_UPNP_LIB
dLibs =
rs_jsonapi {
RS_SRC_PATH=$$clean_path($${PWD}/../../)
RS_BUILD_PATH=$$clean_path($${OUT_PWD}/../../)
no_rs_cross_compiling {
RESTBED_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/restbed)
RESTBED_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/restbed)
@ -73,6 +73,20 @@ rs_deep_search {
win32-g++:mLibs += rpcrt4
}
rs_broadcast_discovery {
no_rs_cross_compiling {
UDP_DISCOVERY_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/udp-discovery-cpp/)
UDP_DISCOVERY_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/udp-discovery-cpp/)
INCLUDEPATH *= $$clean_path($${UDP_DISCOVERY_SRC_PATH})
DEPENDPATH *= $$clean_path($${UDP_DISCOVERY_BUILD_PATH})
QMAKE_LIBDIR *= $$clean_path($${UDP_DISCOVERY_BUILD_PATH})
# Using sLibs would fail as libudp-discovery.a is generated at compile-time
LIBS *= -L$$clean_path($${UDP_DISCOVERY_BUILD_PATH}) -ludp-discovery
} else:sLibs *= udp-discovery
win32-g++:dLibs *= wsock32
}
static {
sLibs *= $$mLibs
} else {

View File

@ -60,7 +60,7 @@ bool myFunnyFunction(
* passed, so any effect on performace would happen only in case where the
* function is called without the parameter.
*/
#define RS_DEFAULT_STORAGE_PARAM(Type) *std::unique_ptr<Type>(new Type)
#define RS_DEFAULT_STORAGE_PARAM(Type,...) *std::unique_ptr<Type>(new Type(__VA_ARGS__))
void *rs_malloc(size_t size) ;

View File

@ -45,11 +45,14 @@ typedef int64_t rstime_t;
// Do we really need this? Our names have rs prefix to avoid pollution already!
namespace rstime {
/*!
* \brief This is a cross-system definition of usleep, which accepts any 32 bits number of micro-seconds.
*/
RS_DEPRECATED_FOR("std::this_thread::sleep_for")
int rs_usleep(uint32_t micro_seconds);
/**
* @deprecated { std::this_thread::sleep_for or
* std::this_thread::sleep_until instead }
* @brief This is a cross-system definition of usleep, which accepts any
* 32 bits number of micro-seconds.
*/
RS_DEPRECATED_FOR("std::this_thread::sleep_for")
int rs_usleep(uint32_t micro_seconds);
/* Use this class to measure and display time duration of a given environment:

View File

@ -167,10 +167,15 @@ CONFIG *= no_rs_deep_search
rs_deep_search:CONFIG -= no_rs_deep_search
# To enable native dialogs append the following assignation to qmake command
#line "CONFIG+=rs_use_native_dialogs"
# line "CONFIG+=rs_use_native_dialogs"
CONFIG *= no_rs_use_native_dialogs
rs_use_native_dialogs:CONFIG -= no_rs_use_native_dialogs
# To disable broadcast discovery happend the following assignation to qmake
# command line "CONFIG+=no_rs_broadcast_discovery"
CONFIG *= rs_broadcast_discovery
no_rs_broadcast_discovery:CONFIG -= rs_broadcast_discovery
# Specify host precompiled jsonapi-generator path, appending the following
# assignation to qmake command line
# 'JSONAPI_GENERATOR_EXE=/myBuildDir/jsonapi-generator'. Required for JSON API
@ -327,6 +332,19 @@ defineReplace(linkDynamicLibs) {
return($$retDlib)
}
## On some environements qmake chose a C++ compiler as C compiler, this breaks
## some sub targets, such as those based on cmake which test for chosen C
## compiler to be a proper C compiler. This function try to deduce the correct C
## compiler also in those cases, and return it. So you can use
## $$fixQmakeCC($$QMAKE_CC) in those cases instead of plain $$QMAKE_CC
defineReplace(fixQmakeCC) {
retVal = $$1
contains(1, .*\+\+$):retVal=$$str_member($$1, 0 ,-3)
contains(1, .*g\+\+$):retVal=$$str_member($$1, 0 ,-3)cc
contains(1, .*clang\+\+$):retVal=$$str_member($$1, 0 ,-3)
return($$retVal)
}
################################################################################
## Statements and variables that depends on build options (CONFIG) goes here ###
################################################################################
@ -496,6 +514,8 @@ rs_deep_search {
rs_use_native_dialogs:DEFINES *= RS_NATIVEDIALOGS
rs_broadcast_discovery:DEFINES *= RS_BROADCAST_DISCOVERY
debug {
QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer
QMAKE_CFLAGS -= -O2 -fomit-frame-pointer

@ -0,0 +1 @@
Subproject commit 5729d5090a5e1ed7d26ed64ae244c7a5e624e82f