Merge branch 'master' of https://github.com/majestrate/llarp + gcc 7.2 fixes

This commit is contained in:
Ryan Tharp 2018-08-06 12:02:00 +00:00
commit 16c56ff04b
82 changed files with 4894 additions and 553 deletions

View File

@ -13,27 +13,37 @@ endmacro(add_cxxflags)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if (WIN32 AND NOT MINGW)
CHECK_CXX_COMPILER_FLAG("/std:c++17" COMPILER_SUPPORTS_CXX17)
else()
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
endif()
option(HAVE_CXX17_FILESYSTEM "Enable if your C++ compiler and runtime library implements std::[experimental::]filesystem" OFF)
if(COMPILER_SUPPORTS_CXX11 AND NOT HAVE_CXX17_FILESYSTEM)
add_cxxflags("-std=c++11")
elseif(COMPILER_SUPPORTS_CXX17)
elseif(COMPILER_SUPPORTS_CXX17 AND HAVE_CXX17_FILESYSTEM)
if (WIN32 AND NOT MINGW)
add_cxxflags("/std:c++17")
else()
add_cxxflags("-std=c++17")
endif()
add_definitions(-DUSE_CXX17_FILESYSTEM)
else()
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 or C++17 support. Please use a different C++ compiler.")
endif()
# attempting to fix linux gcc 7.2 which COMPILER_SUPPORTS_CXX17 but doesn't have filesystem.h
include(CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX(filesystem.h HAVE_STD_FS)
if(ANDROID)
set(THREAD_LIB "-pthread")
# finally removed pthread dependency for MSC++
elseif(WIN32 AND NOT MINGW)
set(THREAD_LIB)
else()
set(THREAD_LIB pthread)
endif()
if(STATIC_LINK)
set(STATIC_LINK_LIBS c)
add_cflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
add_cxxflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
endif()
@ -44,11 +54,18 @@ else()
set(WITH_STATIC ON)
endif()
if (UNIX OR MINGW OR APPLE)
add_cflags("-Wall")
add_cxxflags("-Wall")
endif()
set(DEBUG_FLAGS "-g")
if (WIN32 AND NOT MINGW)
set(OPTIMIZE_FLAGS "-Od")
set(DEBUG_FLAGS "-ZI")
else()
set(OPTIMIZE_FLAGS "-O0")
set(DEBUG_FLAGS "-g")
endif()
if(ASAN)
set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
@ -69,14 +86,18 @@ if(SHADOW)
include(ShadowTools)
add_cxxflags("-fno-inline -fno-strict-aliasing")
add_cflags("-fno-inline -fno-strict-aliasing")
add_definitions(-DTESTNET=true)
add_definitions(-DSHADOW_TESTNET)
include_directories(${SHADOW_ROOT}/include)
endif()
if (WIN32 AND NOT MINGW)
add_cflags("-wd4996 -wd4244 -MP ${OPTIMIZE_FLAGS}")
add_cxxflags("-wd4996 -wd4244 -MP ${OPTIMIZE_FLAGS}")
else()
add_cflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
add_cxxflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
endif()
if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
add_cflags("${DEBUG_FLAGS}")
@ -116,37 +137,50 @@ endif()
set(LIBS ${SODIUM_LIB} ${THREAD_LIB})
set(LIB llarp)
set(LIB lokinet)
set(SHARED_LIB ${LIB})
set(STATIC_LIB ${LIB}-static)
set(TT_ROOT vendor/libtuntap-master)
add_definitions(-D${CMAKE_SYSTEM_NAME})
if (UNIX)
add_definitions(-DUNIX)
endif()
if(UNIX)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-linux.c)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-linux.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-openbsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-netbsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-freebsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-darwin.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "DragonFly")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-freebsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-darwin.c ${TT_ROOT}/tuntap-unix-bsd.c)
else()
message(FATAL_ERROR "Your operating system is not supported yet")
endif()
elseif(WIN32 OR MINGW)
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-windows.c)
add_definitions(-DWIN32_LEAN_AND_MEAN)
else()
message(FATAL_ERROR "What operating system _are_ you building on/for?")
endif(UNIX)
if(TUNTAP)
set(LIBTUNTAP_SRC
${TT_ROOT}/tuntap.c
${TT_ROOT}/tuntap_log.c
if (UNIX)
${TT_ROOT}/tuntap-unix.c
endif()
${LIBTUNTAP_IMPL})
else()
set(LIBTUNTAP_SRC "")
@ -198,6 +232,11 @@ set(LIB_PLATFORM_SRC
llarp/threadpool.cpp
# for android shim
${ANDROID_PLATFORM_SRC}
# win32 inline procs
llarp/win32_inet.c
llarp/win32_intrnl.c
contrib/msc/getopt.c
contrib/msc/getopt1.c
)
@ -303,12 +342,16 @@ set(STATIC_LIB ${LIB}-static)
# TODO: exclude this from includes and expose stuff properly for rcutil
include_directories(llarp)
include_directories(include)
include_directories(vendor/cppbackport-master/lib)
#include_directories(/usr/local/include)
include_directories(${sodium_INCLUDE_DIR})
if (WIN32 AND NOT MINGW)
include_directories(contrib/msc/include)
link_directories(contrib/msc/lib)
endif()
if(SHADOW)
add_shadow_plugin(shadow-plugin-${SHARED_LIB} ${EXE_SRC} ${LIB_SRC})
target_link_libraries(shadow-plugin-${SHARED_LIB} ${LIBS})
@ -319,6 +362,8 @@ else()
add_executable(${CLIENT_EXE} ${CLIENT_SRC})
add_executable(dns ${DNS_SRC})
if(WITH_TESTS)
enable_testing()
add_subdirectory(${GTEST_DIR})
@ -330,62 +375,66 @@ else()
if(WITH_STATIC)
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(NOT HAVE_CXX17_FILESYSTEM)
add_library(backport-static STATIC ${CPP_BACKPORT_SRC})
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(NOT HAVE_CXX17_FILESYSTEM)
add_library(llarpplatform-static STATIC ${LIB_PLATFORM_SRC})
target_link_libraries(llarpplatform-static ${THREAD_LIB})
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(NOT HAVE_CXX17_FILESYSTEM)
target_link_libraries(${STATIC_LIB} ${LIBS} backport-static llarpplatform-static)
else()
target_link_libraries(${STATIC_LIB} ${LIBS} llarpplatform-static)
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(NOT HAVE_CXX17_FILESYSTEM)
if(NOT WITH_SHARED)
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(NOT HAVE_CXX17_FILESYSTEM)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
if (MINGW)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
endif(MINGW)
else()
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
if (MINGW)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
endif(MINGW)
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(NOT HAVE_CXX17_FILESYSTEM)
if (MINGW)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 stdc++fs)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 iphlpapi)
endif(MINGW)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB})
endif(NOT WITH_SHARED)
endif(WITH_STATIC)
if(ANDROID)
add_library(lokinetandroid SHARED jni/lokinet_android.cpp)
target_link_libraries(lokinetandroid ${STATIC_LIB} ${LIBS} log)
endif()
if(WITH_SHARED)
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(HAVE_CXX17_FILESYSTEM)
set(LIB_SRC ${LIB_SRC} ${CPP_BACKPORT_SRC})
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(HAVE_CXX17_FILESYSTEM)
add_library(${SHARED_LIB} SHARED ${LIB_SRC} ${LIB_PLATFORM_SRC})
if (MINGW)
set(${LIBS} ${LIBS} ws2_32 stdc++fs)
set(${LIBS} ${LIBS} ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
set(${LIBS} ${LIBS} ws2_32)
set(${LIBS} ${LIBS} ws2_32 iphlpapi)
endif(MINGW)
target_link_libraries(${SHARED_LIB} ${LIBS} ${THREAD_LIB})
target_link_libraries(${EXE} ${SHARED_LIB})

View File

@ -34,9 +34,10 @@ TESTNET_DEBUG ?= 0
clean:
rm -f build.ninja rules.ninja cmake_install.cmake CMakeCache.txt
rm -rf CMakeFiles
rm -f $(TARGETS) llarpd
rm -f $(TARGETS) llarpd llarpc dns rcutil testAll
rm -f $(SHADOW_PLUGIN) $(SHADOW_CONFIG)
rm -f *.sig
rm -f *.a *.so
debug-configure:
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DWITH_TESTS=ON -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)
@ -77,7 +78,10 @@ shadow-plot: shadow-run
shadow: shadow-plot
testnet-configure: clean
testnet-clean: clean
rm -rf $(TESTNET_ROOT)
testnet-configure: testnet-clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)
testnet-build: testnet-configure

1050
contrib/msc/getopt.c Normal file

File diff suppressed because it is too large Load Diff

190
contrib/msc/getopt1.c Normal file
View File

@ -0,0 +1,190 @@
#ifdef _MSC_VER
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "getopt.h"
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */
#endif /* _MSC_VER */

View File

@ -0,0 +1,157 @@
#ifdef _MSC_VER
/* Declarations for getopt.
Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if defined __STDC__ && __STDC__
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
# ifndef __need_getopt
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
# endif
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */
#endif /* _MSC_VER */

View File

