Skip to content

Commit

Permalink
ConnectivityStatus:
Browse files Browse the repository at this point in the history
this will help getting more granular reporting of connectivity status
from kernel.  it is linux/android specific for now with possible
future support for bsd/darwin.

this is very much a prototype; cleaner interface and code will follow.

it adds libnl (ships with android) dependency which is really not
required, although expedited prototyping.
  • Loading branch information
257 committed Feb 14, 2020
1 parent 6c2f791 commit 702889d
Show file tree
Hide file tree
Showing 10 changed files with 631 additions and 23 deletions.
30 changes: 24 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
cmake_minimum_required (VERSION 3.1)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)

project (opendht)
set (opendht_VERSION_MAJOR 2)
set (opendht_VERSION_MINOR 0.0)
Expand All @@ -22,7 +25,9 @@ option (OPENDHT_PROXY_SERVER_IDENTITY "Allow clients to use the node identity" O
option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restinio and jsoncpp" OFF)
option (OPENDHT_PROXY_OPENSSL "Build DHT proxy with OpenSSL" ON)
option (OPENDHT_PROXY_HTTP_PARSER_FORK "Build DHT proxy with custom http_parser to support old API" OFF)
CMAKE_DEPENDENT_OPTION(OPENDHT_HTTP "Build embedded http(s) client" OFF "NOT OPENDHT_PROXY_SERVER;NOT OPENDHT_PROXY_CLIENT" ON)
option (OPENDHT_PEER_DISCOVERY "Enable multicast peer discovery" ON)
option (OPENDHT_CONNECTIVITY_STAT "Enable connectivity stat module" OFF)
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
option (OPENDHT_TESTS "Add unit tests executable" OFF)
option (OPENDHT_C "Build C bindings" OFF)
Expand Down Expand Up @@ -61,7 +66,7 @@ if (Jsoncpp_FOUND)
)
endif()

if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
if (OPENDHT_HTTP)
find_package(Restinio REQUIRED)
if (Restinio_FOUND)
find_library(FMT_LIBRARY fmt)
Expand All @@ -88,9 +93,12 @@ if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
else()
set(OPENDHT_PROXY_OPENSSL OFF)
endif()
if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT OR OPENDHT_PEER_DISCOVERY)
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
add_definitions(-DASIO_STANDALONE)
endif()
if (OPENDHT_CONNECTIVITY_STAT)
find_package (NL REQUIRED)
endif()

# Build flags
set (CMAKE_CXX_STANDARD 14)
Expand Down Expand Up @@ -146,6 +154,10 @@ include_directories (
include/opendht/
${CMAKE_CURRENT_BINARY_DIR}/include/
)
if (OPENDHT_CONNECTIVITY_STAT)
include_directories (SYSTEM "${NL_INCLUDE_DIRS}")
link_directories (${NL_LIBRARIES})
endif()

# Install dirs
include (GNUInstallDirs)
Expand Down Expand Up @@ -251,7 +263,7 @@ if (OPENDHT_PROXY_CLIENT)
)
endif ()

if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
if (OPENDHT_HTTP)
if (OPENDHT_PUSH_NOTIFICATIONS)
message("Using push notification")
add_definitions(-DOPENDHT_PUSH_NOTIFICATIONS)
Expand Down Expand Up @@ -282,6 +294,12 @@ if(OPENDHT_ARGON2)
include_directories(argon2/include/)
endif()

if (OPENDHT_CONNECTIVITY_STAT)
list (APPEND opendht_SOURCES src/connstat.cpp)
list (APPEND opendht_HEADERS include/opendht/connstat.h)
add_definitions(-DOPENDHT_CONNECTIVITY_STAT)
endif()

# Targets
if (OPENDHT_STATIC)
add_library (opendht-static STATIC
Expand All @@ -298,7 +316,7 @@ if (OPENDHT_STATIC)
PRIVATE ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
${OPENSSL_LIBRARIES})
${OPENSSL_LIBRARIES} ${NL_LIBRARIES})
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()

Expand All @@ -316,11 +334,12 @@ if (OPENDHT_SHARED)
target_link_libraries(opendht PRIVATE ${argon2_LIBRARIES})
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif ()
# FIXME
target_link_libraries(opendht
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES}
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES}
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY} ${NL_LIBRARIES})

install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()
Expand Down Expand Up @@ -357,7 +376,6 @@ if (OPENDHT_PYTHON)
endif ()

