Skip to content
Permalink
Browse files

dhtproxy: switch server to restinio

          rewrite options, getNodeInfo, get & put
opendht: bump to c++14
  • Loading branch information...
binarytrails committed May 14, 2019
1 parent ff6be81 commit 9e3e9e65e60221eabfd4220940b562642c7ec070
Showing with 295 additions and 659 deletions.
  1. +22 −8 CMakeLists.txt
  2. +3 −3 README.md
  3. +14 −0 cmake/FindRestinio.cmake
  4. +39 −14 include/opendht/dht_proxy_server.h
  5. +1 −1 python/opendht.pyx
  6. +2 −2 python/setup.py.in
  7. +214 −631 src/dht_proxy_server.cpp
@@ -16,10 +16,10 @@ option (OPENDHT_SYSTEMD "Install systemd module" OFF)
option (OPENDHT_ARGON2 "Use included argon2 sources" OFF)
option (OPENDHT_LTO "Build with LTO" OFF)
option (OPENDHT_SANITIZE "Build with address sanitizer and stack protector" OFF)
option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restbed and jsoncpp" OFF)
option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restinio and jsoncpp" OFF)
option (OPENDHT_PUSH_NOTIFICATIONS "Enable push notifications support" OFF)
option (OPENDHT_PROXY_SERVER_IDENTITY "Allow clients to use the node identity" OFF)
option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restbed and jsoncpp" OFF)
option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restinio and jsoncpp" OFF)
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
option (OPENDHT_TESTS "Add unit tests executable" OFF)

@@ -58,16 +58,22 @@ if (Jsoncpp_FOUND)
endif()

if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
find_package(Restbed REQUIRED)
find_package(Restinio REQUIRED)
if (Restinio_FOUND)
find_library(FMT_LIBRARY fmt)
add_library(fmt SHARED IMPORTED)
find_library(HTTP_PARSER_LIBRARY http_parser)
add_library(http_parser SHARED IMPORTED)
endif()
if (NOT Jsoncpp_FOUND)
message(SEND_ERROR "Jsoncpp is required for DHT proxy support")
endif()
endif()

# Build flags
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_STANDARD_REQUIRED on)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lpthread -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
if (OPENDHT_SANITIZE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-protector-strong")
endif ()
@@ -100,6 +106,9 @@ endif ()
if (Nettle_INCLUDE_DIRS)
include_directories (SYSTEM "${Nettle_INCLUDE_DIRS}")
endif ()
if (Restinio_INCLUDE_DIR)
include_directories (SYSTEM "${Restinio_INCLUDE_DIR}")
endif ()
if (Restbed_INCLUDE_DIR)
include_directories (SYSTEM "${Restbed_INCLUDE_DIR}")
endif ()
@@ -255,8 +264,9 @@ if (OPENDHT_STATIC)
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif ()
target_link_libraries(opendht-static
PRIVATE ${Restbed_LIBRARY} ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${Jsoncpp_LIBRARIES})
PRIVATE ${Restbed_LIBRARY} ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()

@@ -274,7 +284,11 @@ if (OPENDHT_SHARED)
target_link_libraries(opendht PRIVATE ${argon2_LIBRARIES})
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif ()
target_link_libraries(opendht PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${Restbed_LIBRARY} ${Jsoncpp_LIBRARIES})
target_link_libraries(opendht
PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Restbed_LIBRARY} ${Jsoncpp_LIBRARIES}
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})

install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()

@@ -4,7 +4,7 @@
<a id="user-content-opendht-" class="anchor" href="/savoirfairelinux/opendht/blob/master/README.md#opendht-" aria-hidden="true"></a>OpenDHT
</h1>

A lightweight C++11 Distributed Hash Table implementation.
A lightweight C++14 Distributed Hash Table implementation.

OpenDHT provides an easy to use distributed in-memory data store.
Every node in the network can read and write values to the store.
@@ -14,7 +14,7 @@ Values are distributed over the network, with redundancy.
* High resilience to network disruption
* Public key cryptography layer providing optional data signature and encryption (using GnuTLS)
* IPv4 and IPv6 support
* Clean and powerful C++11 map API
* Clean and powerful C++14 map API
* Python 3 bindings
* REST API