@ -37,7 +37,8 @@ def main():
config = CP()
config['router'] = {
'net-threads': '1',
'worker-threads': '4'
'worker-threads': '4',
'nickname': svcNodeName(nodeid)
}
config['bind'] = {
args.ifname: str(args.baseport + nodeid)
@ -64,7 +65,8 @@ def main():
config['router'] = {
'net-threads': '1',
'worker-threads': '2'
'worker-threads': '2',
'nickname': clientNodeName(nodeid)
}
config['netdb'] = {
'dir': 'netdb'
@ -90,28 +92,31 @@ def main():
f.write('''[test-service]
tag=test
prefetch-tag=test
prefetch-tag=nonexist
''')
with open(args.out, 'w') as f:
f.write('''[program:svc-node]
directory = {}
command = {}
autorestart=true
redirect_stderr=true
stdout_logfile=/dev/fd/1
#stdout_logfile=/dev/fd/1
stdout_logfile={}/svc-node-%(process_num)03d-log.txt
stdout_logfile_maxbytes=0
process_name = svc-node-%(process_num)03d
numprocs = {}
'''.format(os.path.join(args.dir, 'svc-node-%(process_num)03d'), args.bin, args.svc))
'''.format(os.path.join(args.dir, 'svc-node-%(process_num)03d'), args.bin, args.dir, args.svc))
f.write('''[program:client-node]
directory = {}
command = {}
autorestart=true
redirect_stderr=true
stdout_logfile=/dev/fd/1
#stdout_logfile=/dev/fd/1
stdout_logfile={}/client-node-%(process_num)03d-log.txt
stdout_logfile_maxbytes=0
process_name = client-node-%(process_num)03d
numprocs = {}
'''.format(os.path.join(args.dir, 'client-node-%(process_num)03d'), args.bin, args.clients))
'''.format(os.path.join(args.dir, 'client-node-%(process_num)03d'),args.bin, args.dir, args.clients))
f.write('[supervisord]\ndirectory=.\n')

View File

@ -1,7 +1,9 @@
#include <getopt.h>
#include <signal.h>
#include <stdio.h> /* fprintf, printf */
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <llarp.h>
#include <llarp/logic.h>
@ -12,6 +14,17 @@
#include <thread> // for multithreaded version
#include <vector>
#include <algorithm> // for std::generate_n
// keep this once jeff reenables concurrency
#ifdef _MSC_VER
extern "C" void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#endif
#ifdef _WIN32
#define uint UINT
#endif
#if(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
#include <pthread_np.h>
@ -34,11 +47,11 @@ std::string const default_chars =
std::string random_string(size_t len = 15, std::string const &allowed_chars = default_chars) {
std::mt19937_64 gen { std::random_device()() };
std::uniform_int_distribution<size_t> dist { 0, allowed_chars.length()-1 };
std::string ret;
std::generate_n(std::back_inserter(ret), len, [&] { return allowed_chars[dist(gen)]; });
return ret;
}
@ -46,14 +59,14 @@ std::string random_string(size_t len = 15, std::string const &allowed_chars = de
/*
/// check_online_request hook definition
typedef void (*check_query_request_hook_func)(struct check_query_request *);
struct check_query_request
{
bool done;
///hook
check_query_request_hook_func hook;
};
void
llarp_dnsd_checkQuery_resolved(struct check_query_request *request)
{
@ -160,7 +173,7 @@ main(int argc, char *argv[])
iter.visit = &dns_iter_config;
llarp_config_iter(config_reader, &iter);
llarp::LogInfo("config [", conffname, "] loaded");
const uint16_t server_port = 1053;
// llarp::SetLogLevel(llarp::eLogDebug);
@ -171,7 +184,7 @@ main(int argc, char *argv[])
llarp_ev_loop *netloop = nullptr;
llarp_threadpool *worker = nullptr;
llarp_logic *logic = nullptr;
llarp_ev_loop_alloc(&netloop); // set up netio worker
worker = llarp_init_same_process_threadpool();
logic = llarp_init_single_process_logic(worker); // set up logic worker
@ -192,6 +205,7 @@ main(int argc, char *argv[])
llarp::LogInfo("singlethread start");
llarp_ev_loop_run_single_process(netloop, worker, logic);
llarp::LogInfo("singlethread end");
llarp_ev_loop_free(&netloop);
}
else
@ -201,7 +215,7 @@ main(int argc, char *argv[])
llarp_logic *logic = nullptr;
worker = llarp_init_same_process_threadpool();
logic = llarp_init_single_process_logic(worker); // set up logic worker
// configure main netloop
struct dnsd_context dnsd;
if(!llarp_dnsd_init(&dnsd, nullptr, logic, "*", server_port,
@ -214,7 +228,7 @@ main(int argc, char *argv[])
}
// Configure intercept
dnsd.intercept = &hookChecker;
struct sockaddr_in m_address;
int m_sockfd;
@ -239,7 +253,11 @@ main(int argc, char *argv[])
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000; // 1 sec
#ifndef _WIN32
if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
#else
if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) < 0)
#endif
{
perror("Error");
}

View File

@ -3,6 +3,11 @@
#include <signal.h>
#include <string>
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin
#endif
struct llarp_main *ctx = 0;
void

View File

@ -1,8 +1,8 @@
#include <getopt.h>
#include <llarp.h>
#include <signal.h>
#include "logger.hpp"
#include <getopt.h>
#include <llarp/router_contact.h>
#include <llarp/time.h>
@ -278,14 +278,18 @@ main(int argc, char *argv[])
// "encryption.key")
fs::path encryption_keyfile = "encryption.key";
llarp::SecretKey encryption;
llarp_findOrCreateEncryption(&crypt, encryption_keyfile.c_str(),
llarp_findOrCreateEncryption(&crypt, encryption_keyfile.string().c_str(),
&encryption);
llarp_rc_set_pubenckey(&tmp, llarp::seckey_topublic(encryption));
// get identity public sig key
fs::path ident_keyfile = "identity.key";
byte_t identity[SECKEYSIZE];
llarp_findOrCreateIdentity(&crypt, ident_keyfile.c_str(), identity);
llarp_findOrCreateIdentity(&crypt, ident_keyfile.string().c_str(),
identity);
llarp_rc_set_pubsigkey(&tmp, llarp::seckey_topublic(identity));
// this causes a segfault
@ -293,7 +297,8 @@ main(int argc, char *argv[])
// set filename
fs::path our_rc_file = rcfname;
// write file
llarp_rc_write(&tmp, our_rc_file.c_str());
llarp_rc_write(&tmp, our_rc_file.string().c_str());
// release memory for tmp lists
llarp_rc_free(&tmp);
}
@ -311,7 +316,8 @@ main(int argc, char *argv[])
llarp_crypto_libsodium_init(&crypt);
fs::path ident_keyfile = "identity.key";
byte_t identity[SECKEYSIZE];
llarp_findOrCreateIdentity(&crypt, ident_keyfile.c_str(), identity);
llarp_findOrCreateIdentity(&crypt, ident_keyfile.string().c_str(),
identity);
// get identity public key
uint8_t *pubkey = llarp::seckey_topublic(identity);
llarp_rc_set_pubsigkey(&rc, pubkey);
@ -320,7 +326,7 @@ main(int argc, char *argv[])
// set filename
fs::path our_rc_file_out = "update_debug.rc";
// write file
llarp_rc_write(&tmp, our_rc_file_out.c_str());
llarp_rc_write(&tmp, our_rc_file_out.string().c_str());
}
if(listMode)
{

74
development.md Normal file
View File

@ -0,0 +1,74 @@
## Building on Linux
# or your OS or distro's package manager
$ sudo apt install build-essential libtool autoconf cmake git
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make
## Building on Windows (mingw-w64 native, or wow64/linux/unix cross-compiler)
#i686 or x86_64
#if cross-compiling from anywhere other than wow64, export CC and CXX to
#$ARCH-w64-mingw32-g[cc++] respectively
$ pacman -Sy base-devel mingw-w64-$ARCH-toolchain git libtool autoconf cmake
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make ensure sodium
$ cd build
$ cmake ../deps/llarp -DSODIUM_LIBRARIES=./prefix/lib/libsodium.a -DSODIUM_INCLUDE_DIR=./prefix/include -G "Unix Makefiles" -DHAVE_CXX17_FILESYSTEM=ON
$ make
$ cp llarpd ../lokinet.exe
## Building on Windows using Microsoft C/C++ (Visual Studio 2017)
* clone https://github.com/loki-project/lokinet-builder from git-bash or whatever git browser you use
* open `%CLONE_PATH%/lokinet-builder/deps/sodium/builds/msvc/vs2017/libsodium.sln` and build one of the targets
* create a `build` folder in `%CLONE_PATH%/lokinet-builder`
* run cmake-gui from `%CLONE_PATH%/lokinet-builder/deps/llarp` as the source directory
* define `SODIUM_LIB` to `%CLONE_PATH%/lokinet-builder/deps/sodium/bin/win32/%CONFIG%/%TOOLSET%/%TARGET%/libsodium.lib`
* define `SODIUM_INCLUDE_DIR` to `%CLONE_PATH%/lokinet-builder/deps/sodium/src/libsodium/include`
* define `HAVE_CXX17_FILESYSTEM` to `TRUE`
* select `Visual Studio 2017 15 %ARCH%` as the generator
* enter a custom toolset if desired (usually `v141_xp`)
* generate the developer studio project files and open in the IDE
* select a configuration
* press F7 to build everything
## Running
$ ./lokinet
or press `Debug`/`Local Windows Debugger` in the visual studio standard toolbar
### Development
Please note development builds are likely to be unstable.
##### Build requirements:
* CMake
* ninja (for unit testing with Google Tests)
* libsodium >= 1.0.14 (included here)
* c++ 11 capable C++ compiler
* if you have C++17 `<filesystem>` or `<experimental/filesystem>` declared and defined in your platform's C++ toolchain, re-run CMake (in `lokinet-builder/build`) with `-DHAVE_CXX17_FILESYSTEM=ON`.
* since each platform seems to have its own idea of where `std::[experimental::]filesystem` is defined, you will need to manually specify its library in `LDFLAGS` or `CMAKE_x_LINKER_FLAGS` as well.
##### Windows:
* Mingw-w64 is recommended for 32 or 64-bit builds.
* It *is* possible to compile with Microsoft C++ (v19 or later from VS2015+).
* `cpp17::filesystem` in `vendor/cppbackport-master` is not available for Windows.
#### Boxed warning
<div style="border:5px solid #f00;padding:5px">
<p>Inbound sessions are unsupported on Windows Server systems.</p>
<p><strong><em>Ignore this warning at your own peril.</em></strong></p>
</div>
##### Building a debug build:
#in lokinet-builder/
$ cd build
$ make

View File

@ -121,6 +121,7 @@ router's full identity
{
a: [ one, or, many, AI, here ... ],
k: "<32 bytes public long term identity signing key>",
n: "<optional max 32 bytes router nickname>",
p: "<32 bytes public path encryption key>",
u: last_updated_seconds_since_epoch_uint64,
v: 0,

Binary file not shown.

View File

@ -3,8 +3,8 @@
#include <llarp.h>
#include <iostream>
#include <llarp/threading.hpp>
#include <string>
#include <thread>
#include <vector>
namespace llarp

View File

@ -87,4 +87,20 @@ llarp_buffer_read_until(llarp_buffer_t *buff, char delim, byte_t *result,
bool
llarp_buffer_eq(llarp_buffer_t buff, const char *data);
/// put big endian unsigned 16 bit integer
bool
llarp_buffer_put_uint16(llarp_buffer_t *buf, uint16_t i);
/// put big endian unsigned 32 bit integer
bool
llarp_buffer_put_uint32(llarp_buffer_t *buf, uint32_t i);
/// read big endian unsigned 16 bit integer
bool
llarp_buffer_read_uint16(llarp_buffer_t *buf, uint16_t *i);
/// read big endian unsigned 32 bit integer
bool
llarp_buffer_read_uint32(llarp_buffer_t *buf, uint32_t *i);
#endif

View File

@ -1,9 +1,13 @@
#ifndef LLARP_CODEL_QUEUE_HPP
#define LLARP_CODEL_QUEUE_HPP
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/time.h>
#include <llarp/logger.hpp>
#include <llarp/threading.hpp>
#include <algorithm>
#include <cmath>
#include <functional>

View File

@ -5,6 +5,7 @@
#include <llarp/dht/key.hpp>
#include <map>
#include <set>
#include <vector>
namespace llarp
{
@ -17,6 +18,22 @@ namespace llarp
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
bool
GetRandomNodeExcluding(Key_t& result,
const std::set< Key_t >& exclude) const
{
std::vector< Key_t > candidates;
for(const auto& item : nodes)
{
if(exclude.find(item.first) == exclude.end())
candidates.push_back(item.first);
}
if(candidates.size() == 0)
return false;
result = candidates[llarp_randint() % candidates.size()];
return true;
}
bool
FindClosest(const Key_t& target, Key_t& result) const
{

View File

@ -48,7 +48,8 @@ namespace llarp
void
LookupTag(const service::Tag& tag, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
bool iterative = false);
const std::set< service::IntroSet >& include = {},
uint64_t R = 0);
void
LookupRouterViaJob(llarp_router_lookup_job* job);
@ -57,6 +58,15 @@ namespace llarp
LookupTagForPath(const service::Tag& tag, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer);
void
LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer);
void
LookupIntroSetRelayed(const Key_t& requester, uint64_t txid,
const service::Address& addr, bool recursive,
std::vector< IMessage* >& reply);
std::set< service::IntroSet >
FindRandomIntroSetsWithTag(const service::Tag& tag, size_t max = 2);
@ -72,7 +82,7 @@ namespace llarp
void
PropagateIntroSetTo(const Key_t& from, uint64_t fromTX,
const service::IntroSet& introset, const Key_t& peer,
uint64_t S);
uint64_t S, const std::set< Key_t >& exclude);
void
Init(const Key_t& us, llarp_router* router);

View File

@ -4,6 +4,11 @@
#include <llarp/ev.h> // for sockaadr
#include <sys/types.h> // for uint & ssize_t
/* non-cygnus does not have this type */
#ifdef _WIN32
#define uint UINT
#endif
#ifdef __cplusplus
extern "C"
{

View File

@ -6,15 +6,12 @@
#include <inttypes.h>
#include <string.h>
#if defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/endian.h>
#elif defined(__linux__) || defined(__FreeBSD_kernel__) \
|| defined(__OpenBSD__) || defined(__GLIBC__)
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GLIBC__)
#include <endian.h>
#elif defined(__APPLE__) && defined(__MACH__)
#include <libkern/OSByteOrder.h>
#define htobe16(x) OSSwapHostToBigInt16(x)
#define htole16(x) OSSwapHostToLittleInt16(x)
#define be16toh(x) OSSwapBigToHostInt16(x)
@ -29,7 +26,26 @@
#define htole64(x) OSSwapHostToLittleInt64(x)
#define be64toh(x) OSSwapBigToHostInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x)
#elif defined(_WIN32)
#include <winsock2.h>
#define htobe16(x) htons(x)
#define htole16(x) (x)
#define be16toh(x) ntohs(x)
#define le16toh(x) (x)
#define htobe32(x) htonl(x)
#define htole32(x) (x)
#define be32toh(x) ntohl(x)
#define le32toh(x) (x)
#define htobe64(x) \
(((uint64_t)htonl(((uint32_t)(((uint64_t)(x)) >> 32)))) \
| (((uint64_t)htonl(((uint32_t)(x)))) << 32))
#define htole64(x) (x)
#define be64toh(x) \
(((uint64_t)ntohl(((uint32_t)(((uint64_t)(x)) >> 32)))) \
| (((uint64_t)ntohl(((uint32_t)(x)))) << 32))
#define le64toh(x) (x)
#else
#define NEEDS_LOCAL_ENDIAN
#include <cstdint>

View File

@ -1,8 +1,12 @@
#ifndef LLARP_EV_H
#define LLARP_EV_H
#if defined(__MINGW32__)
#if defined(__MINGW32__) || defined(_WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#ifndef ssize_t
#define ssize_t long
#endif
#else
#include <netinet/in.h>
#include <sys/socket.h>
@ -12,10 +16,10 @@
#include <stdlib.h>
/**
* ev.h
*
* event handler (cross platform high performance event system for IO)
*/
* ev.h
*
* event handler (cross platform high performance event system for IO)
*/
// forward declare
struct llarp_threadpool;

View File

@ -1,15 +1,21 @@
#ifndef LLARP_LOGGER_H
#define LLARP_LOGGER_H
enum LogLevel
extern "C"
{
eLogDebug,
eLogInfo,
eLogWarn,
eLogError
};
enum LogLevel
{
eLogDebug,
eLogInfo,
eLogWarn,
eLogError
};
void
cSetLogLevel(enum LogLevel lvl);
void
cSetLogLevel(enum LogLevel lvl);
void
cSetLogNodeName(const char* name);
}
#endif

View File

@ -1,6 +1,5 @@
#ifndef LLARP_LOGGER_HPP
#define LLARP_LOGGER_HPP
#include <llarp/time.h>
#include <ctime>
#include <iomanip>
@ -8,6 +7,13 @@
#include <llarp/threading.hpp>
#include <sstream>
#include <string>
#ifdef _WIN32
#define VC_EXTRALEAN
#include <windows.h>
#endif
#ifdef ANDROID
#include <android/log.h>
#endif
namespace llarp
{
@ -22,13 +28,23 @@ namespace llarp
struct Logger
{
std::string nodeName;
LogLevel minlevel = eLogInfo;
std::ostream& out;
std::mutex access;
Logger() : Logger(std::cout)
Logger() : Logger(std::cout, "unnamed")
{
#ifdef _WIN32
DWORD mode_flags;
HANDLE fd1 = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(fd1, &mode_flags);
// since release SDKs don't have ANSI escape support yet
mode_flags |= 0x0004;
SetConsoleMode(fd1, mode_flags);
#endif
}
Logger(std::ostream& o) : out(o)
Logger(std::ostream& o, const std::string& name) : nodeName(name), out(o)
{
}
};
@ -57,12 +73,29 @@ namespace llarp
/** internal */
template < typename... TArgs >
void
_Log(LogLevel lvl, const char* fname, TArgs&&... args) noexcept
_Log(LogLevel lvl, const char* fname, int lineno, TArgs&&... args) noexcept
{
if(_glog.minlevel > lvl)
return;
std::stringstream ss;
#ifdef ANDROID
switch(lvl)
{
case eLogDebug:
ss << "[DBG] ";
break;
case eLogInfo:
ss << "[NFO] ";
break;
case eLogWarn:
ss << "[WRN] ";
break;
case eLogError:
ss << "[ERR] ";
break;
}
#else
switch(lvl)
{
case eLogDebug:
@ -82,34 +115,45 @@ namespace llarp
ss << "[ERR] ";
break;
}
#endif
std::string tag = fname;
ss << llarp_time_now_ms() << " " << tag;
ss << _glog.nodeName << " " << llarp_time_now_ms() << " " << tag << ":"
<< lineno;
ss << "\t";
LogAppend(ss, std::forward< TArgs >(args)...);
#ifndef ANDROID
ss << (char)27 << "[0;0m";
#else
{
std::unique_lock< std::mutex > lock(_glog.access);
_glog.out << ss.str() << std::endl;
#ifdef SHADOW_TESTNET
__android_log_write(ANDROID_LOG_INFO, "LOKINET", ss.str().c_str());
_glog.out << "\n" << std::flush;
#endif
}
#endif
}
} // namespace llarp
#define LogDebug(x, ...) \
_Log(llarp::eLogDebug, LOG_TAG, __LINE__, x, ##__VA_ARGS__)
#define LogInfo(x, ...) \
_Log(llarp::eLogInfo, LOG_TAG, __LINE__, x, ##__VA_ARGS__)
#define LogWarn(x, ...) \
_Log(llarp::eLogWarn, LOG_TAG, __LINE__, x, ##__VA_ARGS__)
#define LogError(x, ...) \
_Log(llarp::eLogError, LOG_TAG, __LINE__, x, ##__VA_ARGS__)
#define LogDebugTag(tag, x, ...) \
_Log(llarp::eLogDebug, tag, __LINE__, x, ##__VA_ARGS__)
#define LogInfoTag(tag, x, ...) \
_Log(llarp::eLogInfo, tag, __LINE__, x, ##__VA_ARGS__)
#define LogWarnTag(tag, x, ...) \
_Log(llarp::eLogWarn, tag, __LINE__, x, ##__VA_ARGS__)
#define LogErrorTag(tag, x, ...) \
_Log(llarp::eLogError, tag, __LINE__, x, ##__VA_ARGS__)
#ifndef LOG_TAG
#define LOG_TAG "default"
#endif
#define LogDebug(x, ...) _Log(llarp::eLogDebug, LOG_TAG, x, ##__VA_ARGS__)
#define LogInfo(x, ...) _Log(llarp::eLogInfo, LOG_TAG, x, ##__VA_ARGS__)
#define LogWarn(x, ...) _Log(llarp::eLogWarn, LOG_TAG, x, ##__VA_ARGS__)
#define LogError(x, ...) _Log(llarp::eLogError, LOG_TAG, x, ##__VA_ARGS__)
#define LogDebugTag(tag, x, ...) _Log(llarp::eLogDebug, tag, x, ##__VA_ARGS__)
#define LogInfoTag(tag, x, ...) _Log(llarp::eLogInfo, tag, x, ##__VA_ARGS__)
#define LogWarnTag(tag, x, ...) _Log(llarp::eLogWarn, tag, x, ##__VA_ARGS__)
#define LogErrorTag(tag, x, ...) _Log(llarp::eLogError, tag, x, ##__VA_ARGS__)
#endif

View File

@ -1,8 +1,27 @@
#ifndef LLARP_NET_H
#define LLARP_NET_H
#if defined(__MINGW32__)
#if defined(_WIN32) || defined(__MINGW32__)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
// because this shit is not defined for Windows NT reeeee
#ifndef _MSC_VER
#ifdef __cplusplus
extern "C" {
#endif
const char*
inet_ntop(int af, const void* src, char* dst, size_t size);
int
inet_pton(int af, const char* src, void* dst);
#ifdef __cplusplus
}
#endif
#endif
#ifndef ssize_t
#define ssize_t long
#endif
typedef unsigned short in_port_t;
typedef unsigned int in_addr_t;
#else
#include <arpa/inet.h>
#include <netinet/in.h>

View File

@ -121,7 +121,11 @@ namespace llarp
sz = sizeof(sockaddr_in);
ptr = a.addr4();
}
#ifndef _MSC_VER
if(inet_ntop(a.af(), ptr, tmp, sz))
#else
if(inet_ntop(a.af(), (void*)ptr, tmp, sz))
#endif
{
out << tmp;
if(a.af() == AF_INET6)
@ -236,7 +240,7 @@ namespace llarp
{
if(a.af() == AF_INET)
{
return a.port() + a.addr4()->s_addr;
return a.port() ^ a.addr4()->s_addr;
}
uint8_t empty[16] = {0};
return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port();

View File

@ -163,6 +163,14 @@ namespace llarp
HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg,
llarp_router* r);
bool
HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* frame)
{
/// TODO: implement me
llarp::LogWarn("Got hidden service data on transit hop");
return false;
}
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
@ -207,6 +215,9 @@ namespace llarp
{
typedef std::function< void(Path*) > BuildResultHookFunc;
typedef std::vector< PathHopConfig > HopList;
typedef std::function< bool(const service::ProtocolFrame*) >
DataHandlerFunc;
HopList hops;
llarp::service::Introduction intro;
@ -219,6 +230,12 @@ namespace llarp
void
SetBuildResultHook(BuildResultHookFunc func);
void
SetDataHandler(DataHandlerFunc func)
{
m_DataHandler = func;
}
bool
Expired(llarp_time_t now) const;
@ -240,6 +257,9 @@ namespace llarp
HandlePathTransferMessage(const llarp::routing::PathTransferMessage* msg,
llarp_router* r);
bool
HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* frame);
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
@ -279,6 +299,7 @@ namespace llarp
private:
BuildResultHookFunc m_BuiltHook;
DataHandlerFunc m_DataHandler;
llarp_time_t m_LastLatencyTestTime = 0;
uint64_t m_LastLatencyTestID = 0;
};

View File

@ -2,12 +2,14 @@
#define LLARP_PATHBUILDER_HPP_
#include <llarp/pathbuilder.h>
#include <llarp/router.h>
#include <llarp/path.hpp>
#include <llarp/pathset.hpp>
struct llarp_pathbuilder_context : public llarp::path::PathSet
{
struct llarp_router* router;
struct llarp_dht_context* dht;
llarp::SecretKey enckey;
size_t numHops;
/// construct
llarp_pathbuilder_context(llarp_router* p_router,
@ -21,6 +23,9 @@ struct llarp_pathbuilder_context : public llarp::path::PathSet
void
BuildOne();
virtual byte_t*
GetTunnelEncryptionSecretKey();
};
#endif

View File

@ -44,14 +44,14 @@ namespace llarp
void
RemovePath(Path* path);
void
virtual void
HandlePathBuilt(Path* path);
void
AddPath(Path* path);
Path*
GetByUpstream(const RouterID& remote, const PathID_t& rxid);
GetByUpstream(const RouterID& remote, const PathID_t& rxid) const;
void
ExpirePaths(llarp_time_t now);
@ -79,10 +79,13 @@ namespace llarp
}
Path*
PickRandomEstablishedPath();
GetEstablishedPathClosestTo(const RouterID& router) const;
Path*
GetPathByRouter(const RouterID& router);
PickRandomEstablishedPath() const;
Path*
GetPathByRouter(const RouterID& router) const;
bool
GetCurrentIntroductions(

View File

@ -4,11 +4,16 @@
#include <llarp/crypto.h>
#include <llarp/exit_info.h>
#ifdef __cplusplus
#include <string>
#endif
// forward declare
struct llarp_alloc;
struct llarp_rc;
#define MAX_RC_SIZE (1024)
#define NICKLEN (32)
bool
llarp_rc_bdecode(struct llarp_rc *rc, llarp_buffer_t *buf);
@ -24,6 +29,9 @@ struct llarp_rc
byte_t pubkey[PUBKEYSIZE];
struct llarp_xi_list *exits;
byte_t signature[SIGSIZE];
/// node nickname, yw kee
byte_t nickname[NICKLEN];
uint64_t last_updated;
#ifdef __cplusplus
@ -38,6 +46,14 @@ struct llarp_rc
{
return llarp_rc_bdecode(this, buf);
}
std::string
Nick() const
{
const char *nick = (const char *)nickname;
return std::string(nick, strnlen(nick, sizeof(nickname)));
}
#endif
};
@ -60,6 +76,9 @@ void
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
struct llarp_ai_list *addr);
bool
llarp_rc_set_nickname(struct llarp_rc *rc, const char *name);
void
llarp_rc_set_pubenckey(struct llarp_rc *rc, const uint8_t *pubenckey);

View File

@ -21,10 +21,7 @@ namespace llarp
llarp_router *r) = 0;
virtual bool
HandleHiddenServiceFrame(const service::ProtocolFrame *msg)
{
return false;
}
HandleHiddenServiceFrame(const service::ProtocolFrame *msg) = 0;
virtual bool
HandlePathConfirmMessage(const PathConfirmMessage *msg,

View File

@ -13,6 +13,9 @@ namespace llarp
std::string
ToString() const;
bool
FromString(const std::string& str);
Address() : llarp::AlignedBuffer< 32 >()
{
}

View File

@ -9,7 +9,7 @@ namespace llarp
{
namespace service
{
struct Endpoint : public llarp_pathbuilder_context
struct Endpoint : public llarp_pathbuilder_context, public ILookupHolder
{
/// minimum interval for publishing introsets
static const llarp_time_t INTROSET_PUBLISH_INTERVAL =
@ -74,6 +74,12 @@ namespace llarp
return &m_Identity;
}
void
PutLookup(IServiceLookup* lookup, uint64_t txid);
void
HandlePathBuilt(path::Path* path);
/// context needed to initiate an outbound hidden service session
struct OutboundContext : public llarp_pathbuilder_context
{
@ -102,12 +108,24 @@ namespace llarp
void
UpdateIntroSet();
void
HandlePathBuilt(path::Path* path);
bool
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleHiddenServiceFrame(const ProtocolFrame* frame);
void
PutLookup(IServiceLookup* lookup, uint64_t txid);
std::string
Name() const;
private:
void
AsyncEncrypt(llarp_buffer_t payload);
@ -122,6 +140,7 @@ namespace llarp
uint64_t sequenceNo = 0;
llarp::SharedSecret sharedKey;
Endpoint* m_Parent;
uint64_t m_UpdateIntrosetTX = 0;
};
// passed a sendto context when we have a path established otherwise
@ -176,6 +195,8 @@ namespace llarp
service::IntroSet m_IntroSet;
/// pending remote service lookups by id
std::unordered_map< uint64_t, service::IServiceLookup* > m_PendingLookups;
/// prefetch remote address list
std::set< Address > m_PrefetchAddrs;
/// hidden service tag
Tag m_Tag;
/// prefetch descriptors for these hidden service tags
@ -185,13 +206,12 @@ namespace llarp
{
const static llarp_time_t TTL = 10000;
llarp_time_t lastRequest = 0;
llarp_time_t lastModified;
uint64_t pendingTX = 0;
llarp_time_t lastModified = 0;
std::set< IntroSet > result;
Tag tag;
CachedTagResult(const Tag& t, llarp_time_t now)
: lastModified(now), tag(t)
CachedTagResult(Endpoint* p, const Tag& t, uint64_t tx)
: IServiceLookup(p, tx), tag(t)
{
}
@ -205,7 +225,7 @@ namespace llarp
{
if(now <= lastRequest)
return false;
return (now - lastRequest) > TTL && pendingTX == 0;
return (now - lastRequest) > TTL;
}
llarp::routing::IMessage*

View File

@ -16,11 +16,11 @@ namespace llarp
namespace service
{
struct ILookupHolder;
struct IServiceLookup
{
IServiceLookup() : m_created(llarp_time_now_ms())
{
}
IServiceLookup(ILookupHolder* parent, uint64_t tx);
virtual ~IServiceLookup(){};
@ -45,10 +45,19 @@ namespace llarp
bool
SendRequestViaPath(llarp::path::Path* p, llarp_router* r);
private:
ILookupHolder* parent;
uint64_t txid;
protected:
llarp_time_t m_created;
};
struct ILookupHolder
{
virtual void
PutLookup(IServiceLookup* l, uint64_t txid) = 0;
};
} // namespace service
} // namespace llarp

View File

@ -45,7 +45,6 @@ namespace llarp
struct ProtocolFrame : public llarp::routing::IMessage
{
llarp::Encrypted D;
uint64_t S = 0;
llarp::PubKey H;
llarp::KeyExchangeNonce N;
llarp::Signature Z;

View File

@ -1,7 +1,7 @@
#ifndef LLARP_THREADING_HPP
#define LLARP_THREADING_HPP
#include <mutex>
#if defined(__MINGW32__)
#if defined(__MINGW32__) && !defined(_GLIBCXX_HAS_GTHREADS)
#include <llarp/win32/threads/mingw.condition_variable.h>
#include <llarp/win32/threads/mingw.mutex.h>
#include <llarp/win32/threads/mingw.thread.h>

98
jni/lokinet_android.cpp Executable file
View File

@ -0,0 +1,98 @@
//#include <string.h>
#include <jni.h>
#include <llarp.h>
#include <signal.h>
#include <memory>
#include <thread>
struct AndroidMain
{
llarp_main* m_impl = nullptr;
std::thread* m_thread = nullptr;
bool
Start(const char* conf)
{
if(m_impl || m_thread)
return true;
if(!llarp_ensure_config(conf))
return false;
m_impl = llarp_main_init(conf, true);
if(m_impl == nullptr)
return false;
m_thread = new std::thread(std::bind(&AndroidMain::Run, this));
return true;
}
bool
Running() const
{
return m_impl != nullptr;
}
void
Run()
{
printf("running\n");
llarp_main_run(m_impl);
}
void
Stop()
{
llarp_main_signal(m_impl, SIGINT);
m_thread->join();
delete m_thread;
m_thread = nullptr;
llarp_main_free(m_impl);
m_impl = nullptr;
}
typedef std::unique_ptr< AndroidMain > Ptr;
};
static AndroidMain::Ptr daemon(new AndroidMain());
extern "C"
{
JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledWith(JNIEnv* env, jclass)
{
// TODO: fixme
return env->NewStringUTF("android");
}
JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv* env, jclass jcl,
jstring configfile)
{
if(daemon->Running())
return env->NewStringUTF("already running");
std::string conf;
{
const char* nativeString = env->GetStringUTFChars(configfile, JNI_FALSE);
conf += std::string(nativeString);
env->ReleaseStringUTFChars(configfile, nativeString);
}
if(daemon->Start(conf.c_str()))
return env->NewStringUTF("ok");
else
return env->NewStringUTF("failed to start");
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv* env, jclass)
{
if(daemon->Running())
{
daemon->Stop();
}
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged(JNIEnv*, jclass,
jboolean)
{
}
}

View File

@ -0,0 +1,45 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class network_loki_lokinet_Lokinet_JNI */
#ifndef _Included_network_loki_lokinet_Lokinet_JNI
#define _Included_network_loki_lokinet_Lokinet_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: network_loki_lokinet_Lokinet_JNI
* Method: getABICompiledWith
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledWith
(JNIEnv *, jclass);
/*
* Class: network_loki_lokinet_Lokinet_JNI
* Method: startLokinet
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_startLokinet
(JNIEnv *, jclass, jstring);
/*
* Class: network_loki_lokinet_Lokinet_JNI
* Method: stopLokinet
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet
(JNIEnv *, jclass);
/*
* Class: network_loki_lokinet_Lokinet_JNI
* Method: onNetworkStateChanged
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged
(JNIEnv *, jclass, jboolean);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,5 +1,7 @@
#include "address_info.hpp"
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include <llarp/bencode.h>
#include <llarp/mem.h>
#include <llarp/string.h>
@ -120,8 +122,12 @@ llarp_ai_list_iter_bencode(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
bool
llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
{
#ifndef _MSC_VER
struct dict_reader reader = {
.buffer = nullptr, .user = ai, .on_key = &llarp_ai_decode_key};
#else
struct dict_reader reader = { nullptr, ai, &llarp_ai_decode_key };
#endif
return bencode_read_dict(buff, &reader);
}
@ -174,8 +180,13 @@ llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
if(!bencode_start_list(buff))
return false;
#ifndef _MSC_VER
struct llarp_ai_list_iter ai_itr = {
.user = buff, .list = nullptr, .visit = &llarp_ai_list_iter_bencode};
#else
struct llarp_ai_list_iter ai_itr = {buff, nullptr,
&llarp_ai_list_iter_bencode};
#endif
llarp_ai_list_iterate(l, &ai_itr);
return bencode_end(buff);
}
@ -255,7 +266,12 @@ llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx, struct llarp_ai *dst)
bool
llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
#ifndef _MSC_VER
struct list_reader r = {
.buffer = nullptr, .user = l, .on_item = &llarp_ai_list_bdecode_item};
#else
struct list_reader r = {
nullptr, l, &llarp_ai_list_bdecode_item};
#endif
return bencode_read_list(buff, &r);
}

View File

@ -1,7 +1,11 @@
#include <llarp/buffer.h>
#include <llarp/endian.h>
#include <stdarg.h>
#include <stdio.h>
#ifndef ssize_t
#define ssize_t long
#endif
size_t
llarp_buffer_size_left(llarp_buffer_t buff)
{
@ -76,3 +80,42 @@ llarp_buffer_eq(llarp_buffer_t buf, const char* str)
}
return *str == 0;
}
bool
llarp_buffer_put_uint16(llarp_buffer_t* buf, uint16_t i)
{
if(llarp_buffer_size_left(*buf) < sizeof(uint16_t))
return false;
htobe16buf(buf->cur, i);
buf->cur += sizeof(uint16_t);
return true;
}
bool
llarp_buffer_put_uint32(llarp_buffer_t* buf, uint32_t i)
{
if(llarp_buffer_size_left(*buf) < sizeof(uint32_t))
return false;
htobe32buf(buf->cur, i);
buf->cur += sizeof(uint32_t);
return true;
}
bool
llarp_buffer_read_uint16(llarp_buffer_t* buf, uint16_t* i)
{
if(llarp_buffer_size_left(*buf) < sizeof(uint16_t))
return false;
*i = bufbe16toh(buf->cur);
buf->cur += sizeof(uint16_t);
return true;
}
bool
llarp_buffer_put_uint32(llarp_buffer_t* buf, uint32_t* i)
{
if(llarp_buffer_size_left(*buf) < sizeof(uint32_t))
return false;
*i = bufbe32toh(buf->cur);
buf->cur += sizeof(uint32_t);
return true;
}

View File

@ -2,7 +2,9 @@
#include <llarp.h>
#include <llarp/logger.h>
#include <signal.h>
#ifndef _MSC_VER
#include <sys/param.h> // for MIN
#endif
#include <llarp.hpp>
#include "logger.hpp"
#include "math.h"
@ -12,6 +14,16 @@
#include <pthread_np.h>
#endif
// keep this once jeff reenables concurrency
#ifdef _MSC_VER
extern "C" void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#endif
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin
#endif
namespace llarp
{
@ -188,6 +200,7 @@ namespace llarp
}
else
{
llarp::LogInfo("running mainloop");
return llarp_ev_loop_run(mainloop, logic);
}
@ -202,11 +215,14 @@ namespace llarp
llarp::LogInfo("SIGINT");
SigINT();
}
// TODO(despair): implement hot-reloading config on NT
#ifndef _WIN32
if(sig == SIGHUP)
{
llarp::LogInfo("SIGHUP");
ReloadConfig();
}
#endif
}
void
@ -289,194 +305,194 @@ extern "C"
struct llarp_main *
llarp_main_init(const char *fname, bool multiProcess)
{
if(!fname)
fname = "daemon.ini";
char *var = getenv("LLARP_DEBUG");
if(var && *var == '1')
{
cSetLogLevel(eLogDebug);
}
llarp_main *m = new llarp_main;
m->ctx.reset(new llarp::Context());
m->ctx->singleThreaded = !multiProcess;
if(!m->ctx->LoadConfig(fname))
{
m->ctx->Close();
delete m;
return nullptr;
}
return m;
if(!fname)
fname = "daemon.ini";
char *var = getenv("LLARP_DEBUG");
if(var && *var == '1')
{
cSetLogLevel(eLogDebug);
}
llarp_main *m = new llarp_main;
m->ctx.reset(new llarp::Context());
m->ctx->singleThreaded = !multiProcess;
if(!m->ctx->LoadConfig(fname))
{
m->ctx->Close();
delete m;
return nullptr;
}
return m;
}
void
llarp_main_signal(struct llarp_main *ptr, int sig)
{
ptr->ctx->HandleSignal(sig);
ptr->ctx->HandleSignal(sig);
}
int
llarp_main_setup(struct llarp_main *ptr)
{
return ptr->ctx->Setup();
return ptr->ctx->Setup();
}
int
llarp_main_run(struct llarp_main *ptr)
{
return ptr->ctx->Run();
return ptr->ctx->Run();
}
void
llarp_main_abort(struct llarp_main *ptr)
{
llarp_logic_stop_timer(ptr->ctx->router->logic);
llarp_logic_stop_timer(ptr->ctx->router->logic);
}
int
llarp_main_loadDatabase(struct llarp_main *ptr)
{
return ptr->ctx->LoadDatabase();
return ptr->ctx->LoadDatabase();
}
int
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i)
{
return ptr->ctx->IterateDatabase(i);
return ptr->ctx->IterateDatabase(i);
}
bool
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc)
{
return ptr->ctx->PutDatabase(rc);
return ptr->ctx->PutDatabase(rc);
}
struct llarp_rc *
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk)
{
return ptr->ctx->GetDatabase(pk);
return ptr->ctx->GetDatabase(pk);
}
struct llarp_rc *
llarp_main_getLocalRC(struct llarp_main *ptr)
{
//
/*
llarp_config_iterator iter;
iter.user = this;
iter.visit = &iter_config;
llarp_config_iter(ctx->config, &iter);
*/
llarp_rc *rc = new llarp_rc;
llarp_rc_new(rc);
llarp::LogInfo("Loading ", ptr->ctx->conatctFile);
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
return rc;
else
return nullptr;
//
/*
llarp_config_iterator iter;
iter.user = this;
iter.visit = &iter_config;
llarp_config_iter(ctx->config, &iter);
*/
llarp_rc *rc = new llarp_rc;
llarp_rc_new(rc);
llarp::LogInfo("Loading ", ptr->ctx->conatctFile);
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
return rc;
else
return nullptr;
}
void
llarp_main_checkOnline(void *u, uint64_t orig, uint64_t left)
{
// llarp::LogInfo("checkOnline - check ", left);
if(left)
return;
struct check_online_request *request =
static_cast< struct check_online_request * >(u);
// llarp::LogDebug("checkOnline - running");
// llarp::LogInfo("checkOnline - DHT nodes ",
// request->ptr->ctx->router->dht->impl.nodes->nodes.size());
request->online = false;
request->nodes = request->ptr->ctx->router->dht->impl.nodes->nodes.size();
if(request->ptr->ctx->router->dht->impl.nodes->nodes.size())
{
// llarp::LogInfo("checkOnline - Going to say we're online");
request->online = true;
}
request->hook(request);
// reschedue our self
llarp_main_queryDHT(request);
// llarp::LogInfo("checkOnline - check ", left);
if(left)
return;
struct check_online_request *request =
static_cast< struct check_online_request * >(u);
// llarp::LogDebug("checkOnline - running");
// llarp::LogInfo("checkOnline - DHT nodes ",
// request->ptr->ctx->router->dht->impl.nodes->nodes.size());
request->online = false;
request->nodes = request->ptr->ctx->router->dht->impl.nodes->nodes.size();
if(request->ptr->ctx->router->dht->impl.nodes->nodes.size())
{
// llarp::LogInfo("checkOnline - Going to say we're online");
request->online = true;
}
request->hook(request);
// reschedue our self
llarp_main_queryDHT(request);
}
void
llarp_main_queryDHT_online(struct check_online_request *request)
{
// Info("llarp_main_queryDHT_online: ", request->online ? "online" :
// "offline");
if(request->online && !request->first)
{
request->first = true;
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
}
// Info("llarp_main_queryDHT_online: ", request->online ? "online" :
// "offline");
if(request->online && !request->first)
{
request->first = true;
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
}
}
void
llarp_main_queryDHT(struct check_online_request *request)
{
// llarp::LogInfo("llarp_main_queryDHT - setting up timer");
request->hook = &llarp_main_queryDHT_online;
llarp_logic_call_later(request->ptr->ctx->router->logic,
{1000, request, &llarp_main_checkOnline});
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
// llarp::LogInfo("llarp_main_queryDHT - setting up timer");
request->hook = &llarp_main_queryDHT_online;
llarp_logic_call_later(request->ptr->ctx->router->logic,
{1000, request, &llarp_main_checkOnline});
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
}
void
llarp_main_free(struct llarp_main *ptr)
{
delete ptr;
delete ptr;
}
const char *
handleBaseCmdLineArgs(int argc, char *argv[])
{
const char *conffname = "daemon.ini";
int c;
while(1)
const char *conffname = "daemon.ini";
int c;
while(1)
{
static struct option long_options[] = {
{"config", required_argument, 0, 'c'},
{"logLevel", required_argument, 0, 'o'},
{0, 0, 0, 0}};
int option_index = 0;
c = getopt_long(argc, argv, "c:o:", long_options, &option_index);
if(c == -1)
break;
switch(c)
{
static struct option long_options[] = {
{"config", required_argument, 0, 'c'},
{"logLevel", required_argument, 0, 'o'},
{0, 0, 0, 0}};
int option_index = 0;
c = getopt_long(argc, argv, "c:o:", long_options, &option_index);
if(c == -1)
case 0:
break;
switch(c)
{
case 0:
break;
case 'c':
conffname = optarg;
break;
case 'o':
case 'c':
conffname = optarg;
break;
case 'o':
if(strncmp(optarg, "debug", MIN(strlen(optarg), (unsigned long)5))
== 0)
{
cSetLogLevel(eLogDebug);
}
else if(strncmp(optarg, "info", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogInfo);
}
else if(strncmp(optarg, "warn", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogWarn);
}
{
cSetLogLevel(eLogDebug);
}
else if(strncmp(optarg, "info", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogInfo);
}
else if(strncmp(optarg, "warn", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogWarn);
}
else if(strncmp(optarg, "error",
MIN(strlen(optarg), (unsigned long)5))
== 0)
{
cSetLogLevel(eLogError);
}
break;
default:
break;
}
== 0)
{
cSetLogLevel(eLogError);
}
break;
default:
break;
}
return conffname;
}
return conffname;
}
}

View File

@ -256,6 +256,10 @@ namespace iwp
{
iwp_async_session_start *session =
static_cast< iwp_async_session_start * >(user);
// possible repeat job
if(session->buf == nullptr)
return;
auto crypto = session->iwp->crypto;
auto logic = session->iwp->logic;

View File

@ -26,7 +26,7 @@ namespace llarp
if(crypto_scalarmult_curve25519(shared, usSec, themPub))
return false;
crypto_generichash_init(&h, NULL, 0U, outsz);
crypto_generichash_init(&h, nullptr, 0U, outsz);
crypto_generichash_update(&h, client_pk, 32);
crypto_generichash_update(&h, server_pk, 32);
crypto_generichash_update(&h, shared, 32);

View File

@ -38,7 +38,10 @@ namespace llarp
while(itr != nodes.end())
{
if(itr->second.introset.IsExpired(now))
{
llarp::LogInfo("introset expired ", itr->second.introset.A.Addr());
itr = nodes.erase(itr);
}
else
++itr;
}
@ -46,13 +49,15 @@ namespace llarp
ctx->ScheduleCleanupTimer();
}
struct PathTagLookupJob
struct PathLookupJob
{
uint64_t txid;
PathID_t pathID;
llarp_router *m_router;
std::set< service::IntroSet > localtags;
PathTagLookupJob(llarp_router *r, const PathID_t &localpath, uint64_t tx)
std::set< service::IntroSet > localIntroSets;
std::set< Key_t > asked;
PathLookupJob(llarp_router *r, const PathID_t &localpath, uint64_t tx)
: txid(tx), pathID(localpath), m_router(r)
{
}
@ -66,15 +71,16 @@ namespace llarp
{
for(const auto &introset : results)
{
localtags.insert(introset);
localIntroSets.insert(introset);
}
llarp::routing::DHTMessage msg;
auto sz = localtags.size();
auto sz = localIntroSets.size();
std::vector< service::IntroSet > intros(sz);
for(const auto &i : localtags)
for(const auto &i : localIntroSets)
{
intros[--sz] = i;
}
llarp::LogInfo("found ", sz, " introsets for txid=", txid);
msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid));
path->SendRoutingMessage(&msg, m_router);
}
@ -90,12 +96,17 @@ namespace llarp
void
Context::PropagateIntroSetTo(const Key_t &from, uint64_t txid,
const service::IntroSet &introset,
const Key_t &peer, uint64_t S)
const Key_t &peer, uint64_t S,
const std::set< Key_t > &exclude)
{
llarp::LogInfo("Propagate Introset for ", introset.A.Name(), " to ",
peer);
auto id = ++ids;
std::vector< Key_t > E;
for(const auto &ex : exclude)
E.push_back(ex);
TXOwner ownerKey;
ownerKey.node = peer;
ownerKey.txid = id;
@ -103,7 +114,7 @@ namespace llarp
[](const std::vector< service::IntroSet > &) {});
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(peer);
msg->msgs.push_back(new PublishIntroMessage(introset, id, S));
msg->msgs.push_back(new PublishIntroMessage(introset, id, S, E));
router->SendToOrQueue(peer, msg);
}
@ -113,17 +124,41 @@ namespace llarp
{
auto id = ++ids;
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
PathTagLookupJob *j = new PathTagLookupJob(router, path, txid);
j->localtags = FindRandomIntroSetsWithTag(tag);
ownerKey.node = askpeer;
ownerKey.txid = id;
PathLookupJob *j = new PathLookupJob(router, path, txid);
j->localIntroSets = FindRandomIntroSetsWithTag(tag);
SearchJob job(
OurKey(), txid,
std::bind(&PathTagLookupJob::OnResult, j, std::placeholders::_1));
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1));
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->R = 5;
msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for tag ", tag.ToString(), " with ",
j->localIntroSets.size(), " local tags txid=", txid);
router->SendToOrQueue(askpeer, msg);
}
void
Context::LookupIntroSetForPath(const service::Address &addr, uint64_t txid,
const llarp::PathID_t &path,
const Key_t &askpeer)
{
auto id = ++ids;
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
PathLookupJob *j = new PathLookupJob(router, path, txid);
SearchJob job(
OurKey(), txid,
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1));
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(addr, id);
msg->msgs.push_back(dhtmsg);
router->SendToOrQueue(askpeer, msg);
}
@ -140,10 +175,11 @@ namespace llarp
// start at random middle point
auto start = llarp_randint() % nodes.size();
std::advance(itr, start);
auto end = itr;
auto end = itr;
std::string tagname = tag.ToString();
while(itr != nodes.end())
{
if(itr->second.introset.topic == tag)
if(itr->second.introset.topic.ToString() == tagname)
{
found.insert(itr->second.introset);
if(found.size() == max)
@ -154,7 +190,7 @@ namespace llarp
itr = nodes.begin();
while(itr != end)
{
if(itr->second.introset.topic == tag)
if(itr->second.introset.topic.ToString() == tagname)
{
found.insert(itr->second.introset);
if(found.size() == max)
@ -307,6 +343,7 @@ namespace llarp
/// handles replying with a GIM for a lookup
struct IntroSetInformJob
{
std::set< service::IntroSet > localIntroSets;
Key_t replyNode;
uint64_t txid;
llarp_router *m_Router;
@ -318,10 +355,19 @@ namespace llarp
void
OnResult(const std::vector< llarp::service::IntroSet > &results)
{
for(const auto &introset : results)
{
localIntroSets.insert(introset);
}
if(replyNode != m_Router->dht->impl.OurKey())
{
std::vector< service::IntroSet > reply;
for(const auto &introset : localIntroSets)
{
reply.push_back(introset);
}
auto msg = new llarp::DHTImmeidateMessage(replyNode);
msg->msgs.push_back(new GotIntroMessage(results, txid));
msg->msgs.push_back(new GotIntroMessage(reply, txid));
m_Router->SendToOrQueue(replyNode, msg);
}
delete this;
@ -330,7 +376,8 @@ namespace llarp
void
Context::LookupTag(const llarp::service::Tag &tag, const Key_t &whoasked,
uint64_t txid, const Key_t &askpeer, bool iterative)
uint64_t txid, const Key_t &askpeer,
const std::set< service::IntroSet > &include, uint64_t R)
{
auto id = ++ids;
if(txid == 0)
@ -339,14 +386,15 @@ namespace llarp
ownerKey.node = askpeer;
ownerKey.txid = id;
IntroSetInformJob *j = new IntroSetInformJob(router, whoasked, txid);
j->localIntroSets = include;
SearchJob job(
whoasked, txid,
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1));
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->iterative = iterative;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->R = R;
msg->msgs.push_back(dhtmsg);
router->SendToOrQueue(askpeer, msg);
}
@ -363,7 +411,7 @@ namespace llarp
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
IntroSetInformJob *j = new IntroSetInformJob(router, askpeer, txid);
IntroSetInformJob *j = new IntroSetInformJob(router, whoasked, txid);
SearchJob job(
whoasked, txid, addr, excludes,
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1));

View File

@ -101,6 +101,11 @@ namespace llarp
llarp_dht_context* ctx,
std::vector< llarp::dht::IMessage* >& replies) const
{
if(R > 5)
{
llarp::LogError("R value too big, ", R, "> 5");
return false;
}
auto& dht = ctx->impl;
Key_t peer;
std::set< Key_t > exclude = {dht.OurKey(), From};
@ -109,24 +114,35 @@ namespace llarp
const auto introset = dht.GetIntroSetByServiceAddress(S);
if(introset)
{
replies.push_back(new GotIntroMessage({*introset}, T));
}
else if(iterative)
{
// we are iterative and don't have it, reply with a direct reply
replies.push_back(new GotIntroMessage({}, T));
service::IntroSet i = *introset;
replies.push_back(new GotIntroMessage({i}, T));
}
else
{
// we are recursive
if(dht.nodes->FindCloseExcluding(S, peer, exclude))
if(iterative)
{
dht.LookupIntroSet(S, From, T, peer);
// we are iterative and don't have it, reply with a direct reply
replies.push_back(new GotIntroMessage({}, T));
}
else
{
llarp::LogError("cannot find closer peers for introset lookup for ",
S);
// we are recursive
if(dht.nodes->FindCloseExcluding(S, peer, exclude))
{
if(relayed)
dht.LookupIntroSetForPath(S, T, pathID, peer);
else if((peer ^ dht.OurKey())
> (peer
^ From)) // peer is closer than us, recursive search
dht.LookupIntroSet(S, From, T, peer);
else // we are closer than peer so do iterative search
dht.LookupIntroSet(S, From, T, peer, true);
}
else
{
llarp::LogError(
"cannot find closer peers for introset lookup for ", S);
}
}
}
}
@ -135,7 +151,7 @@ namespace llarp
if(relayed)
{
// tag lookup
if(dht.nodes->FindCloseExcluding(N.Key(), peer, exclude))
if(dht.nodes->GetRandomNodeExcluding(peer, exclude))
{
dht.LookupTagForPath(N, T, pathID, peer);
}
@ -146,20 +162,23 @@ namespace llarp
}
else
{
if(iterative)
auto introsets = dht.FindRandomIntroSetsWithTag(N);
if(iterative || R == 0)
{
std::vector< service::IntroSet > introsets;
for(const auto& introset : dht.FindRandomIntroSetsWithTag(N, 8))
introsets.push_back(introset);
std::vector< service::IntroSet > reply;
for(const auto& introset : introsets)
{
reply.push_back(introset);
}
// we are iterative and don't have it, reply with a direct reply
replies.push_back(new GotIntroMessage(introsets, T));
replies.push_back(new GotIntroMessage(reply, T));
}
else
{
// tag lookup
if(dht.nodes->FindCloseExcluding(N.Key(), peer, exclude))
if(dht.nodes->GetRandomNodeExcluding(peer, exclude))
{
dht.LookupTag(N, From, T, peer, true);
dht.LookupTag(N, From, T, peer, introsets, R - 1);
}
}
}

View File

@ -67,6 +67,7 @@ namespace llarp
return false;
}
dht.services->PutNode(I);
llarp::LogInfo("Put Introset for ", I.A.Addr().ToString());
replies.push_back(new GotIntroMessage({I}, txID));
Key_t peer;
std::set< Key_t > exclude;
@ -76,7 +77,7 @@ namespace llarp
exclude.insert(dht.OurKey());
if(S && dht.nodes->FindCloseExcluding(addr, peer, exclude))
{
dht.PropagateIntroSetTo(From, txID, I, peer, S - 1);
dht.PropagateIntroSetTo(From, txID, I, peer, S - 1, exclude);
}
return true;
}