# CMake module
include(CMakePackageConfigHelpers)
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/opendhtConfigVersion.cmake"
VERSION ${opendht_VERSION}
COMPATIBILITY AnyNewerVersion
Expand Down
140 changes: 140 additions & 0 deletions cmake/FindNL.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#
# Find the native netlink includes and library
#
# If they exist, differentiate between versions 1, 2 and 3.
# Version 1 does not have netlink/version.h
# Version 2 started separating libraries (libnl{,-genl,-route}).
# Version 3 (>= 3.2) started appending the major version number as suffix to
# library names (libnl-3)
#
# NL_INCLUDE_DIRS - where to find libnl.h, etc.
# NL_LIBRARIES - List of libraries when using libnl.
# NL_FOUND - True if libnl found.

if(NL_LIBRARIES AND NL_INCLUDE_DIRS)
# in cache already
SET(NL_FOUND TRUE)
else()
SET( SEARCHPATHS
/opt/local
/sw
/usr
/usr/local
)

find_package(PkgConfig)
pkg_check_modules(NL3 libnl-3.0 libnl-genl-3.0 libnl-route-3.0)
if(NOT NL3_FOUND)
pkg_search_module(NL2 libnl-2.0)
endif()

# Try to find NL 2.0, 3.0 or 3.1 (/usr/include/netlink/version.h) or
# NL >= 3.2 (/usr/include/libnl3/netlink/version.h)
find_path(NL3_INCLUDE_DIR
PATH_SUFFIXES
include/libnl3
include
NAMES
netlink/version.h
HINTS
"${NL3_libnl-3.0_INCLUDEDIR}"
"${NL2_INCLUDEDIR}"
PATHS
$(SEARCHPATHS)
)
# NL version >= 2
if(NL3_INCLUDE_DIR)
find_library(NL3_LIBRARY
NAMES
nl-3 nl
PATH_SUFFIXES
lib64 lib
HINTS
"${NL3_libnl-3.0_LIBDIR}"
"${NL2_LIBDIR}"
PATHS
$(SEARCHPATHS)
)
find_library(NLGENL_LIBRARY
NAMES
nl-genl-3 nl-genl
PATH_SUFFIXES
lib64 lib
HINTS
"${NL3_libnl-genl-3.0_LIBDIR}"
"${NL2_LIBDIR}"
PATHS
$(SEARCHPATHS)
)
find_library(NLROUTE_LIBRARY
NAMES
nl-route-3 nl-route
PATH_SUFFIXES
lib64 lib
HINTS
"${NL3_libnl-route-3.0_LIBDIR}"
"${NL2_LIBDIR}"
PATHS
$(SEARCHPATHS)
)
#
# If we don't have all of those libraries, we can't use libnl.
#
if(NL3_LIBRARY AND NLGENL_LIBRARY AND NLROUTE_LIBRARY)
set(NL_LIBRARY ${NL3_LIBRARY})
# NL2 and NL3 are similar and just affect how the version is reported in
# the --version output. In cast of doubt, assume NL3 since a library
# without version number could be any of 2.0, 3.0 or 3.1.
if(NOT NL3_FOUND AND NL2_FOUND)
set(HAVE_LIBNL2 1)
else()
set(HAVE_LIBNL3 1)
endif()
endif()
set(NL_INCLUDE_DIR ${NL3_INCLUDE_DIR})
endif()

# libnl-2 and libnl-3 not found, try NL version 1
if(NOT (NL_LIBRARY AND NL_INCLUDE_DIR))
pkg_search_module(NL1 libnl-1)
find_path(NL1_INCLUDE_DIR
NAMES
netlink/netlink.h
HINTS
"${NL1_INCLUDEDIR}"
PATHS
$(SEARCHPATHS)
)
find_library(NL1_LIBRARY
NAMES
nl
PATH_SUFFIXES
lib64 lib
HINTS
"${NL1_LIBDIR}"
PATHS
$(SEARCHPATHS)
)
set(NL_LIBRARY ${NL1_LIBRARY})
set(NL_INCLUDE_DIR ${NL1_INCLUDE_DIR})
if(NL1_LIBRARY AND NL1_INCLUDE_DIR)
set(HAVE_LIBNL1 1)
endif()
endif()
endif()