@@ -27,7 +27,7 @@ Build instructions: <https://github.com/savoirfairelinux/opendht/wiki/Build-the-

#### How-to build a simple client app
```bash
g++ main.cpp -std=c++11 -lopendht -lgnutls
g++ main.cpp -std=c++14 -lopendht -lgnutls
```

## Examples
@@ -0,0 +1,14 @@
# header-only does not produce a library
if(NOT Restinio_FOUND)
find_path (Restinio_INCLUDE_DIR restinio
HINTS
"/usr/include"
"/usr/local/include"
"/opt/local/include")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Restinio DEFAULT_MSG Restinio_INCLUDE_DIR)
if (Restinio_INCLUDE_DIR)
set(Restinio_FOUND TRUE)
set(Restinio_INCLUDE_DIRS ${Restinio_INCLUDE_DIR})
endif()
endif()
@@ -2,6 +2,7 @@
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,12 +31,21 @@
#include <thread>
#include <memory>
#include <mutex>
#include <restbed>
#include <restinio/all.hpp>

#ifdef OPENDHT_JSONCPP
#include <json/json.h>
#endif

using RestRouter = restinio::router::express_router_t<>;
using RestRouterTraits = restinio::traits_t<
restinio::asio_timer_manager_t,
restinio::single_threaded_ostream_logger_t,
RestRouter>;
using RequestStatus = restinio::request_handling_status_t;
using ResponseByParts = restinio::chunked_output_t;
using ResponseByPartsBuilder = restinio::response_builder_t<ResponseByParts>;

namespace Json {
class Value;
}
@@ -123,22 +133,28 @@ class OPENDHT_PUBLIC DhtProxyServer
void stop();

private:
template <typename HttpResponse>
HttpResponse initHttpResponse(HttpResponse response) const;

std::unique_ptr<RestRouter> createRestRouter();

/**
* Return the PublicKey id, the node id and node stats
* Method: GET "/"
* Result: HTTP 200, body: Node infos in JSON format
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
void getNodeInfo(const std::shared_ptr<restbed::Session>& session) const;
RequestStatus getNodeInfo(restinio::request_handle_t request,
restinio::router::route_params_t params) const;

/**
* Return ServerStats in JSON format
* Method: STATS "/"
* Result: HTTP 200, body: Node infos in JSON format
* @param session
*/
void getStats(const std::shared_ptr<restbed::Session>& session) const;
//void getStats(const std::shared_ptr<restbed::Session>& session) const;

/**
* Return Values of an infoHash
@@ -150,7 +166,8 @@ class OPENDHT_PUBLIC DhtProxyServer
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
void get(const std::shared_ptr<restbed::Session>& session) const;
RequestStatus get(restinio::request_handle_t request,
restinio::router::route_params_t params);

/**
* Listen incoming Values of an infoHash.
@@ -162,7 +179,7 @@ class OPENDHT_PUBLIC DhtProxyServer
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
void listen(const std::shared_ptr<restbed::Session>& session);
//void listen(const std::shared_ptr<restbed::Session>& session);

/**
* Put a value on the DHT
@@ -173,7 +190,8 @@ class OPENDHT_PUBLIC DhtProxyServer
* HTTP 400, body: {"err":"xxxx"} if bad json or HTTP 502 if put fails
* @param session
*/
void put(const std::shared_ptr<restbed::Session>& session);
RequestStatus put(restinio::request_handle_t request,
restinio::router::route_params_t params);

void cancelPut(const InfoHash& key, Value::Id vid);

@@ -187,7 +205,7 @@ class OPENDHT_PUBLIC DhtProxyServer
* HTTP 400, body: {"err":"xxxx"} if bad json
* @param session
*/
void putSigned(const std::shared_ptr<restbed::Session>& session) const;
//void putSigned(const std::shared_ptr<restbed::Session>& session) const;