View File

@ -30,6 +30,11 @@ std::string getDNSstring(const char *buffer)
return str;
}
// lets just remove uint
#ifdef _WIN32
#define uint UINT
#endif
extern "C"
{
uint16_t
@ -57,7 +62,7 @@ extern "C"
{
dns_msg_header *hdr = new dns_msg_header;
hdr->id = get16bits(buffer);
uint fields = get16bits(buffer);
uint16_t fields = get16bits(buffer);
uint8_t lFields = (fields & 0x00FF) >> 0;
uint8_t hFields = (fields & 0xFF00) >> 8;
// hdr->qr = fields & 0x8000;
@ -79,7 +84,7 @@ extern "C"
hdr->arCount = get16bits(buffer);
return hdr;
}
dns_msg_question *
decode_question(const char *buffer)
{
@ -208,7 +213,7 @@ extern "C"
// llarp::LogInfo("start ", start, " domain size ", domain.size());
*buffer++ = domain.size() - start; // last label length octet
for(uint i = start; i < domain.size(); i++)
for(size_t i = start; i < domain.size(); i++)
{
*buffer++ = domain[i]; // last label octets
// llarp::LogInfo("Writing ", domain[i], " at ", i);
@ -242,14 +247,14 @@ extern "C"
llarp::LogInfo("msg op ", hdr->opcode);
llarp::LogInfo("msg rc ", hdr->rcode);
for(uint i = 0; i < hdr->qdCount; i++)
for(uint8_t i = 0; i < hdr->qdCount; i++)
{
dns_msg_question *question = decode_question((const char*)castBuf);
llarp::LogInfo("Read a question");
castBuf += question->name.length() + 8;
}
for(uint i = 0; i < hdr->anCount; i++)
for(uint8_t i = 0; i < hdr->anCount; i++)
{
dns_msg_answer *answer = decode_answer((const char*)castBuf);
llarp::LogInfo("Read an answer");

View File

@ -2,21 +2,26 @@
#include <llarp/dns.h>
#include "buffer.hpp"
#include <netdb.h> /* getaddrinfo, getnameinfo */
#ifndef _WIN32
#include <arpa/inet.h>
#include <netdb.h> /* getaddrinfo, getnameinfo */
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <stdlib.h> /* exit */
#include <string.h> /* memset */
#include <sys/socket.h>
#include <sys/types.h>
#ifndef _MSC_VER
#include <unistd.h> /* close */
#include <arpa/inet.h>
#include <netinet/in.h>
#endif
#include <cstdio>
#include <llarp/dns.h>
#include "llarp/net.hpp" // for llarp::Addr
#include "logger.hpp"
#include <algorithm> // for std::find_if
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
@ -76,7 +81,7 @@ build_dns_packet(char *url, uint16_t id, uint16_t reqType)
{
dnsQuery->request[dnsQuery->length++] = word[i];
}
word = strtok(NULL, ".");
word = strtok(nullptr, ".");
}
dnsQuery->request[dnsQuery->length++] = 0x00; // End of the host name
@ -104,11 +109,11 @@ answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url,
request->resolved = resolved;
request->found = false;
request->context = dnsc;
char *sUrl = strdup(url);
request->question.name = (char *)sUrl;
// leave 256 bytes available
if (request->question.name.size() > 255)
{
@ -119,15 +124,15 @@ answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url,
}
request->question.type = 1;
request->question.qClass = 1;
// register our self with the tracker
dns_tracker *tracker = request->context->tracker;
uint16_t id = ++tracker->c_requests;
if (id == 65535) id = 0;
tracker->client_request[id] = request;
dns_query *dns_packet = build_dns_packet((char *)request->question.name.c_str(), id, 1);
return dns_packet;
}
@ -138,11 +143,11 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
ssize_t sz)
{
// llarp::LogInfo("got a response, udp user is ", udp->user);
unsigned char *castBuf = (unsigned char *)buf;
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
dns_msg_header *hdr = decode_hdr((const char *)castBuf);
llarp::LogDebug("Header got client responses for id: ", hdr->id);
if(!request)
{
@ -152,17 +157,17 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
return;
}
// llarp_dnsc_unbind(request);
if(sz < 0)
{
llarp::LogWarn("Error Receiving DNS Client Response");
request->resolved(request);
return;
}
// unsigned char *castBuf = (unsigned char *)buf;
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
// hexdump("received packet", &buffer, ret);
/*
uint16_t QDCOUNT; // No. of items in Question Section
@ -178,12 +183,12 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
*/
uint8_t rcode;
// int length;
// struct dns_query *dnsQuery = &request->query;
// rcode = (buffer[3] & 0x0F);
// llarp::LogInfo("dnsc rcode ", rcode);
dns_msg_header *msg = decode_hdr((const char *)castBuf);
castBuf += 12;
llarp::LogDebug("msg id ", msg->id);
@ -193,23 +198,23 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
llarp::LogDebug("msg op ", opcode);
rcode = msg->rcode;
llarp::LogDebug("msg rc ", rcode);
llarp::LogDebug("msg qdc ", msg->qdCount);
llarp::LogDebug("msg anc ", msg->anCount);
llarp::LogDebug("msg nsc ", msg->nsCount);
llarp::LogDebug("msg arc ", msg->arCount);
// we may need to parse question first
/*
dns_msg_question *question = decode_question((const char *)castBuf);
llarp::LogInfo("que name ", question->name);
castBuf += question->name.length() + 8;
dns_msg_answer *answer = decode_answer((const char *)castBuf);
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
*/
// FIXME: only handling one atm
dns_msg_question *question = nullptr;
for(uint i = 0; i < hdr->qdCount; i++)
@ -221,7 +226,7 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
castBuf += question->name.length() + 1 + 4;
castBuf += 2; // skip answer label
}
// FIXME: only handling one atm
dns_msg_answer *answer = nullptr;
for(uint i = 0; i < hdr->anCount; i++)
@ -243,16 +248,16 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
llarp::LogDebug("Read an authority");
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
}
// dns_msg_answer *answer2 = decode_answer((const char*)castBuf);
// castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
// llarp::LogDebug("query type: %u\n", dnsQuery->reqType);
/*
QCLASS = (uint16_t)dnsQuery->request[dnsQuery->length - 2] * 0x100
+ dnsQuery->request[dnsQuery->length - 1];
llarp::LogInfo("query class: ", QCLASS);
length = dnsQuery->length + 1; // to skip 0xc00c
// printf("length [%d] from [%d]\n", length, buffer.base);
ATYPE = (uint16_t)buffer[length + 1] * 0x100 + buffer[length + 2];
@ -264,31 +269,31 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
llarp::LogInfo("seconds to cache: ", TTL);
RDLENGTH = (uint16_t)buffer[length + 9] * 0x100 + buffer[length + 10];
llarp::LogInfo("bytes in answer: ", RDLENGTH);
MSGID = (uint16_t)buffer[0] * 0x100 + buffer[1];
// llarp::LogDebug("answer msg id: %u\n", MSGID);
*/
llarp::Addr upstreamAddr(*request->context->server);
if(answer == nullptr)
{
llarp::LogWarn("nameserver ", upstreamAddr, " didnt return any answers:");
request->resolved(request);
return;
}
llarp::LogDebug("ans class ", answer->aClass);
llarp::LogDebug("ans type ", answer->type);
llarp::LogDebug("ans ttl ", answer->ttl);
llarp::LogDebug("ans rdlen ", answer->rdLen);
/*
llarp::LogInfo("ans2 class ", answer2->aClass);
llarp::LogInfo("ans2 type ", answer2->type);
llarp::LogInfo("ans2 ttl ", answer2->ttl);
llarp::LogInfo("ans2 rdlen ", answer2->rdLen);
*/
if(rcode == 2)
{
llarp::LogWarn("nameserver ", upstreamAddr, " returned SERVFAIL:");
@ -306,16 +311,16 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
request->resolved(request);
return;
}
int ip = 0;
/* search for and print IPv4 addresses */
// if(dnsQuery->reqType == 0x01)
if(request->question.type == 1)
{
// llarp::LogInfo("DNS server's answer is: (type#=", ATYPE, "):");
llarp::LogDebug("IPv4 address(es) for ", request->question.name, ":");
if(answer->rdLen == 4)
{
request->result.sa_family = AF_INET;
@ -324,20 +329,20 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
#endif
struct in_addr *addr =
&((struct sockaddr_in *)&request->result)->sin_addr;
unsigned char *ip = (unsigned char *)&(addr->s_addr);
ip[0] = answer->rData[0];
ip[1] = answer->rData[1];
ip[2] = answer->rData[2];
ip[3] = answer->rData[3];
llarp::Addr test(request->result);
llarp::LogDebug(test);
request->found = true;
request->resolved(request);
return;
}
if(!ip)
{
llarp::LogWarn(" No IPv4 address found in the DNS answer!");
@ -351,14 +356,14 @@ void
raw_resolve_host(struct dnsc_context *dnsc, const char *url,
dnsc_answer_hook_func resolved, void *user)
{
dns_query *dns_packet = answer_request_alloc(dnsc, nullptr, url, resolved, user);
if (!dns_packet)
{
llarp::LogError("Couldn't make dnsc packet");
return;
}
// char *word;
llarp::Addr upstreamAddr(*dnsc->server);
llarp::LogDebug("Asking DNS server ", upstreamAddr, " about ", url);
@ -368,7 +373,11 @@ raw_resolve_host(struct dnsc_context *dnsc, const char *url,
socklen_t size;
// int length;
unsigned char buffer[DNC_BUF_SIZE];
#ifndef _WIN32
int sockfd;
#else
SOCKET sockfd;
#endif
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0)
@ -386,8 +395,15 @@ raw_resolve_host(struct dnsc_context *dnsc, const char *url,
size = sizeof(addr);
//hexdump("sending packet", &dnsQuery.request, dnsQuery.length);
ret = sendto(sockfd, dns_packet->request, dns_packet->length, 0,
#ifdef _WIN32
ret = sendto(sockfd, (const char *)dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#else
ret = sendto(sockfd, (const char *)dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#endif
delete dns_packet;
if(ret < 0)
{
@ -410,7 +426,11 @@ raw_resolve_host(struct dnsc_context *dnsc, const char *url,
// hexdump("received packet", &buffer, ret);
#ifndef _WIN32
close(sockfd);
#else
closesocket(sockfd);
#endif
unsigned char *castBuf = (unsigned char *)buffer;
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);

View File

@ -9,6 +9,11 @@
extern dns_tracker dns_udp_tracker;
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin
#endif
ssize_t
raw_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
const void *buffer, size_t length)
@ -16,7 +21,11 @@ raw_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
int *fd = (int *)sock;
// how do we get to these??
socklen_t addrLen = sizeof(struct sockaddr_in);
return sendto(*fd, buffer, length, 0, from, addrLen);
#ifdef _WIN32
return sendto(*fd, (const char *)buffer, length, 0, from, addrLen);
#else
return sendto(*fd, (const char *)buffer, length, 0, from, addrLen);
#endif
}
ssize_t
@ -40,7 +49,7 @@ llarp_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
void
write404_dnss_response(const struct sockaddr *from, dnsd_question_request *request)
{
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2);
char buf[BUFFER_SIZE];
memset(buf, 0, BUFFER_SIZE);
@ -52,26 +61,26 @@ write404_dnss_response(const struct sockaddr *from, dnsd_question_request *reque
fields += (0 << 14); // I think opcode is always 0
fields += 3; // response code (3 => not found, 0 = Ok)
put16bits(write_buffer, fields);
put16bits(write_buffer, 1); // QD (number of questions)
put16bits(write_buffer, 1); // AN (number of answers)
put16bits(write_buffer, 0); // NS (number of auth RRs)
put16bits(write_buffer, 0); // AR (number of Additional RRs)
// code question
code_domain(write_buffer, request->question.name);
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
// code answer
code_domain(write_buffer, ""); // com, type=6, ttl=0
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, 1); // rdLength
*write_buffer++ = 0; // write a null byte
uint out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending 404, ", out_bytes, " bytes");
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
@ -83,7 +92,7 @@ void
writecname_dnss_response(std::string cname, const struct sockaddr *from,
dnsd_question_request *request)
{
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2);
char buf[BUFFER_SIZE];
memset(buf, 0, BUFFER_SIZE);
@ -98,39 +107,39 @@ writecname_dnss_response(std::string cname, const struct sockaddr *from,
//fields |= 1UL << 8; // RD recursion desired
//fields |= 1UL << 9; // 9 is truncate, forces TCP
put16bits(write_buffer, fields);
put16bits(write_buffer, 1); // QD (number of questions)
put16bits(write_buffer, 1); // AN (number of answers)
put16bits(write_buffer, 1); // NS (number of auth RRs)
put16bits(write_buffer, 1); // AR (number of Additional RRs)
// code question
code_domain(write_buffer, request->question.name);
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
// code answer
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
put16bits(write_buffer, 5); // cname
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, cname.length() + 2); // rdLength
code_domain(write_buffer, cname); // com, type=6, ttl=0
// location of cname
//*write_buffer++ = ip[0];
//*write_buffer++ = ip[1];
// write auth RR
code_domain(write_buffer, cname); // com, type=6, ttl=0
put16bits(write_buffer, 2); // NS
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
std::string local("ns1.loki");
put16bits(write_buffer, local.length() + 2); // rdLength
code_domain(write_buffer, local); // com, type=6, ttl=0
// write addl RR
code_domain(write_buffer, local); // com, type=6, ttl=0
put16bits(write_buffer, 1); // A
@ -142,7 +151,7 @@ writecname_dnss_response(std::string cname, const struct sockaddr *from,
*write_buffer++ = 0;
*write_buffer++ = 0;
*write_buffer++ = 1;
uint out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending cname, ", out_bytes, " bytes");
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
@ -315,7 +324,7 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
return;
}
*/
if(request->llarp)
{
// make async request
@ -386,7 +395,7 @@ llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_ev_loop *netloop,
dnsd->udp.tick = nullptr;
dns_udp_tracker.dnsd = dnsd;
dnsd->tracker = &dns_udp_tracker; // register global tracker with context
dnsd->logic = logic; // set logic worker for timers
dnsd->intercept = nullptr; // set default intercepter
@ -397,7 +406,7 @@ llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_ev_loop *netloop,
llarp::LogError("Couldnt init dns client");
return false;
}
if (netloop)
{
return llarp_ev_add_udp(netloop, &dnsd->udp, (const sockaddr *)&bindaddr)

View File

@ -5,11 +5,11 @@
#ifdef __linux__
#include "ev_epoll.hpp"
#endif
#if(__APPLE__ && __MACH__)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
#include "ev_kqueue.hpp"
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include "ev_kqueue.hpp"
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
#include "ev_win32.hpp"
#endif
void
@ -18,11 +18,17 @@ llarp_ev_loop_alloc(struct llarp_ev_loop **ev)
#ifdef __linux__
*ev = new llarp_epoll_loop;
#endif
#if(__APPLE__ && __MACH__)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
*ev = new llarp_kqueue_loop;
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
*ev = new llarp_kqueue_loop;
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
*ev = new llarp_win32_loop;
#endif
// a) I assume that the libre fork of Solaris is still
// 5.10, and b) the current commercial version is 5.11, naturally.
// -despair86
#if defined(__SunOS_5_10) || defined(__SunOS_5_11)
*ev = new llarp_sun_iocp_loop;
#endif
(*ev)->init();
}
@ -88,5 +94,11 @@ int
llarp_ev_udp_sendto(struct llarp_udp_io *udp, const sockaddr *to,
const void *buf, size_t sz)
{
return static_cast< llarp::ev_io * >(udp->impl)->sendto(to, buf, sz);
auto ret = static_cast< llarp::ev_io * >(udp->impl)->sendto(to, buf, sz);
if(ret == -1)
{
llarp::LogWarn("sendto failed ", strerror(errno));
errno = 0;
}
return ret;
}

View File

@ -2,23 +2,35 @@
#define LLARP_EV_HPP
#include <llarp/ev.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <list>
namespace llarp
{
struct ev_io
{
#ifndef _WIN32
int fd;
ev_io(int f) : fd(f){};
#else
SOCKET fd;
ev_io(SOCKET f) : fd(f){};
#endif
virtual int
read(void* buf, size_t sz) = 0;
virtual int
sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
virtual ~ev_io()
{
#ifndef _WIN32
::close(fd);
#else
closesocket(fd);
#endif
};
};
}; // namespace llarp

View File

@ -145,7 +145,7 @@ struct llarp_epoll_loop : public llarp_ev_loop
byte_t readbuf[2048];
do
{
result = epoll_wait(epollfd, events, 1024, 100);
result = epoll_wait(epollfd, events, 1024, 10);
if(result > 0)
{
int idx = 0;

View File

@ -3,13 +3,7 @@
#include <llarp/buffer.h>
#include <llarp/net.h>
#if __FreeBSD__ || __OpenBSD__ || __NetBSD__
// kqueue / kevent
#include <sys/event.h>
#include <sys/time.h>
#endif
#if(__APPLE__ && __MACH__)
#if __FreeBSD__ || __OpenBSD__ || __NetBSD__ || (__APPLE__ && __MACH__)
// kqueue / kevent
#include <sys/event.h>
#include <sys/time.h>
@ -107,11 +101,13 @@ struct llarp_kqueue_loop : public llarp_ev_loop
int
tick(int ms)
{
(void)ms;
struct kevent events[1024];
int result;
byte_t readbuf[2048];
result = kevent(kqueuefd, NULL, 0, events, 1024, NULL);
timespec t;
t.tv_sec = 0;
t.tv_nsec = ms * 1000UL;
result = kevent(kqueuefd, nullptr, 0, events, 1024, &t);
// result: 0 is a timeout
if(result > 0)
{
@ -129,23 +125,25 @@ struct llarp_kqueue_loop : public llarp_ev_loop
}
++idx;
}
for(auto& l : udp_listeners)
if(l->tick)
l->tick(l);
}
for(auto& l : udp_listeners)
if(l->tick)
l->tick(l);
return result;
}
int
run()
{
timespec t;
t.tv_sec = 0;
t.tv_nsec = 10000UL;
struct kevent events[1024];
int result;
byte_t readbuf[2048];
do
{
result = kevent(kqueuefd, NULL, 0, events, 1024, NULL);
result = kevent(kqueuefd, nullptr, 0, events, 1024, &t);
// result: 0 is a timeout
if(result > 0)
{
@ -161,7 +159,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
llarp::LogInfo("run error reading, should close ev");
close_ev(ev);
// ev->fd = 0;
//delete ev;
// delete ev;
// break;
}
}
@ -241,9 +239,8 @@ struct llarp_kqueue_loop : public llarp_ev_loop
bool
close_ev(llarp::ev_io* ev)
{
// printf("closing_ev [%x] fd[%d]\n", ev, ev->fd);
EV_SET(&change, ev->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
return kevent(kqueuefd, &change, 1, NULL, 0, NULL) == -1;
EV_SET(&change, ev->fd, EVFILT_READ, EV_DELETE, 0, 0, nullptr);
return kevent(kqueuefd, &change, 1, nullptr, 0, nullptr) == -1;
}
bool
@ -255,7 +252,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
llarp::udp_listener* listener = new llarp::udp_listener(fd, l);
EV_SET(&change, fd, EVFILT_READ, EV_ADD, 0, 0, listener);
if(kevent(kqueuefd, &change, 1, NULL, 0, NULL) == -1)
if(kevent(kqueuefd, &change, 1, nullptr, 0, nullptr) == -1)
{
l->impl = nullptr;
delete listener;

330
llarp/ev_win32.hpp Normal file
View File

@ -0,0 +1,330 @@
#ifndef EV_WIN32_HPP
#define EV_WIN32_HPP
#include <llarp/buffer.h>
#include <llarp/net.h>
#include <windows.h>
#include <cstdio>
#include <llarp/net.hpp>
#include "ev.hpp"
#include "logger.hpp"
namespace llarp
{
struct udp_listener : public ev_io
{
llarp_udp_io* udp;
// we receive queued data in the OVERLAPPED data field,
// much like the pipefds in the UNIX kqueue and loonix
// epoll handles
// 0 is the read port, 1 is the write port
WSAOVERLAPPED portfds[2] = {0};
size_t iosz;
// the unique completion key that helps us to
// identify the object instance for which we receive data
// Here, we'll use the address of the udp_listener instance, converted to
// its literal int/int64 representation.
ULONG_PTR listener_id = 0;
udp_listener(SOCKET fd, llarp_udp_io* u) : ev_io(fd), udp(u){};
~udp_listener()
{
}
int
getData(void* buf, size_t sz, size_t ret)
{
iosz = ret;
return read(buf, sz);
}
virtual int
read(void* buf, size_t sz)
{
sockaddr_in6 src;
socklen_t slen = sizeof(src);
sockaddr* addr = (sockaddr*)&src;
unsigned long flags = 0;
WSABUF wbuf = {sz, static_cast< char* >(buf)};
// WSARecvFrom
int ret = ::WSARecvFrom(fd, &wbuf, 1, nullptr, &flags, addr, &slen,
&portfds[0], nullptr);
// 997 is the error code for queued ops
int s_errno = ::WSAGetLastError();
if(ret && s_errno != 997)
{
llarp::LogWarn("recv socket error ", s_errno);
return -1;
}
// get the _real_ payload size from tick()
udp->recvfrom(udp, addr, buf, iosz);
return 0;
}
virtual int
sendto(const sockaddr* to, const void* data, size_t sz)
{
socklen_t slen;
WSABUF wbuf = {sz, (char*)data};
switch(to->sa_family)
{
case AF_INET:
slen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
slen = sizeof(struct sockaddr_in6);
break;
default:
return -1;
}
// WSASendTo
ssize_t sent =
::WSASendTo(fd, &wbuf, 1, nullptr, 0, to, slen, &portfds[1], nullptr);
int s_errno = ::WSAGetLastError();
if(sent && s_errno != 997)
{
llarp::LogWarn("send socket error ", s_errno);
return -1;
}
return 0;
}
};
}; // namespace llarp
struct llarp_win32_loop : public llarp_ev_loop
{
HANDLE iocpfd;
llarp_win32_loop() : iocpfd(INVALID_HANDLE_VALUE)
{
WSADATA wsockd;
int err;
// So, what I was told last time was that we can defer
// loading winsock2 up to this point, as we reach this ctor
// early on during daemon startup.
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
if(err)
perror("Failed to start Windows Sockets");
}
~llarp_win32_loop()
{
if(iocpfd != INVALID_HANDLE_VALUE)
::CloseHandle(iocpfd);
::WSACleanup();
}
bool
init()
{
if(iocpfd == INVALID_HANDLE_VALUE)
iocpfd = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
if(iocpfd != INVALID_HANDLE_VALUE)
return true; // we don't have a socket to attach to this IOCP yet
return false;
}
// it works! -despair86, 3-Aug-18 @0420
int
tick(int ms)
{
// The only field we really care about is
// the listener_id, as it contains the address
// of the udp_listener instance.
DWORD iolen = 0;
// ULONG_PTR is guaranteed to be the same size
// as an arch-specific pointer value
ULONG_PTR ev_id = 0;
WSAOVERLAPPED* qdata = nullptr;
int result = 0;
int idx = 0;
byte_t readbuf[2048];
do
{
if(ev_id && qdata && iolen)
{
llarp::udp_listener* ev =
reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && ev->fd)
{
if(ev->getData(readbuf, sizeof(readbuf), iolen) == -1)
{
llarp::LogInfo("tick close ev");
close_ev(ev);
}
}
}
++idx;
} while(::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, ms));
for(auto& l : udp_listeners)
{
if(l->tick)
l->tick(l);
}
if(!idx)
return -1;
else
result = idx;
return result;
}
// ok apparently this isn't being used yet...
int
run()
{
// The only field we really care about is
// the listener_id, as it contains the address
// of the udp_listener instance.
DWORD iolen = 0;
// ULONG_PTR is guaranteed to be the same size
// as an arch-specific pointer value
ULONG_PTR ev_id = 0;
WSAOVERLAPPED* qdata = nullptr;
int result = 0;
int idx = 0;
byte_t readbuf[2048];
// unlike epoll and kqueue, we only need to run so long as the
// system call returns TRUE
do
{
if(ev_id && qdata && iolen)
{
llarp::udp_listener* ev = reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && ev->fd)
{
if(ev->getData(readbuf, sizeof(readbuf), iolen) == -1)
{
llarp::LogInfo("close ev");
close_ev(ev);
}
}
}
++idx;
} while(::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, 10));
for(auto& l : udp_listeners)
{
if(l->tick)
l->tick(l);
}
if(!idx)
return -1;
else
result = idx;
return result;
}
SOCKET
udp_bind(const sockaddr* addr)
{
socklen_t slen;
switch(addr->sa_family)
{
case AF_INET:
slen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
slen = sizeof(struct sockaddr_in6);
break;
default:
return INVALID_SOCKET;
}
SOCKET fd = ::WSASocket(addr->sa_family, SOCK_DGRAM, 0, nullptr, 0,
WSA_FLAG_OVERLAPPED);
if(fd == INVALID_SOCKET)
{
perror("WSASocket()");
return INVALID_SOCKET;
}
if(addr->sa_family == AF_INET6)
{
// enable dual stack explicitly
int dual = 1;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&dual,
sizeof(dual))
== -1)
{
// failed
perror("setsockopt()");
closesocket(fd);
return INVALID_SOCKET;
}
}
llarp::Addr a(*addr);
llarp::LogDebug("bind to ", a);
if(bind(fd, addr, slen) == -1)
{
perror("bind()");
closesocket(fd);
return INVALID_SOCKET;
}
llarp::LogInfo("socket fd is ", fd);
return fd;
}
bool
close_ev(llarp::ev_io* ev)
{
// On Windows, just close the socket to decrease the iocp refcount
// and stop any pending I/O
BOOL stopped = ::CancelIo(reinterpret_cast< HANDLE >(ev->fd));
return closesocket(ev->fd) == 0 && stopped == TRUE;
}
bool
udp_listen(llarp_udp_io* l, const sockaddr* src)
{
SOCKET fd = udp_bind(src);
llarp::LogDebug("new socket fd is ", fd);
if(fd == INVALID_SOCKET)
return false;
llarp::udp_listener* listener = new llarp::udp_listener(fd, l);
listener->listener_id = reinterpret_cast< ULONG_PTR >(listener);
if(!::CreateIoCompletionPort(reinterpret_cast< HANDLE >(fd), iocpfd,
listener->listener_id, 0))
{
delete listener;
return false;
}
l->impl = listener;
udp_listeners.push_back(l);
return true;
}
bool
udp_close(llarp_udp_io* l)
{
bool ret = false;
llarp::udp_listener* listener =
static_cast< llarp::udp_listener* >(l->impl);
if(listener)
{
ret = close_ev(listener);
l->impl = nullptr;
delete listener;
udp_listeners.remove(l);
}
return ret;
}
void
stop()
{
// do nothing, cancel io in close_ev()
}
};
#endif

View File

@ -1,4 +1,7 @@
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include <llarp/bencode.h>
#include <llarp/exit_info.h>
#include <llarp/mem.h>

View File

@ -1,4 +1,7 @@
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include <llarp/bencode.h>
#include <llarp/exit_route.h>
#include <llarp/string.h>

View File

@ -8,15 +8,20 @@
#endif
#include "filesystem.h"
// mingw32 in the only one that doesn't use cpp17::filesystem
#if defined(__MINGW32__)
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
// win32 is the only one that doesn't use cpp17::filesystem
// because cpp17::filesystem is unimplemented for Windows
// -despair86
#if defined(__MINGW32__) || defined(_MSC_VER)
namespace fs = std::experimental::filesystem;
#else
namespace fs = std::filesystem;
#endif // end win32
#else
// not CPP17 needs this
// openbsd needs this
// linux gcc 7.2 needs this
namespace fs = cpp17::filesystem;
#endif // end mingw32
#endif
#endif // end LLARP_FS_HPP

View File

@ -40,7 +40,7 @@ namespace ini
{
struct Level
{
Level() : parent(NULL), depth(0)
Level() : parent(nullptr), depth(0)
{
}
Level(Level *p) : parent(p), depth(0)
@ -156,7 +156,7 @@ namespace ini
Parser::err(const char *s)
{
char buf[256];
sprintf(buf, "%s on line #%ld", s, ln_);
sprintf(buf, "%s on line #%d", s, ln_);
throw std::runtime_error(buf);
}
@ -210,8 +210,7 @@ namespace ini
size_t depth;
std::string sname;
parseSLine(sname, depth);
Level *lp = NULL;
Level *lp = nullptr;
Level *parent = &l;
if(depth > l.depth + 1)
err("section with wrong depth");

View File

@ -1,3 +1,7 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include "llarp/iwp/frame_state.hpp"
#include "buffer.hpp"
#include "llarp/crypto.hpp"
@ -7,6 +11,7 @@
#include "llarp/logger.hpp"
#include "mem.hpp"
#include "router.hpp"
#include <algorithm>
llarp_router *
frame_state::Router()
@ -21,17 +26,14 @@ frame_state::process_inbound_queue()
InboundMessage::OrderCompare >
q;
recvqueue.Process(q);
uint64_t last = 0;
while(q.size())
{
// TODO: is this right?
auto &front = q.top();
if(front->msgid < nextMsgID && nextMsgID - front->msgid > 1)
{
// re-queue because of an ordering gap
recvqueue.Put(front);
}
else
if(last != front->msgid)
{
auto buffer = front->Buffer();
if(!Router()->HandleRecvLinkMessage(parent, buffer))
@ -39,12 +41,14 @@ frame_state::process_inbound_queue()
llarp::LogWarn("failed to process inbound message ", front->msgid);
llarp::DumpBuffer< llarp_buffer_t, 128 >(buffer);
}
else
{
nextMsgID = std::max(front->msgid, nextMsgID + 1);
}
delete front;
last = front->msgid;
}
else
{
llarp::LogWarn("duplicate inbound message ", last);
}
delete front;
q.pop();
}
// TODO: this isn't right

View File

@ -213,8 +213,8 @@ llarp_link::RemoveSession(llarp_link_session* s)
UnmapAddr(s->addr);
s->done();
m_sessions.erase(itr);
delete s;
}
delete s;
}
uint8_t*

View File

@ -1,4 +1,8 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/iwp.h>
#include <algorithm>
#include <llarp/crypto.hpp>
#include <llarp/iwp/server.hpp>
#include <llarp/iwp/session.hpp>
@ -463,7 +467,6 @@ static void
handle_verify_session_start(iwp_async_session_start *s)
{
llarp_link_session *self = static_cast< llarp_link_session * >(s->user);
self->serv->remove_intro_from(self->addr);
if(!s->buf)
{
// verify fail
@ -472,6 +475,7 @@ handle_verify_session_start(iwp_async_session_start *s)
self->serv->RemoveSession(self);
return;
}
self->serv->remove_intro_from(self->addr);
self->send_LIM();
self->working = false;
}
@ -520,7 +524,7 @@ handle_generated_intro(iwp_async_intro *i)
}
link->EnterState(llarp_link_session::eIntroSent);
link->lastIntroSentAt = llarp_time_now_ms();
auto dlt = (link->createdAt - link->lastIntroSentAt);
auto dlt = (link->createdAt - link->lastIntroSentAt) + 500;
auto logic = link->serv->logic;
link->intro_resend_job_id = llarp_logic_call_later(
logic, {dlt, link, &llarp_link_session::handle_introack_timeout});
@ -649,6 +653,11 @@ llarp_link_session::on_session_start(const void *buf, size_t sz)
llarp::LogDebug("session start too big");
return;
}
if(working)
{
llarp::LogError("duplicate session start from ", addr);
return;
}
// own the buffer
memcpy(workbuf, buf, sz);
// verify session start