# handle the QUIETLY and REQUIRED arguments and set NL_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(NL DEFAULT_MSG NL_LIBRARY NL_INCLUDE_DIR)

IF(NL_FOUND)
set(NL_LIBRARIES ${NLGENL_LIBRARY} ${NLROUTE_LIBRARY} ${NL_LIBRARY})
set(NL_INCLUDE_DIRS ${NL_INCLUDE_DIR})
set(HAVE_LIBNL 1)
else()
set(NL_LIBRARIES )
set(NL_INCLUDE_DIRS)
endif()

MARK_AS_ADVANCED( NL_LIBRARIES NL_INCLUDE_DIRS )
18 changes: 18 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ AC_ARG_ENABLE([proxy_server_identity], AS_HELP_STRING([--enable-proxy-server-ide
AC_ARG_ENABLE([proxy_client], AS_HELP_STRING([--enable-proxy-client], [Enable proxy client ability]), proxy_client=yes, proxy_client=no)
AM_CONDITIONAL(ENABLE_PROXY_CLIENT, test x$proxy_client == xyes)

dnl connectivity status
AC_ARG_ENABLE([connstat],
AS_HELP_STRING([--disable-connstat],
[Disable native connectivity stat reports]))
AS_IF([test "$SYS" == "android"], [have_libnl=yes],
[test "$SYS" == "linux"], [PKG_CHECK_MODULES([NL3],
[libnl-3.0 libnl-genl-3.0 libnl-route-3.0],
[have_libnl=yes], [have_libnl=no])],
[have_libnl=no]
)
dnl assert on other hosts
AS_IF([test "x$enable_connstat" = "xyes" && "x$have_libnl" = "xno"], [
AC_MSG_ERROR(["libnl is required connectivity stat"])]
)
AM_CONDITIONAL([ENABLE_CONNSTAT], [test "x$have_libnl" == "xyes"])
AM_COND_IF([ENABLE_CONNSTAT], [AC_DEFINE([ENABLE_CONNSTAT], [1], [Enable connstat])])


AC_ARG_ENABLE([tests], AS_HELP_STRING([--enable-tests], [Enable tests]), build_tests=yes, build_tests=no)
AM_CONDITIONAL(ENABLE_TESTS, test x$build_tests == xyes)
AM_COND_IF([ENABLE_TESTS], [
Expand Down
102 changes: 102 additions & 0 deletions include/opendht/connstat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Paymon <[email protected]>
*
* 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
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include "log.h"

#include <functional>
#include <thread>
#include <mutex>
#include <atomic>

struct nl_sock;
struct nl_msg;
struct sockaddr_nl;
struct ucred;

namespace dht {
namespace net {

class OPENDHT_PUBLIC ConnectivityStatus
{
public:
enum class Event : long unsigned int {
NONE_EVENT = 0,
ADDR,
ROUTE,
LINK,
NEIGHT,
EVENTS_NEW,
NEWLINK,
NEWROUTE4,
NEWROUTE6,
NEWROUTE,
NEWADDR4,
NEWADDR6,
NEWADDR,
NEWNEIGH,
NEIGHTBL,
IPV4_MROUTE,
IPV6_MROUTE,
IP_MROUTE,
EVENTS_DEL,
DELLINK,
DELROUTE4,
DELROUTE6,
DELROUTE,
DELADDR4,
DELADDR6,
DELADDR,
DELNEIGH
};

ConnectivityStatus();
~ConnectivityStatus();

using ConnectionEventCb = std::function<void (Event)>;

void setEventListener (ConnectionEventCb ucb, Event);
void removeEventListener (Event);

private:

std::mutex mtx_;
std::unique_ptr<dht::Logger> logger_;

std::map<Event, ConnectionEventCb> event_cbs = {};

using NlMsgPtr = std::unique_ptr<nl_msg, void(*)(nl_msg *)>;
NlMsgPtr bye;
using NlPtr = std::unique_ptr<nl_sock, void(*)(nl_sock *)>;
NlPtr nlsk;
static NlPtr nlsk_init ();

void nlsk_setup (nl_sock*);
void nl_event_loop_thrd (nl_sock*);
void get_neigh_state (struct nl_msg*);
int nl_event_cb (struct nl_msg*);
void executer (Event);

std::atomic_bool stop {false};

std::thread thrd_;
};

} /* namespace net */
} /* namespace dht */
Loading

0 comments on commit 702889d

Please sign in to comment.