/**
* Put a value to encrypt by the proxy on the DHT
@@ -198,7 +216,7 @@ class OPENDHT_PUBLIC DhtProxyServer
* HTTP 400, body: {"err":"xxxx"} if bad json
* @param session
*/
void putEncrypted(const std::shared_ptr<restbed::Session>& session) const;
//void putEncrypted(const std::shared_ptr<restbed::Session>& session) const;
#endif // OPENDHT_PROXY_SERVER_IDENTITY

/**
@@ -211,7 +229,7 @@ class OPENDHT_PUBLIC DhtProxyServer
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
void getFiltered(const std::shared_ptr<restbed::Session>& session) const;
//void getFiltered(const std::shared_ptr<restbed::Session>& session) const;

/**
* Respond allowed Methods
@@ -220,7 +238,8 @@ class OPENDHT_PUBLIC DhtProxyServer
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
* @param session
*/
void handleOptionsMethod(const std::shared_ptr<restbed::Session>& session) const;
RequestStatus options(restinio::request_handle_t request,
restinio::router::route_params_t params);

/**
* Remove finished listeners
@@ -238,15 +257,15 @@ class OPENDHT_PUBLIC DhtProxyServer
* so you need to refresh the operation each six hours.
* @param session
*/
void subscribe(const std::shared_ptr<restbed::Session>& session);
//void subscribe(const std::shared_ptr<restbed::Session>& session);
/**
* Unsubscribe to push notifications for an iOS or Android device.
* Method: UNSUBSCRIBE "/{InfoHash: .*}"
* Body: {"key": "device_key", "token": x} where x if the token to cancel
* Return: nothing
* @param session
*/
void unsubscribe(const std::shared_ptr<restbed::Session>& session);
//void unsubscribe(const std::shared_ptr<restbed::Session>& session);
/**
* Send a push notification via a gorush push gateway
* @param key of the device
@@ -269,7 +288,7 @@ class OPENDHT_PUBLIC DhtProxyServer
using time_point = clock::time_point;

std::thread server_thread {};
std::unique_ptr<restbed::Service> service_;
//std::unique_ptr<restbed::Service> service_;
std::shared_ptr<DhtRunner> dht_;
Json::StreamWriterBuilder jsonBuilder_;

@@ -287,7 +306,7 @@ class OPENDHT_PUBLIC DhtProxyServer
// NOTE: can be simplified when we will supports restbed 5.0
std::thread listenThread_;
struct SessionToHashToken {
std::shared_ptr<restbed::Session> session;
//std::shared_ptr<restbed::Session> session;
InfoHash hash;
std::future<size_t> token;
};
@@ -313,6 +332,12 @@ class OPENDHT_PUBLIC DhtProxyServer
std::map<std::string, PushListener> pushListeners_;
proxy::ListenToken tokenPushNotif_ {0};
#endif //OPENDHT_PUSH_NOTIFICATIONS

const std::string RESP_MSG_INCORRECT_JSON = "{\"err:\":\"Incorrect JSON\"}";
const std::string RESP_MSG_SERVICE_UNAVAILABLE = "{\"err\":\"Incorrect DhtRunner\"}";
const std::string RESP_MSG_INTERNAL_SERVER_ERRROR = "{\"err\":\"Internal server error\"}";
const std::string RESP_MSG_MISSING_PARAMS = "{\"err\":\"Missing parameters\"}";
const std::string RESP_MSG_PUT_FAILED = "{\"err\":\"Put failed\"}";
};

}
@@ -1,5 +1,5 @@
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11
# distutils: extra_compile_args = -std=c++14
# distutils: include_dirs = ../../include
# distutils: library_dirs = ../../src
# distutils: libraries = opendht gnutls
@@ -50,8 +50,8 @@ setup(name="opendht",
["@CURRENT_SOURCE_DIR@/opendht.pyx"],
include_dirs = ['@PROJECT_SOURCE_DIR@/include'],
language="c++",
extra_compile_args=["-std=c++11"],
extra_link_args=["-std=c++11"],
extra_compile_args=["-std=c++14"],
extra_link_args=["-std=c++14"],
libraries=["opendht"],
library_dirs = ['@CURRENT_BINARY_DIR@', '@PROJECT_BINARY_DIR@']
))

0 comments on commit 9e3e9e6

Please sign in to comment.
You can’t perform that action at this time.