View File

@ -12,8 +12,17 @@ namespace llarp
}
} // namespace llarp
void
cSetLogLevel(LogLevel lvl)
extern "C"
{
llarp::SetLogLevel((llarp::LogLevel)lvl);
}
void
cSetLogLevel(LogLevel lvl)
{
llarp::SetLogLevel((llarp::LogLevel)lvl);
}
void
cSetLogNodeName(const char* name)
{
llarp::_glog.nodeName = name;
}
}

View File

@ -28,7 +28,7 @@ namespace llarp
DumpBuffer(const T &buff)
{
size_t idx = 0;
printf("buffer of size %ld\n", buff.sz);
printf("buffer of size %u\n", buff.sz);
while(idx < buff.sz)
{
if(buff.base + idx == buff.cur)

View File

@ -2,13 +2,12 @@
#include "str.hpp"
#ifdef ANDROID
#include "android/ifaddrs.h"
#else
#include <ifaddrs.h>
#endif
#ifndef _WIN32
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#endif
#include <cstdio>
#include "logger.hpp"
@ -42,6 +41,692 @@ operator<(const in6_addr& a, const in6_addr& b)
return memcmp(&a, &b, sizeof(in6_addr)) < 0;
}
#ifdef _WIN32
#include <assert.h>
#include <errno.h>
#include <strsafe.h>
#include <iphlpapi.h>
// current strategy: mingw 32-bit builds call an inlined version of the function
// microsoft c++ and mingw 64-bit builds call the normal function
#define DEFAULT_BUFFER_SIZE 15000
// the inline monkey patch for downlevel platforms
#ifndef _MSC_VER
extern "C" DWORD FAR PASCAL
_GetAdaptersAddresses(ULONG Family, ULONG Flags, PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen);
#endif
// in any case, we still need to implement some form of
// getifaddrs(3) with compatible semantics on NT...
// daemon.ini section [bind] will have something like
// [bind]
// Ethernet=1090
// inside, since that's what we use in windows to refer to
// network interfaces
struct llarp_nt_ifaddrs_t
{
struct llarp_nt_ifaddrs_t* ifa_next; /* Pointer to the next structure. */
char* ifa_name; /* Name of this network interface. */
unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */
struct sockaddr* ifa_addr; /* Network address of this interface. */
struct sockaddr* ifa_netmask; /* Netmask of this interface. */
};
// internal struct
struct _llarp_nt_ifaddrs_t
{
struct llarp_nt_ifaddrs_t _ifa;
char _name[256];
struct sockaddr_storage _addr;
struct sockaddr_storage _netmask;
};
static inline void*
_llarp_nt_heap_alloc(const size_t n_bytes)
{
/* Does not appear very safe with re-entrant calls on XP */
return HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, n_bytes);
}
static inline void
_llarp_nt_heap_free(void* mem)
{
HeapFree(GetProcessHeap(), 0, mem);
}
#define llarp_nt_new0(struct_type, n_structs) \
((struct_type*)malloc((size_t)sizeof(struct_type) * (size_t)(n_structs)))
int
llarp_nt_sockaddr_pton(const char* src, struct sockaddr* dst)
{
struct addrinfo hints = {0}, *result = nullptr;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_NUMERICHOST;
const int status = getaddrinfo(src, nullptr, &hints, &result);
if(!status)
{
memcpy(dst, result->ai_addr, result->ai_addrlen);
freeaddrinfo(result);
return 1;
}
return 0;
}
/* NB: IP_ADAPTER_INFO size varies size due to sizeof (time_t), the API assumes
* 4-byte datatype whilst compiler uses an 8-byte datatype. Size can be forced
* with -D_USE_32BIT_TIME_T with side effects to everything else.
*
* Only supports IPv4 addressing similar to SIOCGIFCONF socket option.
*
* Interfaces that are not "operationally up" will return the address 0.0.0.0,
* this includes adapters with static IP addresses but with disconnected cable.
* This is documented under the GetIpAddrTable API. Interface status can only
* be determined by the address, a separate flag is introduced with the
* GetAdapterAddresses API.
*
* The IPv4 loopback interface is not included.
*
* Available in Windows 2000 and Wine 1.0.
*/
static bool
_llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
{
DWORD dwRet;
ULONG ulOutBufLen = DEFAULT_BUFFER_SIZE;
PIP_ADAPTER_INFO pAdapterInfo = nullptr;
PIP_ADAPTER_INFO pAdapter = nullptr;
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
#ifdef DEBUG
fprintf(stderr, "IP_ADAPTER_INFO buffer length %lu bytes.\n", ulOutBufLen);
#endif
pAdapterInfo = (IP_ADAPTER_INFO*)_llarp_nt_heap_alloc(ulOutBufLen);
dwRet = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterInfo);
pAdapterInfo = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS: /* NO_ERROR */
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterInfo)
_llarp_nt_heap_free(pAdapterInfo);
return false;
default:
errno = dwRet;
#ifdef DEBUG
fprintf(stderr, "system call failed: %lu\n", GetLastError());
#endif
if(pAdapterInfo)
_llarp_nt_heap_free(pAdapterInfo);
return false;
}
/* count valid adapters */
int n = 0, k = 0;
for(pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next)
{
for(IP_ADDR_STRING* pIPAddr = &pAdapter->IpAddressList; pIPAddr;
pIPAddr = pIPAddr->Next)
{
/* skip null adapters */
if(strlen(pIPAddr->IpAddress.String) == 0)
continue;
++n;
}
}
#ifdef DEBUG
fprintf(stderr, "GetAdaptersInfo() discovered %d interfaces.\n", n);
#endif
/* contiguous block for adapter list */
struct _llarp_nt_ifaddrs_t* ifa =
llarp_nt_new0(struct _llarp_nt_ifaddrs_t, n);
struct _llarp_nt_ifaddrs_t* ift = ifa;
/* now populate list */
for(pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next)
{
for(IP_ADDR_STRING* pIPAddr = &pAdapter->IpAddressList; pIPAddr;
pIPAddr = pIPAddr->Next)
{
/* skip null adapters */
if(strlen(pIPAddr->IpAddress.String) == 0)
continue;
/* address */
ift->_ifa.ifa_addr = (struct sockaddr*)&ift->_addr;
assert(1 == llarp_nt_sockaddr_pton(pIPAddr->IpAddress.String,ift->_ifa.ifa_addr));
/* name */
#ifdef DEBUG
fprintf(stderr, "name:%s IPv4 index:%lu\n", pAdapter->AdapterName,
pAdapter->Index);
#endif
ift->_ifa.ifa_name = ift->_name;
StringCchCopyN(ift->_ifa.ifa_name, 128, pAdapter->AdapterName, 128);
/* flags: assume up, broadcast and multicast */
ift->_ifa.ifa_flags = IFF_UP | IFF_BROADCAST | IFF_MULTICAST;
if(pAdapter->Type == MIB_IF_TYPE_LOOPBACK)
ift->_ifa.ifa_flags |= IFF_LOOPBACK;
/* netmask */
ift->_ifa.ifa_netmask = (sockaddr*)&ift->_netmask;
assert(1 == llarp_nt_sockaddr_pton(pIPAddr->IpMask.String, ift->_ifa.ifa_netmask));
/* next */
if(k++ < (n - 1))
{
ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1);
ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next);
}
}
}
if(pAdapterInfo)
_llarp_nt_heap_free(pAdapterInfo);
*ifap = (struct llarp_nt_ifaddrs_t*)ifa;
return true;
}
/* Supports both IPv4 and IPv6 addressing. The size of IP_ADAPTER_ADDRESSES
* changes between Windows XP, XP SP1, and Vista with additional members.
*
* Interfaces that are not "operationally up" will typically return a host
* IP address with the defined IPv4 link-local prefix 169.254.0.0/16.
* Adapters with a static configured IP address but down will return both
* the IPv4 link-local prefix and the static address.
*
* It is easier to say "not up" rather than "down" as this API returns six
* effective down status values: down, testing, unknown, dormant, not present,
* and lower layer down.
*
* Available in Windows XP and Wine 1.3.
*
* NOTE(despair): an inline implementation is provided, much like
* getaddrinfo(3) for old hosts. See "win32_intrnl.*"
*/
#ifdef _MSC_VER
static bool
_llarp_nt_getadaptersaddresses(struct llarp_nt_ifaddrs_t** ifap)
{
DWORD dwSize = DEFAULT_BUFFER_SIZE, dwRet;
IP_ADAPTER_ADDRESSES *pAdapterAddresses = nullptr, *adapter;
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
#ifdef DEBUG
fprintf(stderr, "IP_ADAPTER_ADDRESSES buffer length %lu bytes.\n", dwSize);
#endif
pAdapterAddresses = (IP_ADAPTER_ADDRESSES*)_llarp_nt_heap_alloc(dwSize);
#if defined(_MSC_VER) || defined(_WIN64)
dwRet = GetAdaptersAddresses(AF_UNSPEC,
/* requires Windows XP SP1 */
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#else
dwRet = _GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#endif
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterAddresses);
pAdapterAddresses = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS:
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return FALSE;
default:
errno = _doserrno;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return FALSE;
}
/* count valid adapters */
int n = 0, k = 0;
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
for(IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress;
unicast; unicast = unicast->Next)
{
/* ensure IP adapter */
if(AF_INET != unicast->Address.lpSockaddr->sa_family
&& AF_INET6 != unicast->Address.lpSockaddr->sa_family)
{
continue;
}
++n;
}
}
/* contiguous block for adapter list */
struct _llarp_nt_ifaddrs_t* ifa =
llarp_nt_new0(struct _llarp_nt_ifaddrs_t, n);
struct _llarp_nt_ifaddrs_t* ift = ifa;
/* now populate list */
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
int unicastIndex = 0;
for(IP_ADAPTER_UNICAST_ADDRESS *unicast = adapter->FirstUnicastAddress;
unicast; unicast = unicast->Next, ++unicastIndex)
{
/* ensure IP adapter */
if(AF_INET != unicast->Address.lpSockaddr->sa_family
&& AF_INET6 != unicast->Address.lpSockaddr->sa_family)
{
continue;
}
/* address */
ift->_ifa.ifa_addr = (sockaddr*)&ift->_addr;
memcpy(ift->_ifa.ifa_addr, unicast->Address.lpSockaddr,
unicast->Address.iSockaddrLength);
/* name */
#ifdef DEBUG
fprintf(stderr, "name:%s IPv4 index:%lu IPv6 index:%lu\n",
adapter->AdapterName, adapter->IfIndex, adapter->Ipv6IfIndex);
#endif
ift->_ifa.ifa_name = ift->_name;
StringCchCopyN(ift->_ifa.ifa_name, 256, adapter->AdapterName, 256);
/* flags */
ift->_ifa.ifa_flags = 0;
if(IfOperStatusUp == adapter->OperStatus)
ift->_ifa.ifa_flags |= IFF_UP;
if(IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
ift->_ifa.ifa_flags |= IFF_LOOPBACK;
if(!(adapter->Flags & IP_ADAPTER_NO_MULTICAST))
ift->_ifa.ifa_flags |= IFF_MULTICAST;
/* netmask */
ift->_ifa.ifa_netmask = (sockaddr*)&ift->_netmask;
/* pre-Vista must hunt for matching prefix in linked list, otherwise use
* OnLinkPrefixLength from IP_ADAPTER_UNICAST_ADDRESS structure.
* FirstPrefix requires Windows XP SP1, from SP1 to pre-Vista provides a
* single adapter prefix for each IP address. Vista and later provides
* host IP address prefix, subnet IP address, and subnet broadcast IP
* address. In addition there is a multicast and broadcast address
* prefix.
*/
ULONG prefixLength = 0;
#if defined(_WIN32) && (_WIN32_WINNT >= 0x0600)
/* For a unicast IPv4 address, any value greater than 32 is an illegal
* value. For a unicast IPv6 address, any value greater than 128 is an
* illegal value. A value of 255 is commonly used to represent an illegal
* value.
*
* Windows 7 SP1 returns 64 for Teredo links which is incorrect.
*/
#define IN6_IS_ADDR_TEREDO(addr) \
(((const uint32_t*)(addr))[0] == ntohl(0x20010000))
if(AF_INET6 == unicast->Address.lpSockaddr->sa_family &&
/* TunnelType only applies to one interface on the adapter and no
* convenient method is provided to determine which.
*/
TUNNEL_TYPE_TEREDO == adapter->TunnelType &&
/* Test the interface with the known Teredo network prefix.
*/
IN6_IS_ADDR_TEREDO(
&((struct sockaddr_in6*)(unicast->Address.lpSockaddr))->sin6_addr)
&&
/* Test that this version is actually wrong, subsequent releases from
* Microsoft may resolve the issue.
*/
32 != unicast->OnLinkPrefixLength)
{
#ifdef DEBUG
fprintf(stderr,
"IPv6 Teredo tunneling adapter %s prefix length is an "
"illegal value %lu, overriding to 32.\n",
adapter->AdapterName, unicast->OnLinkPrefixLength);
#endif
prefixLength = 32;
}
else
prefixLength = unicast->OnLinkPrefixLength;
#else
/* The order of linked IP_ADAPTER_UNICAST_ADDRESS structures pointed to by
* the FirstUnicastAddress member does not have any relationship with the
* order of linked IP_ADAPTER_PREFIX structures pointed to by the
* FirstPrefix member.
*
* Example enumeration:
* [ no subnet ]
* ::1/128 - address
* ff00::%1/8 - multicast (no IPv6 broadcast)
* 127.0.0.0/8 - subnet
* 127.0.0.1/32 - address
* 127.255.255.255/32 - subnet broadcast
* 224.0.0.0/4 - multicast
* 255.255.255.255/32 - broadcast
*
* Which differs from most adapters listing three IPv6:
* fe80::%10/64 - subnet
* fe80::51e9:5fe5:4202:325a%10/128 - address
* ff00::%10/8 - multicast
*
* !IfOperStatusUp IPv4 addresses are skipped:
* fe80::%13/64 - subnet
* fe80::d530:946d:e8df:8c91%13/128 - address
* ff00::%13/8 - multicast
* [ no subnet ]
* [ no address ]
* 224.0.0.0/4 - multicast
* 255.255.255.255/32 - broadcast
*
* On PTP links no multicast or broadcast addresses are returned:
* [ no subnet ]
* fe80::5efe:10.203.9.30/128 - address
* [ no multicast ]
* [ no multicast ]
* [ no broadcast ]
*
* Active primary IPv6 interfaces are a bit overloaded:
* ::/0 - default route
* 2001::/32 - global subnet
* 2001:0:4137:9e76:2443:d6:ba87:1a2a/128 - global address
* fe80::/64 - link-local subnet
* fe80::2443:d6:ba87:1a2a/128 - link-local address
* ff00::/8 - multicast
*/
#define IN_LINKLOCAL(a) ((((uint32_t)(a)) & 0xaffff0000) == 0xa9fe0000)
for(IP_ADAPTER_PREFIX* prefix = adapter->FirstPrefix; prefix;
prefix = prefix->Next)
{
LPSOCKADDR lpSockaddr = prefix->Address.lpSockaddr;
if(lpSockaddr->sa_family != unicast->Address.lpSockaddr->sa_family)
continue;
/* special cases */
/* RFC2863: IPv4 interface not up */
if(AF_INET == lpSockaddr->sa_family
&& adapter->OperStatus != IfOperStatusUp)
{
/* RFC3927: link-local IPv4 always has 16-bit CIDR */
if(IN_LINKLOCAL(
ntohl(((struct sockaddr_in*)(unicast->Address.lpSockaddr))
->sin_addr.s_addr)))
{
#ifdef DEBUG
fprintf(stderr,
"Assuming 16-bit prefix length for link-local IPv4 "
"adapter %s.\n",
adapter->AdapterName);
#endif
prefixLength = 16;
}
else
{
#ifdef DEBUG
fprintf(stderr, "Prefix length unavailable for IPv4 adapter %s.\n",
adapter->AdapterName);
#endif
}
break;
}
/* default IPv6 route */
if(AF_INET6 == lpSockaddr->sa_family && 0 == prefix->PrefixLength
&& IN6_IS_ADDR_UNSPECIFIED(
&((struct sockaddr_in6*)(lpSockaddr))->sin6_addr))
{
#ifdef DEBUG
fprintf(stderr,
"Ingoring unspecified address prefix on IPv6 adapter %s.\n",
adapter->AdapterName);
#endif
continue;
}
/* Assume unicast address for first prefix of operational adapter */
if(AF_INET == lpSockaddr->sa_family)
assert(!IN_MULTICAST(
ntohl(((struct sockaddr_in*)(lpSockaddr))->sin_addr.s_addr)));
if(AF_INET6 == lpSockaddr->sa_family)
assert(!IN6_IS_ADDR_MULTICAST(
&((struct sockaddr_in6*)(lpSockaddr))->sin6_addr));
/* Assume subnet or host IP address for XP backward compatibility */
prefixLength = prefix->PrefixLength;
break;
}
#endif /* defined( _WIN32 ) && ( _WIN32_WINNT >= 0x0600 ) */
/* map prefix to netmask */
ift->_ifa.ifa_netmask->sa_family = unicast->Address.lpSockaddr->sa_family;
switch(unicast->Address.lpSockaddr->sa_family)
{
case AF_INET:
if(0 == prefixLength || prefixLength > 32)
{
#ifdef DEBUG
fprintf(stderr,
"IPv4 adapter %s prefix length is an illegal value "
"%lu, overriding to 32.\n",
adapter->AdapterName, prefixLength);
#endif
prefixLength = 32;
}
/* NB: left-shift of full bit-width is undefined in C standard. */
((struct sockaddr_in*)ift->_ifa.ifa_netmask)->sin_addr.s_addr =
htonl(0xffffffffU << (32 - prefixLength));
break;
case AF_INET6:
if(0 == prefixLength || prefixLength > 128)
{
#ifdef DEBUG
fprintf(stderr,
"IPv6 adapter %s prefix length is an illegal value "
"%lu, overriding to 128.\n",
adapter->AdapterName, prefixLength);
#endif
prefixLength = 128;
}
for(LONG i = prefixLength, j = 0; i > 0; i -= 8, ++j)
{
((struct sockaddr_in6*)ift->_ifa.ifa_netmask)
->sin6_addr.s6_addr[j] =
i >= 8 ? 0xff : (ULONG)((0xffU << (8 - i)) & 0xffU);
}
break;
}
/* next */
if(k++ < (n - 1))
{
ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1);
ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next);
}
}
}
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
*ifap = (struct llarp_nt_ifaddrs_t*)ifa;
return TRUE;
}
#endif
// an implementation of if_nametoindex(3) based on GetAdapterIndex(2)
// with a fallback to GetAdaptersAddresses(2) commented out for now
// unless it becomes evident that the first codepath fails in certain
// edge cases?
static unsigned
_llarp_nt_getadaptersaddresses_nametoindex(const char* ifname)
{
ULONG ifIndex;
DWORD /* dwSize = 4096,*/ dwRet;
// IP_ADAPTER_ADDRESSES *pAdapterAddresses = nullptr, *adapter;
char szAdapterName[256];
if(!ifname)
return 0;
StringCchCopyN(szAdapterName, sizeof(szAdapterName), ifname, 256);
dwRet = GetAdapterIndex((LPWSTR)szAdapterName, &ifIndex);
if(!dwRet)
return ifIndex;
else
return 0;
#if 0
/* fallback to finding index via iterating adapter list */
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
pAdapterAddresses = (IP_ADAPTER_ADDRESSES*)_llarp_nt_heap_alloc(dwSize);
#ifdef _MSC_VER
dwRet = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#else
dwRet = _GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#endif
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterAddresses);
pAdapterAddresses = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS:
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
default:
errno = _doserrno;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
}
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
if(0 == strcmp(szAdapterName, adapter->AdapterName))
{
//ifIndex = AF_INET6 == iffamily ? adapter->Ipv6IfIndex : adapter->IfIndex;
_llarp_nt_heap_free(pAdapterAddresses);
return ifIndex;
}
}
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
#endif
}
// the emulated getifaddrs(3) itself.
static bool
llarp_nt_getifaddrs(struct llarp_nt_ifaddrs_t** ifap)
{
assert(nullptr != ifap);
#ifdef DEBUG
fprintf(stderr, "llarp_nt_getifaddrs (ifap:%p error:%p)\n", (void*)ifap,(void*)errno);
#endif
#ifdef _MSC_VER
return _llarp_nt_getadaptersaddresses(ifap);
#else
return _llarp_nt_getadaptersinfo(ifap);
#endif
}
static void
llarp_nt_freeifaddrs(struct llarp_nt_ifaddrs_t* ifa)
{
if(!ifa)
return;
free(ifa);
}
// emulated if_nametoindex(3)
static unsigned
llarp_nt_if_nametoindex(const char* ifname)
{
if(!ifname)
return 0;
return _llarp_nt_getadaptersaddresses_nametoindex(ifname);
}
// fix up names for win32
#define ifaddrs llarp_nt_ifaddrs_t
#define getifaddrs llarp_nt_getifaddrs
#define freeifaddrs llarp_nt_freeifaddrs
#define if_nametoindex llarp_nt_if_nametoindex
#endif
// jeff's original code
bool
llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
{
@ -51,7 +736,11 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
if(af == AF_INET)
sl = sizeof(sockaddr_in);
#ifndef _WIN32
if(getifaddrs(&ifa) == -1)
#else
if(!getifaddrs(&ifa))
#endif
return false;
ifaddrs* i = ifa;
while(i)
@ -86,7 +775,6 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
freeifaddrs(ifa);
return found;
}
namespace llarp
{
bool
@ -94,8 +782,11 @@ namespace llarp
{
ifaddrs* ifa = nullptr;
bool found = false;
#ifndef _WIN32
if(getifaddrs(&ifa) == -1)
#else
if(!getifaddrs(&ifa))
#endif
return false;
ifaddrs* i = ifa;
while(i)

View File

@ -12,6 +12,7 @@
#include "mem.hpp"
static const char skiplist_subdirs[] = "0123456789abcdef";
static const std::string RC_FILE_EXT = ".signed";
struct llarp_nodedb
{
@ -21,7 +22,7 @@ struct llarp_nodedb
llarp_crypto *crypto;
// std::map< llarp::pubkey, llarp_rc > entries;
std::unordered_map< llarp::PubKey, llarp_rc, llarp::PubKeyHash > entries;
std::unordered_map< llarp::PubKey, llarp_rc, llarp::PubKey::Hash > entries;
fs::path nodePath;
void
@ -38,11 +39,11 @@ struct llarp_nodedb
llarp_rc *
getRC(const llarp::PubKey &pk)
{
return &entries[pk];
return &entries.at(pk);
}
bool
Has(const llarp::PubKey &pk)
Has(const llarp::PubKey &pk) const
{
return entries.find(pk) != entries.end();
}
@ -66,7 +67,7 @@ struct llarp_nodedb
*/
bool
pubKeyExists(llarp_rc *rc)
pubKeyExists(llarp_rc *rc) const
{
// extract pk from rc
llarp::PubKey pk = rc->pubkey;
@ -85,6 +86,8 @@ struct llarp_nodedb
llarp::PubKey pk = rc->pubkey;
// TODO: zero out any fields you don't want to compare
// XXX: make a copy and then do modifications on the copy
// touching external data in here is HARAM >:[
// serialize both and memcmp
byte_t nodetmp[MAX_RC_SIZE];
@ -103,19 +106,17 @@ struct llarp_nodedb
}
std::string
getRCFilePath(const byte_t *pubkey)
getRCFilePath(const byte_t *pubkey) const
{
char ftmp[68] = {0};
const char *hexname =
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(pubkey, ftmp);
std::string hexString(hexname);
std::string filepath = nodePath;
filepath.append(PATH_SEP);
filepath.append(&hexString[hexString.length() - 1]);
filepath.append(PATH_SEP);
filepath.append(hexname);
filepath.append(".signed");
return filepath;
hexString += RC_FILE_EXT;
std::string skiplistDir;
skiplistDir += hexString[hexString.length() - 1];
fs::path filepath = nodePath / skiplistDir / hexString;
return filepath.string();
}
bool
@ -166,6 +167,8 @@ struct llarp_nodedb
for(const char &ch : skiplist_subdirs)
{
if(!ch)
continue;
std::string p;
p += ch;
fs::path sub = path / p;
@ -182,7 +185,7 @@ struct llarp_nodedb
{
ssize_t sz = 0;
fs::directory_iterator i(dir);
#if __has_include(<filesystem>) && !defined(__OpenBSD__)
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
auto itr = fs::begin(i);
while(itr != fs::end(i))
#else
@ -190,7 +193,7 @@ struct llarp_nodedb
while(itr != itr.end())
#endif
{
if(fs::is_regular_file(itr->symlink_status()) && loadfile(*itr))
if(fs::is_regular_file(itr->path()) && loadfile(*itr))
sz++;
++itr;
@ -201,16 +204,12 @@ struct llarp_nodedb
bool
loadfile(const fs::path &fpath)
{
#if __APPLE__ && __MACH__
// skip .DS_Store files
if(strstr(fpath.c_str(), ".DS_Store") != 0)
{
if(fpath.extension() != RC_FILE_EXT)
return false;
}
#endif
llarp_rc rc;
llarp_rc_clear(&rc);
if(!llarp_rc_read(fpath.c_str(), &rc))
if(!llarp_rc_read(fpath.string().c_str(), &rc))
{
llarp::LogError("Signature read failed", fpath);
return false;
@ -287,7 +286,7 @@ crypto_threadworker_verifyrc(void *user)
verify_request->valid =
llarp_rc_verify_sig(verify_request->nodedb->crypto, &verify_request->rc);
// if it's valid we need to set it
if(verify_request->valid)
if(verify_request->valid && llarp_rc_is_public_router(&verify_request->rc))
{
llarp::LogDebug("RC is valid, saving to disk");
llarp_threadpool_queue_job(verify_request->diskworker,
@ -296,7 +295,8 @@ crypto_threadworker_verifyrc(void *user)
else
{
// callback to logic thread
llarp::LogWarn("RC is not valid, can't save to disk");
if(!verify_request->valid)
llarp::LogWarn("RC is not valid, can't save to disk");
llarp_logic_queue_job(verify_request->logic,
{verify_request, &logic_threadworker_callback});
}
@ -347,6 +347,7 @@ llarp_nodedb_ensure_dir(const char *dir)
{
fs::path path(dir);
std::error_code ec;
if(!fs::exists(dir, ec))
fs::create_directories(path, ec);
@ -358,6 +359,11 @@ llarp_nodedb_ensure_dir(const char *dir)
for(const char &ch : skiplist_subdirs)
{
// this seems to be a problem on all targets
// perhaps cpp17::fs is just as screwed-up
// attempting to create a folder with no name
if(!ch)
return true;
std::string p;
p += ch;
fs::path sub = path / p;
@ -435,7 +441,8 @@ void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
struct llarp_rc *result, size_t N)
{
/// TODO: check for "guard" status for N = 0?
/// checking for "guard" status for N = 0 is done by caller inside of
/// pathbuilder's scope
auto sz = n->entries.size();
if(prev)

View File

@ -5,7 +5,6 @@
#include "buffer.hpp"
#include "router.hpp"
namespace llarp
{
namespace path
@ -463,6 +462,14 @@ namespace llarp
return false;
}
bool
Path::HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* frame)
{
if(m_DataHandler)
return m_DataHandler(frame);
return false;
}
bool
Path::HandlePathLatencyMessage(
const llarp::routing::PathLatencyMessage* msg, llarp_router* r)

View File

@ -119,7 +119,7 @@ namespace llarp
user = u;
result = func;
worker = pool;
LRCM = new LR_CommitMessage;
LRCM = new LR_CommitMessage();
for(size_t idx = 0; idx < MAXHOPS; ++idx)
{
@ -187,6 +187,7 @@ llarp_pathbuilder_context::llarp_pathbuilder_context(
: llarp::path::PathSet(pathNum), router(p_router), dht(p_dht), numHops(hops)
{
p_router->paths.AddPathBuilder(this);
p_router->crypto.encryption_keygen(enckey);
}
bool
@ -200,6 +201,12 @@ llarp_pathbuilder_context::SelectHop(llarp_nodedb* db, llarp_rc* prev,
return true;
}
byte_t*
llarp_pathbuilder_context::GetTunnelEncryptionSecretKey()
{
return enckey;
}
void
llarp_pathbuilder_context::BuildOne()
{

View File

@ -46,7 +46,27 @@ namespace llarp
}
Path*
PathSet::GetPathByRouter(const RouterID& id)
PathSet::GetEstablishedPathClosestTo(const AlignedBuffer< 32 >& id) const
{
Path* path = nullptr;
AlignedBuffer< 32 > dist;
dist.Fill(0xff);
for(const auto& item : m_Paths)
{
if(!item.second->IsReady())
continue;
AlignedBuffer< 32 > localDist = item.second->Endpoint() ^ id;
if(localDist < dist)
{
dist = localDist;
path = item.second;
}
}
return path;
}
Path*
PathSet::GetPathByRouter(const RouterID& id) const
{
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
@ -89,7 +109,7 @@ namespace llarp
}
Path*
PathSet::GetByUpstream(const RouterID& remote, const PathID_t& rxid)
PathSet::GetByUpstream(const RouterID& remote, const PathID_t& rxid) const
{
auto itr = m_Paths.find({remote, rxid});
if(itr == m_Paths.end())
@ -125,7 +145,7 @@ namespace llarp
}
Path*
PathSet::PickRandomEstablishedPath()
PathSet::PickRandomEstablishedPath() const
{
std::vector< Path* > established;
auto itr = m_Paths.begin();

View File

@ -166,7 +166,7 @@ llarp_router::try_connect(fs::path rcfile)
{
llarp_rc remote;
llarp_rc_new(&remote);
if(!llarp_rc_read(rcfile.c_str(), &remote))
if(!llarp_rc_read(rcfile.string().c_str(), &remote))
{
llarp::LogError("failure to decode or verify of remote RC");
return;
@ -196,14 +196,15 @@ llarp_router::EnsureIdentity()
{
if(!EnsureEncryptionKey())
return false;
return llarp_findOrCreateIdentity(&crypto, ident_keyfile.c_str(), identity);
return llarp_findOrCreateIdentity(&crypto, ident_keyfile.string().c_str(),
identity);
}
bool
llarp_router::EnsureEncryptionKey()
{
return llarp_findOrCreateEncryption(&crypto, encryption_keyfile.c_str(),
&this->encryption);
return llarp_findOrCreateEncryption(
&crypto, encryption_keyfile.string().c_str(), &this->encryption);
}
void
@ -233,15 +234,16 @@ llarp_router::SaveRC()
if(llarp_rc_bencode(&rc, &buf))
{
std::ofstream f(our_rc_file);
std::ofstream f(our_rc_file.string());
if(f.is_open())
{
f.write((char *)buf.base, buf.cur - buf.base);
llarp::LogInfo("our RC saved to ", our_rc_file.c_str());
llarp::LogInfo("our RC saved to ", our_rc_file.string().c_str());
return true;
}
}
llarp::LogError("did not save RC to ", our_rc_file.c_str());
llarp::LogError("did not save RC to ", our_rc_file.string().c_str());
return false;
}
@ -384,7 +386,6 @@ llarp_router::Tick()
paths.TickPaths();
}
void
llarp_router::SendTo(llarp::RouterID remote, const llarp::ILinkMessage *msg,
llarp_link *link)
@ -500,8 +501,8 @@ llarp_router::on_try_connect_result(llarp_link_establish_job *job)
if(job->session)
{
// llarp::LogDebug("try_connect got session");
auto session = job->session;
router->async_verify_RC(session->get_remote_router(), false, job);
// auto session = job->session;
// router->async_verify_RC(session->get_remote_router(), false, job);
return;
}
// llarp::LogDebug("try_connect no session");
@ -574,20 +575,16 @@ llarp_router::async_verify_RC(llarp_rc *rc, bool isExpectingClient,
job->hook = &llarp_router::on_verify_client_rc;
else
job->hook = &llarp_router::on_verify_server_rc;
llarp_nodedb_async_verify(job);
}
#include <string.h>
void
llarp_router::Run()
{
// zero out router contact
llarp::Zero(&rc, sizeof(llarp_rc));
// fill our address list
rc.addrs = llarp_ai_list_new();
bool publicFound = false;
rc.addrs = llarp_ai_list_new();
sockaddr *dest = (sockaddr *)&this->ip4addr;
llarp::Addr publicAddr(*dest);
@ -596,7 +593,6 @@ llarp_router::Run()
if(publicAddr)
{
llarp::LogInfo("public address:port ", publicAddr);
;
}
}
@ -609,17 +605,8 @@ llarp_router::Run()
if(this->publicOverride && a.sameAddr(publicAddr))
{
llarp::LogInfo("Found adapter for public address");
publicFound = true;
}
if(a.isPrivate())
{
if(!this->publicOverride)
{
llarp::LogWarn("Skipping private network link: ", a);
continue;
}
}
else
if(!a.isPrivate())
{
llarp::LogInfo("Loading Addr: ", a, " into our RC");
llarp_ai_list_pushback(rc.addrs, &addr);
@ -758,11 +745,7 @@ llarp_router::InitOutboundLink()
return true;
llarp_iwp_args args = {
.crypto = &crypto,
.logic = logic,
.cryptoworker = tp,
.router = this,
.keyfile = transport_keyfile.c_str(),
&crypto, logic, tp, this, transport_keyfile.string().c_str(),
};
auto link = new(std::nothrow) llarp_link(args);
@ -915,7 +898,9 @@ llarp_rc_read(const char *fpath, llarp_rc *result)
printf("File[%s] not found\n", fpath);
return false;
}
std::ifstream f(our_rc_file, std::ios::binary);
std::ifstream f(our_rc_file.string(), std::ios::binary);
if(!f.is_open())
{
printf("Can't open file [%s]\n", fpath);
@ -935,7 +920,7 @@ llarp_rc_read(const char *fpath, llarp_rc *result)
llarp::Zero(result, sizeof(llarp_rc));
if(!llarp_rc_bdecode(result, &buf))
{
printf("Can't decode [%s]\n", fpath);
llarp::LogError("Can't decode ", fpath);
return false;
}
return true;
@ -969,7 +954,7 @@ llarp_rc_write(struct llarp_rc *rc, const char *fpath)
if(llarp_rc_bencode(rc, &buf))
{
std::ofstream f(our_rc_file, std::ios::binary);
std::ofstream f(our_rc_file.string(), std::ios::binary);
if(f.is_open())
{
f.write((char *)buf.base, buf.cur - buf.base);
@ -1041,13 +1026,13 @@ llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
{
llarp::LogInfo("generating new identity key");
crypto->identity_keygen(secretkey);
std::ofstream f(path, std::ios::binary);
std::ofstream f(path.string(), std::ios::binary);
if(f.is_open())
{
f.write((char *)secretkey, SECKEYSIZE);
}
}
std::ifstream f(path, std::ios::binary);
std::ifstream f(path.string(), std::ios::binary);
if(f.is_open())
{
f.read((char *)secretkey, SECKEYSIZE);
@ -1069,13 +1054,14 @@ llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath,
{
llarp::LogInfo("generating new encryption key");
crypto->encryption_keygen(*encryption);
std::ofstream f(path, std::ios::binary);
std::ofstream f(path.string(), std::ios::binary);
if(f.is_open())
{
f.write((char *)encryption, SECKEYSIZE);
}
}
std::ifstream f(path, std::ios::binary);
std::ifstream f(path.string(), std::ios::binary);
if(f.is_open())
{
f.read((char *)encryption, SECKEYSIZE);
@ -1132,12 +1118,13 @@ namespace llarp
if(!StrEq(key, "*"))
{
llarp::LogInfo("interface specific binding activated");
llarp_iwp_args args = {
.crypto = &self->crypto,
.logic = self->logic,
.cryptoworker = self->tp,
.router = self,
.keyfile = self->transport_keyfile.c_str(),
&self->crypto,
self->logic,
self->tp,
self,
self->transport_keyfile.string().c_str(),
};
link = new(std::nothrow) llarp_link(args);
@ -1190,6 +1177,16 @@ namespace llarp
}
else if(StrEq(section, "router"))
{
if(StrEq(key, "nickname"))
{
if(llarp_rc_set_nickname(&self->rc, val))
{
// set logger name here
_glog.nodeName = self->rc.Nick();
}
else
llarp::LogWarn("failed to set nickname to ", val);
}
if(StrEq(key, "encryption-privkey"))
{
self->encryption_keyfile = val;

View File

@ -4,6 +4,7 @@
#include <llarp/crypto.hpp>
#include "buffer.hpp"
#include "logger.hpp"
#include "mem.hpp"
bool
llarp_rc_new(struct llarp_rc *rc)
@ -11,6 +12,7 @@ llarp_rc_new(struct llarp_rc *rc)
rc->addrs = llarp_ai_list_new();
rc->exits = llarp_xi_list_new();
rc->last_updated = 0;
llarp::Zero(rc->nickname, sizeof(rc->nickname));
return true;
}
@ -62,6 +64,17 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
return true;
}
if(llarp_buffer_eq(*key, "n"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz > sizeof(rc->nickname))
return false;
llarp::Zero(rc->nickname, sizeof(rc->nickname));
memcpy(rc->nickname, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "p"))
{
if(!bencode_read_string(r->buffer, &strbuf))
@ -115,6 +128,14 @@ llarp_rc_is_public_router(const struct llarp_rc *const rc)
return rc->addrs && llarp_ai_list_size(rc->addrs) > 0;
}
bool
llarp_rc_set_nickname(struct llarp_rc *rc, const char *nick)
{
strncpy((char *)rc->nickname, nick, sizeof(rc->nickname));
/// TODO: report nickname truncation
return true;
}
void
llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src)
{
@ -135,6 +156,7 @@ llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src)
dst->exits = llarp_xi_list_new();
llarp_xi_list_copy(dst->exits, src->exits);
}
memcpy(dst->nickname, src->nickname, sizeof(dst->nickname));
}
bool
@ -198,6 +220,14 @@ llarp_rc_bencode(const struct llarp_rc *rc, llarp_buffer_t *buff)
if(!bencode_write_bytestring(buff, rc->pubkey, PUBKEYSIZE))
return false;
/* write nickname */
if(!bencode_write_bytestring(buff, "n", 1))
return false;
if(!bencode_write_bytestring(
buff, rc->nickname,
strnlen((char *)rc->nickname, sizeof(rc->nickname))))
return false;
/* write encryption pubkey */
if(!bencode_write_bytestring(buff, "p", 1))
return false;

View File

@ -1,3 +1,7 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/service.hpp>
#include "buffer.hpp"
#include "fs.hpp"

View File

@ -11,5 +11,15 @@ namespace llarp
std::string str = Base32Encode(*this, tmp);
return str + ".loki";
}
bool
Address::FromString(const std::string& str)
{
auto pos = str.find(".loki");
if(pos == std::string::npos)
return false;
auto sub = str.substr(0, pos);
return Base32Decode(sub, *this);
}
} // namespace service
} // namespace llarp

View File

@ -1,3 +1,4 @@
#include <llarp/dht/messages/findintro.hpp>
#include <llarp/messages/dht.hpp>
#include <llarp/service/endpoint.hpp>
@ -31,6 +32,12 @@ namespace llarp
{
m_PrefetchTags.insert(v);
}
if(k == "prefetch-addr")
{
Address addr;
if(addr.FromString(v))
m_PrefetchAddrs.insert(addr);
}
return true;
}
@ -47,6 +54,7 @@ namespace llarp
{
if(context)
{
llarp::LogInfo("BEEP");
byte_t tmp[128] = {0};
memcpy(tmp, "BEEP", 4);
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
@ -109,6 +117,22 @@ namespace llarp
}
}
for(const auto& addr : m_PrefetchAddrs)
{
if(!HasPathToService(addr))
{
PathAlignJob* j = new PathAlignJob(addr);
if(!EnsurePathToService(j->remote,
std::bind(&PathAlignJob::HandleResult, j,
std::placeholders::_1),
10000))
{
llarp::LogWarn("failed to ensure path to ", addr);
delete j;
}
}
}
// prefetch tags
for(const auto& tag : m_PrefetchTags)
{
@ -116,7 +140,8 @@ namespace llarp
if(itr == m_PrefetchedTags.end())
{
itr = m_PrefetchedTags
.insert(std::make_pair(tag, CachedTagResult(tag, now)))
.insert(std::make_pair(
tag, CachedTagResult(this, tag, GenTXID())))
.first;
}
for(const auto& introset : itr->second.result)
@ -126,7 +151,11 @@ namespace llarp
std::bind(&PathAlignJob::HandleResult, j,
std::placeholders::_1),
10000))
{
llarp::LogWarn("failed to ensure path to ", introset.A.Addr(),
" for tag");
delete j;
}
}
itr->second.Expire(now);
if(itr->second.ShouldRefresh(now))
@ -134,8 +163,7 @@ namespace llarp
auto path = PickRandomEstablishedPath();
if(path)
{
itr->second.pendingTX = GenTXID();
m_PendingLookups[itr->second.pendingTX] = &itr->second;
itr->second.txid = GenTXID();
itr->second.SendRequestViaPath(path, m_Router);
}
}
@ -172,6 +200,18 @@ namespace llarp
return m_Name + ":" + m_Identity.pub.Name();
}
bool
Endpoint::HasPathToService(const Address& addr) const
{
return m_RemoteSessions.find(addr) != m_RemoteSessions.end();
}
void
Endpoint::PutLookup(IServiceLookup* lookup, uint64_t txid)
{
m_PendingLookups.insert(std::make_pair(txid, lookup));
}
bool
Endpoint::HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg)
{
@ -245,7 +285,7 @@ namespace llarp
{
auto now = llarp_time_now_ms();
pendingTX = 0;
txid = 0;
for(const auto& introset : introsets)
if(result.insert(introset).second)
lastModified = now;
@ -279,21 +319,22 @@ namespace llarp
Endpoint::CachedTagResult::BuildRequestMessage()
{
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage(tag, pendingTX));
msg->M.push_back(new llarp::dht::FindIntroMessage(tag, txid));
lastRequest = llarp_time_now_ms();
parent->PutLookup(this, txid);
return msg;
}
bool
Endpoint::PublishIntroSet(llarp_router* r)
{
auto path = PickRandomEstablishedPath();
auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr());
if(path)
{
m_CurrentPublishTX = llarp_randint();
llarp::routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::PublishIntroMessage(
m_IntroSet, m_CurrentPublishTX, 3));
m_IntroSet, m_CurrentPublishTX, 4));
if(path->SendRoutingMessage(&msg, r))
{
m_LastPublishAttempt = llarp_time_now_ms();
@ -301,7 +342,7 @@ namespace llarp
return true;
}
}
llarp::LogWarn(Name(), " publish introset failed");
llarp::LogWarn(Name(), " publish introset failed, no path");
return false;
}
@ -332,12 +373,11 @@ namespace llarp
struct HiddenServiceAddressLookup : public IServiceLookup
{
Endpoint* endpoint;
Address remote;
uint64_t txid;
HiddenServiceAddressLookup(Endpoint* parent, const Address& addr,
uint64_t tx)
: endpoint(parent), remote(addr), txid(tx)
Endpoint* endpoint;
HiddenServiceAddressLookup(Endpoint* p, const Address& addr, uint64_t tx)
: IServiceLookup(p, tx), remote(addr), endpoint(p)
{
llarp::LogInfo("New hidden service lookup for ", addr.ToString());
}
@ -392,16 +432,52 @@ namespace llarp
}
}
void
Endpoint::HandlePathBuilt(path::Path* p)
{
p->SetDataHandler(std::bind(&Endpoint::HandleHiddenServiceFrame, this,
std::placeholders::_1));
}
bool
Endpoint::HandleHiddenServiceFrame(const ProtocolFrame* frame)
{
llarp::LogInfo("handle hidden service frame");
return true;
}
void
Endpoint::OutboundContext::HandlePathBuilt(path::Path* p)
{
p->SetDataHandler(
std::bind(&Endpoint::OutboundContext::HandleHiddenServiceFrame, this,
std::placeholders::_1));
}
void
Endpoint::OutboundContext::PutLookup(IServiceLookup* lookup, uint64_t txid)
{
m_Parent->PutLookup(lookup, txid);
}
bool
Endpoint::OutboundContext::HandleHiddenServiceFrame(
const ProtocolFrame* frame)
{
return m_Parent->HandleHiddenServiceFrame(frame);
}
bool
Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook,
llarp_time_t timeoutMS)
{
auto path = PickRandomEstablishedPath();
auto path = GetEstablishedPathClosestTo(remote);
if(!path)
{
llarp::LogWarn("No outbound path for lookup yet");
return false;
}
llarp::LogInfo(Name(), " Ensure Path to ", remote.ToString());
{
auto itr = m_RemoteSessions.find(remote);
if(itr != m_RemoteSessions.end())
@ -414,15 +490,15 @@ namespace llarp
if(itr != m_PendingServiceLookups.end())
{
// duplicate
llarp::LogWarn("duplicate pending service lookup to ",
remote.ToString());
return false;
}
llarp::LogInfo(Name(), " Ensure Path to ", remote.ToString());
m_PendingServiceLookups.insert(std::make_pair(remote, hook));
HiddenServiceAddressLookup* job =
new HiddenServiceAddressLookup(this, remote, GenTXID());
m_PendingLookups.insert(std::make_pair(job->txid, job));
return job->SendRequestViaPath(path, Router());
}
@ -459,20 +535,30 @@ namespace llarp
Endpoint::OutboundContext::HandleGotIntroMessage(
const llarp::dht::GotIntroMessage* msg)
{
if(msg->T != m_UpdateIntrosetTX)
{
llarp::LogError("unwarrented introset message txid=", msg->T);
return false;
}
auto crypto = m_Parent->Crypto();
if(msg->I.size() == 1)
{
// found intro set
auto itr = msg->I.begin();
if(itr->VerifySignature(crypto) && currentIntroSet.A == itr->A)
const auto& introset = msg->I[0];
if(introset.VerifySignature(crypto) && currentIntroSet.A == introset.A)
{
currentIntroSet = *itr;
// update
currentIntroSet = introset;
// reset tx
m_UpdateIntrosetTX = 0;
// shift to newest intro
// TODO: check timestamp on introset to make sure it's new enough
ShiftIntroduction();
return true;
}
else
{
llarp::LogError("Signature Error for intro set ", *itr);
llarp::LogError("Signature Error for intro set ", introset);
return false;
}
}
@ -575,7 +661,7 @@ namespace llarp
transfer.Y.Randomize();
transfer.P = selectedIntro.pathID;
llarp::LogInfo("sending frame via ", path->Upstream(), " to ",
path->Endpoint());
path->Endpoint(), " for ", Name());
path->SendRoutingMessage(&transfer, m_Parent->Router());
}
else
@ -584,17 +670,27 @@ namespace llarp
}
}
std::string
Endpoint::OutboundContext::Name() const
{
return "OBContext:" + m_Parent->Name() + "-"
+ currentIntroSet.A.Addr().ToString();
}
void
Endpoint::OutboundContext::UpdateIntroSet()
{
auto path = PickRandomEstablishedPath();
auto path = GetEstablishedPathClosestTo(currentIntroSet.A.Addr());
if(path)
{
uint64_t txid = llarp_randint();
routing::DHTMessage msg;
msg.M.push_back(
new llarp::dht::FindIntroMessage(currentIntroSet.A.Addr(), txid));
path->SendRoutingMessage(&msg, m_Parent->Router());
if(m_UpdateIntrosetTX == 0)
{
m_UpdateIntrosetTX = llarp_randint();
routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::FindIntroMessage(
currentIntroSet.A.Addr(), m_UpdateIntrosetTX));
path->SendRoutingMessage(&msg, m_Parent->Router());
}
}
else
{

View File

@ -1,9 +1,17 @@
#include <llarp/path.hpp>
#include <llarp/service/endpoint.hpp>
#include <llarp/service/lookup.hpp>
namespace llarp
{
namespace service
{
IServiceLookup::IServiceLookup(ILookupHolder *p, uint64_t tx)
: parent(p), txid(tx)
{
p->PutLookup(this, tx);
}
bool
IServiceLookup::SendRequestViaPath(llarp::path::Path *path, llarp_router *r)
{

View File

@ -17,8 +17,9 @@ namespace llarp
bool
ProtocolMessage::BEncode(llarp_buffer_t* buf) const
{
// TODO: implement me
return false;
if(!bencode_start_dict(buf))
return false;
return bencode_end(buf);
}
bool

View File

@ -1,5 +1,7 @@
#include "threadpool.hpp"
#ifndef _MSC_VER
#include <pthread.h>
#endif
#include <cstring>
#include <llarp/time.h>
@ -11,6 +13,12 @@
#include <pthread_np.h>
#endif
#ifdef _MSC_VER
#include <windows.h>
extern "C" void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#endif
namespace llarp
{
namespace thread
@ -27,8 +35,10 @@ namespace llarp
pthread_setname_np(name);
#elif(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
pthread_set_name_np(pthread_self(), name);
#else
#elif !defined(_MSC_VER) || !defined(_WIN32)
pthread_setname_np(pthread_self(), name);
#else
SetThreadName(GetCurrentThreadId(), name);
#endif
}
for(;;)
@ -93,6 +103,7 @@ struct llarp_threadpool
{
llarp::thread::Pool *impl;
std::mutex m_access;
std::queue< llarp_thread_job * > jobs;
llarp_threadpool(int workers, const char *name)
@ -159,8 +170,16 @@ llarp_threadpool_queue_job(struct llarp_threadpool *pool,
{
if(pool->impl)
pool->impl->QueueJob(job);
else
pool->jobs.push(new llarp_thread_job(job));
else if(job.user && job.work)
{
auto j = new llarp_thread_job;
j->work = job.work;
j->user = job.user;
{
std::unique_lock< std::mutex > lock(pool->m_access);
pool->jobs.push(j);
}
}
}
void
@ -168,11 +187,14 @@ llarp_threadpool_tick(struct llarp_threadpool *pool)
{
while(pool->jobs.size())
{
auto &job = pool->jobs.front();
if(job && job->work && job->user)
job->work(job->user);
llarp_thread_job *job;
{
std::unique_lock< std::mutex > lock(pool->m_access);
job = pool->jobs.front();
pool->jobs.pop();
}
job->work(job->user);
delete job;
pool->jobs.pop();
}
}

312
llarp/win32_inet.c Normal file
View File

@ -0,0 +1,312 @@
#if defined(__MINGW32__) && !defined(_WIN64)
/*
* Contains routines missing from WS2_32.DLL until 2006, if yer using
* Microsoft C/C++, then this code is irrelevant, as the official
* Platform SDK already links against these routines in the correct
* libraries.
*
* -despair86 30/07/18
*/
#include <assert.h>
#include <llarp/net.h>
#include <windows.h>
#include <iphlpapi.h>
#include "win32_intrnl.h"
const char *
inet_ntop(int af, const void *src, char *dst, size_t size)
{
int address_length;
DWORD string_length = size;
struct sockaddr_storage sa;
struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
memset(&sa, 0, sizeof(sa));
switch(af)
{
case AF_INET:
address_length = sizeof(struct sockaddr_in);
sin->sin_family = af;
memcpy(&sin->sin_addr, src, sizeof(struct in_addr));
break;
case AF_INET6:
address_length = sizeof(struct sockaddr_in6);
sin6->sin6_family = af;
memcpy(&sin6->sin6_addr, src, sizeof(struct in6_addr));
break;
default:
return NULL;
}
if(WSAAddressToString((LPSOCKADDR)&sa, address_length, NULL, dst,
&string_length)
== 0)
{
return dst;
}
return NULL;
}
int
inet_pton(int af, const char *src, void *dst)
{
int address_length;
struct sockaddr_storage sa;
struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
switch(af)
{
case AF_INET:
address_length = sizeof(struct sockaddr_in);
break;
case AF_INET6:
address_length = sizeof(struct sockaddr_in6);
break;
default:
return -1;
}
if(WSAStringToAddress((LPTSTR)src, af, NULL, (LPSOCKADDR)&sa, &address_length)
== 0)
{
switch(af)
{
case AF_INET:
memcpy(dst, &sin->sin_addr, sizeof(struct in_addr));
break;
case AF_INET6:
memcpy(dst, &sin6->sin6_addr, sizeof(struct in6_addr));
break;
}
return 1;
}
return 0;
}
typedef struct _InterfaceIndexTable
{
DWORD numIndexes;
IF_INDEX indexes[1];
} InterfaceIndexTable;
// windows 2000
// todo(despair86): implement IPv6 detection using
// the ipv6 preview stack/adv net pack from 1999/2001
DWORD FAR PASCAL
_GetAdaptersAddresses(ULONG Family, ULONG Flags, PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen)
{
InterfaceIndexTable *indexTable;
IFInfo ifInfo;
int i;
ULONG ret, requiredSize = 0;
PIP_ADAPTER_ADDRESSES currentAddress;
PUCHAR currentLocation;
HANDLE tcpFile;
if(!pOutBufLen)
return ERROR_INVALID_PARAMETER;
if(Reserved)
return ERROR_INVALID_PARAMETER;
indexTable = getInterfaceIndexTable();
if(!indexTable)
return ERROR_NOT_ENOUGH_MEMORY;
ret = openTcpFile(&tcpFile, FILE_READ_DATA);
if(!NT_SUCCESS(ret))
return ERROR_NO_DATA;
for(i = indexTable->numIndexes; i >= 0; i--)
{
if(NT_SUCCESS(
getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
/* The whole struct */
requiredSize += sizeof(IP_ADAPTER_ADDRESSES);
/* Friendly name */
if(!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
requiredSize +=
strlen((char *)ifInfo.if_info.ent.if_descr) + 1; // FIXME
/* Adapter name */
requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
/* Unicast address */
if(!(Flags & GAA_FLAG_SKIP_UNICAST))
requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
/* FIXME: Implement multicast, anycast, and dns server stuff */
/* FIXME: Implement dns suffix and description */
requiredSize += 2 * sizeof(WCHAR);
/* We're only going to implement what's required for XP SP0 */
}
}
#ifdef DEBUG
fprintf(stderr, "size: %ld, requiredSize: %ld\n", *pOutBufLen, requiredSize);
#endif
if(!pAdapterAddresses || *pOutBufLen < requiredSize)
{
*pOutBufLen = requiredSize;
closeTcpFile(tcpFile);
free(indexTable);
return ERROR_BUFFER_OVERFLOW;
}
RtlZeroMemory(pAdapterAddresses, requiredSize);
/* Let's set up the pointers */
currentAddress = pAdapterAddresses;
for(i = indexTable->numIndexes; i >= 0; i--)
{
if(NT_SUCCESS(
getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
currentLocation =
(PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES);
/* FIXME: Friendly name */
if(!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
{
currentAddress->FriendlyName = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
}
/* Adapter name */
currentAddress->AdapterName = (PVOID)currentLocation;
currentLocation += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
/* Unicast address */
if(!(Flags & GAA_FLAG_SKIP_UNICAST))
{
currentAddress->FirstUnicastAddress = (PVOID)currentLocation;
currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
currentAddress->FirstUnicastAddress->Address.lpSockaddr =
(PVOID)currentLocation;
currentLocation += sizeof(struct sockaddr);
}
/* FIXME: Implement multicast, anycast, and dns server stuff */
/* FIXME: Implement dns suffix and description */
currentAddress->DnsSuffix = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
currentAddress->Description = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
currentAddress->Next = (PVOID)currentLocation;
/* Terminate the last address correctly */
if(i == 0)
currentAddress->Next = NULL;
/* We're only going to implement what's required for XP SP0 */
currentAddress = currentAddress->Next;
}
}
/* Now again, for real this time */
currentAddress = pAdapterAddresses;
for(i = indexTable->numIndexes; i >= 0; i--)
{
if(NT_SUCCESS(
getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
/* Make sure we're not looping more than we hoped for */
assert(currentAddress);
/* Alignment information */
currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES);
currentAddress->IfIndex = indexTable->indexes[i];
/* Adapter name */
strcpy(currentAddress->AdapterName, (char *)ifInfo.if_info.ent.if_descr);
if(!(Flags & GAA_FLAG_SKIP_UNICAST))
{
currentAddress->FirstUnicastAddress->Length =
sizeof(IP_ADAPTER_UNICAST_ADDRESS);
currentAddress->FirstUnicastAddress->Flags = 0; // FIXME
currentAddress->FirstUnicastAddress->Next =
NULL; // FIXME: Support more than one address per adapter
currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family =
AF_INET;
memcpy(currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data,
&ifInfo.ip_addr.iae_addr, sizeof(ifInfo.ip_addr.iae_addr));
currentAddress->FirstUnicastAddress->Address.iSockaddrLength =
sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT);
currentAddress->FirstUnicastAddress->PrefixOrigin =
IpPrefixOriginOther; // FIXME
currentAddress->FirstUnicastAddress->SuffixOrigin =
IpPrefixOriginOther; // FIXME
currentAddress->FirstUnicastAddress->DadState =
IpDadStatePreferred; // FIXME
currentAddress->FirstUnicastAddress->ValidLifetime =
0xFFFFFFFF; // FIXME
currentAddress->FirstUnicastAddress->PreferredLifetime =
0xFFFFFFFF; // FIXME
currentAddress->FirstUnicastAddress->LeaseLifetime =
0xFFFFFFFF; // FIXME
}
/* FIXME: Implement multicast, anycast, and dns server stuff */
currentAddress->FirstAnycastAddress = NULL;
currentAddress->FirstMulticastAddress = NULL;
currentAddress->FirstDnsServerAddress = NULL;
/* FIXME: Implement dns suffix, description, and friendly name */
currentAddress->DnsSuffix[0] = UNICODE_NULL;
currentAddress->Description[0] = UNICODE_NULL;
currentAddress->FriendlyName[0] = UNICODE_NULL;
/* Physical Address */
memcpy(currentAddress->PhysicalAddress, ifInfo.if_info.ent.if_physaddr,
ifInfo.if_info.ent.if_physaddrlen);
currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen;
/* Flags */
currentAddress->Flags = 0; // FIXME
/* MTU */
currentAddress->Mtu = ifInfo.if_info.ent.if_mtu;
/* Interface type */
currentAddress->IfType = ifInfo.if_info.ent.if_type;
/* Operational status */
if(ifInfo.if_info.ent.if_operstatus >= IF_OPER_STATUS_CONNECTING)
currentAddress->OperStatus = IfOperStatusUp;
else
currentAddress->OperStatus = IfOperStatusDown;
/* We're only going to implement what's required for XP SP0 */
/* Move to the next address */
currentAddress = currentAddress->Next;
}
}
closeTcpFile(tcpFile);
free(indexTable);
return NO_ERROR;
}
#elif _MSC_VER
/* just a comment */
static void* unused;
#endif

540
llarp/win32_intrnl.c Normal file
View File

@ -0,0 +1,540 @@
#if defined(__MINGW32__) && !defined(_WIN64)
/*
* All the user-mode scaffolding necessary to backport GetAdaptersAddresses(2))
* to the NT 5.x series. See further comments for any limitations.
*
* -despair86 30/07/18
*/
#include <assert.h>
#include <stdio.h>
// apparently mingw-w64 loses its shit over this
// but only for 32-bit builds, naturally
#ifdef WIN32_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winternl.h>
#include <tdi.h>
#include "win32_intrnl.h"
const PWCHAR TcpFileName = L"\\Device\\Tcp";
// from ntdll.dll
typedef void(FAR PASCAL *pRtlInitUString)(UNICODE_STRING *, const WCHAR *);
typedef NTSTATUS(FAR PASCAL *pNTOpenFile)(HANDLE *, ACCESS_MASK,
OBJECT_ATTRIBUTES *,
IO_STATUS_BLOCK *, ULONG, ULONG);
typedef NTSTATUS(FAR PASCAL *pNTClose)(HANDLE);
#define FSCTL_TCP_BASE FILE_DEVICE_NETWORK
#define _TCP_CTL_CODE(Function, Method, Access) \
CTL_CODE(FSCTL_TCP_BASE, Function, Method, Access)
#define IOCTL_TCP_QUERY_INFORMATION_EX \
_TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef struct _InterfaceIndexTable
{
DWORD numIndexes;
DWORD numAllocated;
DWORD indexes[1];
} InterfaceIndexTable;
NTSTATUS
tdiGetMibForIfEntity(HANDLE tcpFile, TDIEntityID *ent,
IFEntrySafelySized *entry)
{
TCP_REQUEST_QUERY_INFORMATION_EX req = {{{0}}};
NTSTATUS status = 0;
DWORD returnSize;
#ifdef DEBUG
fprintf(stderr, "TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n", (int)tcpFile,
(int)ent->tei_instance);
#endif
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = 1;
req.ID.toi_entity = *ent;
status =
DeviceIoControl(tcpFile, IOCTL_TCP_QUERY_INFORMATION_EX, &req,
sizeof(req), entry, sizeof(*entry), &returnSize, NULL);
if(!status)
{
perror("IOCTL Failed\n");
return 0xc0000001;
}
fprintf(stderr,
"TdiGetMibForIfEntity() => {\n"
" if_index ....................... %lx\n"
" if_type ........................ %lx\n"
" if_mtu ......................... %ld\n"
" if_speed ....................... %lx\n"
" if_physaddrlen ................. %ld\n",
entry->ent.if_index, entry->ent.if_type, entry->ent.if_mtu,
entry->ent.if_speed, entry->ent.if_physaddrlen);
fprintf(stderr,
" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n"
" if_descr ....................... %s\n",
entry->ent.if_physaddr[0] & 0xff, entry->ent.if_physaddr[1] & 0xff,
entry->ent.if_physaddr[2] & 0xff, entry->ent.if_physaddr[3] & 0xff,
entry->ent.if_physaddr[4] & 0xff, entry->ent.if_physaddr[5] & 0xff,
entry->ent.if_descr);
fprintf(stderr, "} status %08lx\n", status);
return 0;
}
static NTSTATUS
tdiGetSetOfThings(HANDLE tcpFile, DWORD toiClass, DWORD toiType, DWORD toiId,
DWORD teiEntity, DWORD teiInstance, DWORD fixedPart,
DWORD entrySize, PVOID *tdiEntitySet, PDWORD numEntries)
{
TCP_REQUEST_QUERY_INFORMATION_EX req = {{{0}}};
PVOID entitySet = 0;
NTSTATUS status = 0;
DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES,
arraySize = entrySize * MAX_TDI_ENTITIES;
req.ID.toi_class = toiClass;
req.ID.toi_type = toiType;
req.ID.toi_id = toiId;
req.ID.toi_entity.tei_entity = teiEntity;
req.ID.toi_entity.tei_instance = teiInstance;
/* There's a subtle problem here...
* If an interface is added at this exact instant, (as if by a PCMCIA
* card insertion), the array will still not have enough entries after
* have allocated it after the first DeviceIoControl call.
*
* We'll get around this by repeating until the number of interfaces
* stabilizes.
*/
do
{
status =
DeviceIoControl(tcpFile, IOCTL_TCP_QUERY_INFORMATION_EX, &req,
sizeof(req), 0, 0, &allocationSizeForEntityArray, NULL);
if(!status)
return 0xc0000001;
arraySize = allocationSizeForEntityArray;
entitySet = HeapAlloc(GetProcessHeap(), 0, arraySize);
if(!entitySet)
{
status = ((NTSTATUS)0xC000009A);
return status;
}
status = DeviceIoControl(tcpFile, IOCTL_TCP_QUERY_INFORMATION_EX, &req,
sizeof(req), entitySet, arraySize,
&allocationSizeForEntityArray, NULL);
/* This is why we have the loop -- we might have added an adapter */
if(arraySize == allocationSizeForEntityArray)
break;
HeapFree(GetProcessHeap(), 0, entitySet);
entitySet = 0;
if(!status)
return 0xc0000001;
} while(TRUE); /* We break if the array we received was the size we
* expected. Therefore, we got here because it wasn't */
*numEntries = (arraySize - fixedPart) / entrySize;
*tdiEntitySet = entitySet;
return 0;
}
static NTSTATUS
tdiGetEntityIDSet(HANDLE tcpFile, TDIEntityID **entitySet,
PDWORD numEntities)
{
NTSTATUS status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_GENERIC,
INFO_TYPE_PROVIDER,
ENTITY_LIST_ID,
GENERIC_ENTITY,
0,
0,
sizeof(TDIEntityID),
(PVOID *)entitySet,
numEntities);
return status;
}
NTSTATUS
tdiGetIpAddrsForIpEntity(HANDLE tcpFile, TDIEntityID *ent, IPAddrEntry **addrs,
PDWORD numAddrs)
{
NTSTATUS status;
fprintf(stderr,"TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%lx)\n", tcpFile,
ent->tei_instance);
status = tdiGetSetOfThings(tcpFile, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER,
0x102, CL_NL_ENTITY,
ent->tei_instance, 0, sizeof(IPAddrEntry),
(PVOID *)addrs, numAddrs);
return status;
}
static VOID
tdiFreeThingSet(PVOID things)
{
HeapFree(GetProcessHeap(), 0, things);
}
NTSTATUS
openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess)
{
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
pRtlInitUString _RtlInitUnicodeString;
pNTOpenFile _NTOpenFile;
HANDLE ntdll;
ntdll = GetModuleHandle("ntdll.dll");
_RtlInitUnicodeString = (pRtlInitUString)GetProcAddress(ntdll, "RtlInitUnicodeString");
_NTOpenFile = (pNTOpenFile)GetProcAddress(ntdll, "NtOpenFile");
_RtlInitUnicodeString(&fileName, TcpFileName);
InitializeObjectAttributes(&objectAttributes, &fileName, OBJ_CASE_INSENSITIVE,
NULL, NULL);
status = _NTOpenFile(tcpFile, DesiredAccess | SYNCHRONIZE, &objectAttributes,
&ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
/* String does not need to be freed: it points to the constant
* string we provided */
if(!NT_SUCCESS(status))
*tcpFile = INVALID_HANDLE_VALUE;
return status;
}
VOID
closeTcpFile(HANDLE h)
{
pNTClose _NTClose;
HANDLE ntdll = GetModuleHandle("ntdll.dll");
_NTClose = (pNTClose)GetProcAddress(ntdll, "NtClose");
assert(h != INVALID_HANDLE_VALUE);
_NTClose(h);
}
BOOL
isLoopback(HANDLE tcpFile, TDIEntityID *loop_maybe)
{
IFEntrySafelySized entryInfo;
NTSTATUS status;
status = tdiGetMibForIfEntity(tcpFile, loop_maybe, &entryInfo);
return NT_SUCCESS(status)
&& (entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK);
}
BOOL
isIpEntity(HANDLE tcpFile, TDIEntityID *ent)
{
return (ent->tei_entity == CL_NL_ENTITY || ent->tei_entity == CO_NL_ENTITY);
}
NTSTATUS
getNthIpEntity(HANDLE tcpFile, DWORD index, TDIEntityID *ent)
{
DWORD numEntities = 0;
DWORD numRoutes = 0;
TDIEntityID *entitySet = 0;
NTSTATUS status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
int i;
if(!NT_SUCCESS(status))
return status;
for(i = 0; i < numEntities; i++)
{
if(isIpEntity(tcpFile, &entitySet[i]))
{
fprintf(stderr, "Entity %d is an IP Entity\n", i);
if(numRoutes == index)
break;
else
numRoutes++;
}
}
if(numRoutes == index && i < numEntities)
{
fprintf(stderr,"Index %lu is entity #%d - %04lx:%08lx\n", index, i,
entitySet[i].tei_entity, entitySet[i].tei_instance);
memcpy(ent, &entitySet[i], sizeof(*ent));
tdiFreeThingSet(entitySet);
return 0;
}
else
{
tdiFreeThingSet(entitySet);
return 0xc000001;
}
}
BOOL
isInterface(TDIEntityID *if_maybe)
{
return if_maybe->tei_entity == IF_ENTITY;
}
NTSTATUS
getInterfaceInfoSet(HANDLE tcpFile, IFInfo **infoSet, PDWORD numInterfaces)
{
DWORD numEntities;
TDIEntityID *entIDSet = NULL;
NTSTATUS status = tdiGetEntityIDSet(tcpFile, &entIDSet, &numEntities);
IFInfo *infoSetInt = 0;
int curInterf = 0, i;
if(!NT_SUCCESS(status))
{
fprintf(stderr, "getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status);
return status;
}
infoSetInt = HeapAlloc(GetProcessHeap(), 0, sizeof(IFInfo) * numEntities);
if(infoSetInt)
{
for(i = 0; i < numEntities; i++)
{
if(isInterface(&entIDSet[i]))
{
infoSetInt[curInterf].entity_id = entIDSet[i];
status = tdiGetMibForIfEntity(tcpFile, &entIDSet[i],
&infoSetInt[curInterf].if_info);
fprintf(stderr, "tdiGetMibForIfEntity: %08lx\n", status);
if(NT_SUCCESS(status))
{
DWORD numAddrs;
IPAddrEntry *addrs;
TDIEntityID ip_ent;
int j;
status = getNthIpEntity(tcpFile, curInterf, &ip_ent);
if(NT_SUCCESS(status))
status =
tdiGetIpAddrsForIpEntity(tcpFile, &ip_ent, &addrs, &numAddrs);
for(j = 0; NT_SUCCESS(status) && j < numAddrs; j++)
{
fprintf(stderr, "ADDR %d: index %ld (target %ld)\n", j, addrs[j].iae_index,
infoSetInt[curInterf].if_info.ent.if_index);
if(addrs[j].iae_index == infoSetInt[curInterf].if_info.ent.if_index)
{
memcpy(&infoSetInt[curInterf].ip_addr, &addrs[j],
sizeof(addrs[j]));
curInterf++;
break;
}
}
if(NT_SUCCESS(status))
tdiFreeThingSet(addrs);
}
}
}
tdiFreeThingSet(entIDSet);
if(NT_SUCCESS(status))
{
*infoSet = infoSetInt;
*numInterfaces = curInterf;
}
else
{
HeapFree(GetProcessHeap(), 0, infoSetInt);
}
return status;
}
else
{
tdiFreeThingSet(entIDSet);
return ((NTSTATUS)0xC000009A);
}
}
NTSTATUS
getInterfaceInfoByName(HANDLE tcpFile, char *name, IFInfo *info)
{
IFInfo *ifInfo;
DWORD numInterfaces;
int i;
NTSTATUS status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
if(NT_SUCCESS(status))
{
for(i = 0; i < numInterfaces; i++)
{
if(!strcmp((PCHAR)ifInfo[i].if_info.ent.if_descr, name))
{
memcpy(info, &ifInfo[i], sizeof(*info));
break;
}
}
HeapFree(GetProcessHeap(), 0, ifInfo);
return i < numInterfaces ? 0 : 0xc0000001;
}
return status;
}
NTSTATUS
getInterfaceInfoByIndex(HANDLE tcpFile, DWORD index, IFInfo *info)
{
IFInfo *ifInfo;
DWORD numInterfaces;
NTSTATUS status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
int i;
if(NT_SUCCESS(status))
{
for(i = 0; i < numInterfaces; i++)
{
if(ifInfo[i].if_info.ent.if_index == index)
{
memcpy(info, &ifInfo[i], sizeof(*info));
break;
}
}
HeapFree(GetProcessHeap(), 0, ifInfo);
return i < numInterfaces ? 0 : 0xc0000001;
}
return status;
}
NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile, char *name, DWORD index, IFInfo *ifInfo)
{
NTSTATUS status = name ? getInterfaceInfoByName(tcpFile, name, ifInfo)
: getInterfaceInfoByIndex(tcpFile, index, ifInfo);
if(!NT_SUCCESS(status))
{
fprintf(stderr,"getIPAddrEntryForIf returning %lx\n", status);
}
return status;
}
InterfaceIndexTable *
getInterfaceIndexTableInt(BOOL nonLoopbackOnly)
{
DWORD numInterfaces, curInterface = 0;
int i;
IFInfo *ifInfo;
InterfaceIndexTable *ret = 0;
HANDLE tcpFile;
NTSTATUS status = openTcpFile(&tcpFile, FILE_READ_DATA);
if(NT_SUCCESS(status))
{
status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
fprintf(stderr,"InterfaceInfoSet: %08lx, %04lx:%08lx\n", status,
ifInfo->entity_id.tei_entity, ifInfo->entity_id.tei_instance);
if(NT_SUCCESS(status))
{
ret = (InterfaceIndexTable *)calloc(
1, sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
if(ret)
{
ret->numAllocated = numInterfaces;
fprintf(stderr,"NumInterfaces = %ld\n", numInterfaces);
for(i = 0; i < numInterfaces; i++)
{
fprintf(stderr,"Examining interface %d\n", i);
if(!nonLoopbackOnly || !isLoopback(tcpFile, &ifInfo[i].entity_id))
{
fprintf(stderr,"Interface %d matches (%ld)\n", i, curInterface);
ret->indexes[curInterface++] = ifInfo[i].if_info.ent.if_index;
}
}
ret->numIndexes = curInterface;
}
tdiFreeThingSet(ifInfo);
}
closeTcpFile(tcpFile);
}
return ret;
}
InterfaceIndexTable *
getInterfaceIndexTable(void)
{
return getInterfaceIndexTableInt(FALSE);
}
#endif
/*
* We need this in the Microsoft C/C++ port, as we're not using Pthreads, and jeff insists
* on naming the threads at runtime.
* Apparently throwing exception 1080890248 is only visible when running under a machine
* code monitor.
*
* -despair86 30/07/18
*/
#ifdef _MSC_VER
#include <windows.h>
#define EXCEPTION_SET_THREAD_NAME ((DWORD)0x406D1388)
typedef struct _THREADNAME_INFO
{
DWORD dwType; /* must be 0x1000 */
LPCSTR szName; /* pointer to name (in user addr space) */
DWORD dwThreadID; /* thread ID (-1=caller thread) */
DWORD dwFlags; /* reserved for future use, must be zero */
} THREADNAME_INFO;
void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
{
THREADNAME_INFO info;
DWORD infosize;
info.dwType = 0x1000;
info.szName = szThreadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
infosize = sizeof(info) / sizeof(DWORD);
__try
{
RaiseException(EXCEPTION_SET_THREAD_NAME, 0, infosize, (DWORD *)&info);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
#endif

111
llarp/win32_intrnl.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef WIN32_INTRNL_H
#define WIN32_INTRNL_H
/* if yer using Microsoft C++, then downlevel platforms are irrelevant to you */
#if defined(__MINGW32__) && !defined(_WIN64)
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
#include <tdiinfo.h>
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned int uint;
/* forward declare, each module has their own idea of what this is */
typedef struct _InterfaceIndexTable InterfaceIndexTable;
typedef struct IFEntry
{
ulong if_index;
ulong if_type;
ulong if_mtu;
ulong if_speed;
ulong if_physaddrlen;
uchar if_physaddr[8];
ulong if_adminstatus;
ulong if_operstatus;
ulong if_lastchange;
ulong if_inoctets;
ulong if_inucastpkts;
ulong if_innucastpkts;
ulong if_indiscards;
ulong if_inerrors;
ulong if_inunknownprotos;
ulong if_outoctets;
ulong if_outucastpkts;
ulong if_outnucastpkts;
ulong if_outdiscards;
ulong if_outerrors;
ulong if_outqlen;
ulong if_descrlen;
uchar if_descr[1];
} IFEntry;
typedef struct IPAddrEntry
{
ulong iae_addr;
ulong iae_index;
ulong iae_mask;
ulong iae_bcastaddr;
ulong iae_reasmsize;
ushort iae_context;
ushort iae_pad;
} IPAddrEntry;
typedef union _IFEntrySafelySized {
CHAR MaxSize[sizeof(DWORD) + sizeof(IFEntry) + 128 + 1];
IFEntry ent;
} IFEntrySafelySized;
#ifndef IFENT_SOFTWARE_LOOPBACK
#define IFENT_SOFTWARE_LOOPBACK 24 /* This is an SNMP constant from rfc1213 */
#endif /*IFENT_SOFTWARE_LOOPBACK*/
/* Encapsulates information about an interface */
typedef struct _IFInfo
{
TDIEntityID entity_id;
IFEntrySafelySized if_info;
IPAddrEntry ip_addr;
} IFInfo;
/* functions */
NTSTATUS
openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess);
VOID
closeTcpFile(HANDLE h);
BOOL
isLoopback(HANDLE tcpFile, TDIEntityID* loop_maybe);
BOOL
isIpEntity(HANDLE tcpFile, TDIEntityID* ent);
NTSTATUS
getNthIpEntity(HANDLE tcpFile, DWORD index, TDIEntityID* ent);
BOOL
isInterface(TDIEntityID* if_maybe);
NTSTATUS
getInterfaceInfoSet(HANDLE tcpFile, IFInfo** infoSet, PDWORD numInterfaces);
NTSTATUS
getInterfaceInfoByName(HANDLE tcpFile, char* name, IFInfo* info);
NTSTATUS
getInterfaceInfoByIndex(HANDLE tcpFile, DWORD index, IFInfo* info);
NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile, char* name, DWORD index, IFInfo* ifInfo);
InterfaceIndexTable*
getInterfaceIndexTableInt(BOOL nonLoopbackOnly);
InterfaceIndexTable*
getInterfaceIndexTable(void);
#endif
#endif

View File

@ -3,31 +3,7 @@
Lokinet is a private, decentralized and Sybil resistant overlay network for the internet, it uses a new routing protocol called LLARP (Low latency anonymous routing protocol)
You can learn more about the high level design of LLARP [here](doc/high-level.txt)
And you can read the LLARP protocol specification [here](doc/proto_v0.txt)
## Building
$ sudo apt install build-essential libtool autoconf cmake git
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make
## Running
$ ./lokinet
### Development
Please note development builds are likely to be unstable
Build requirements:
* CMake
* ninja
* libsodium >= 1.0.14
* c++ 11 capable C++ compiler
Building a debug build:
$ make
To build lokinet see the [lokinet-builder](https://github.com/loki-project/lokinet-builder) repository.

View File

@ -22,6 +22,7 @@ struct HiddenServiceTest : public ::testing::Test
{
ident.RegenerateKeys(Crypto());
ident.pub.vanity.Randomize();
ident.pub.UpdateAddr();
}
};
@ -40,4 +41,12 @@ TEST_F(HiddenServiceTest, TestGenerateIntroSet)
}
ASSERT_TRUE(ident.SignIntroSet(I, Crypto()));
ASSERT_TRUE(I.VerifySignature(Crypto()));
};
};
TEST_F(HiddenServiceTest, TestAddressToFromString)
{
auto str = ident.pub.Addr().ToString();
llarp::service::Address addr;
ASSERT_TRUE(addr.FromString(str));
ASSERT_TRUE(addr == ident.pub.Addr());
}

View File

@ -30,18 +30,21 @@
#ifndef PBL_CPP_FILESYSTEM_H
#define PBL_CPP_FILESYSTEM_H
#if _MSC_VER >= 1910
#define CPP17
#define CPP11
#define CPP14
#endif
#include "version.h"
// linux gcc 7.2 has CPP17 but doesn't have filesystem.h
#if defined(CPP17) && !defined(__OpenBSD__) && __has_include(<filesystem>)
#if defined(__MINGW32__)
// mingw32 needs experimental
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
#if defined(__MINGW32__) || defined(_MSC_VER)
// win32 needs experimental
#include <experimental/filesystem>
#else
#include <filesystem>
#endif
#else
// OpenBSD needs this
// MacOS llvm 3.8 needs this
@ -61,6 +64,6 @@
#include "fs/remove.h"
#include "fs/rename.h"
#include "fs/tempdir.h"
#endif // if not cpp17 and not openbsd
#endif // if not cpp17 and not openbsd
#endif // PBL_CPP_FILESYSTEM_H

View File

@ -64,7 +64,8 @@ namespace
{
t = file_type::fifo;
}
else if ( S_ISLNK(m) )
#ifndef _WIN32 // these only work on cygnus or msys2!
else if(S_ISLNK(m))
{
t = file_type::symlink;
}
@ -72,9 +73,8 @@ namespace
{
t = file_type::socket;
}
#endif
return ::cpp17::filesystem::file_status(t, p);
}
}
@ -156,13 +156,15 @@ file_status symlink_status(const path& path_)
if ( !path_.empty() )
{
struct stat st;
if ( ::lstat(path_.c_str(), &st) == 0 )
#ifndef _WIN32
if(::lstat(path_.c_str(), &st) == 0)
#else
if(::stat(path_.c_str(), &st) == 0)
#endif
{
return from_mode_t(st.st_mode);
}
}
return file_status();
}

View File

@ -30,6 +30,7 @@
#if defined Windows
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#else
#include <arpa/inet.h>
#include <netinet/in.h>