Ryan Tharp 6 years ago
commit 4b3b09736b

@ -13,22 +13,14 @@ endmacro(add_cxxflags)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if (MSVC)
CHECK_CXX_COMPILER_FLAG("/std:c++17" COMPILER_SUPPORTS_CXX17)
else()
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17) CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
endif()
option(HAVE_CXX17_FILESYSTEM "Disable if your C++ compiler and runtime library lacks std::[experimental::]filesystem" ON) option(HAVE_CXX17_FILESYSTEM "Disable if your C++ compiler and runtime library lacks std::[experimental::]filesystem" ON)
if(COMPILER_SUPPORTS_CXX11 AND NOT HAVE_CXX17_FILESYSTEM) if(COMPILER_SUPPORTS_CXX11 AND NOT HAVE_CXX17_FILESYSTEM)
add_cxxflags("-std=c++11") add_cxxflags("-std=c++11")
elseif(COMPILER_SUPPORTS_CXX17 AND HAVE_CXX17_FILESYSTEM) elseif(COMPILER_SUPPORTS_CXX17 AND HAVE_CXX17_FILESYSTEM)
if (MSVC)
add_cxxflags("/std:c++17")
else()
add_cxxflags("-std=c++17") add_cxxflags("-std=c++17")
endif()
add_definitions(-DUSE_CXX17_FILESYSTEM) add_definitions(-DUSE_CXX17_FILESYSTEM)
else() else()
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 or C++17 support. Please use a different C++ compiler.") message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 or C++17 support. Please use a different C++ compiler.")
@ -36,30 +28,26 @@ endif()
add_cxxflags("-fpermissive") add_cxxflags("-fpermissive")
if (WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE)
if (USING_CLANG)
add_cxxflags("-Wno-unused-command-line-argument -Wno-c++11-narrowing")
add_cflags("-Wno-unused-command-line-argument")
# because clang is insane enough to inline whole sections of the C++ library!
# May have been fixed in llvm-7.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-multiple-definition --rtlib=libgcc")
endif(USING_CLANG)
endif()
if(DEBIAN) if(DEBIAN)
add_definitions(-DDEBIAN) add_definitions(-DDEBIAN)
endif() endif()
if(ANDROID) if(ANDROID)
set(THREAD_LIB "-pthread") set(THREAD_LIB "-pthread")
# finally removed pthread dependency for MSC++
elseif(MSVC)
set(THREAD_LIB)
else() else()
set(THREAD_LIB pthread) set(THREAD_LIB pthread)
endif() endif()
if(MSVC)
option (BUILD_AVX2 "Enable AVX2 FPU vector instructions." OFF)
if (BUILD_AVX2)
add_cflags("/arch:AVX2")
add_cxxflags("/arch:AVX2")
else()
add_cflags("/arch:SSE2")
add_cxxflags("/arch:SSE2")
endif(BUILD_AVX2)
endif()
if(STATIC_LINK) if(STATIC_LINK)
add_cflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive") add_cflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
add_cxxflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive") add_cxxflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
@ -75,18 +63,11 @@ else()
set(WITH_STATIC ON) set(WITH_STATIC ON)
endif() endif()
if (NOT MSVC)
add_cflags("-Wall") add_cflags("-Wall")
add_cxxflags("-Wall") add_cxxflags("-Wall")
endif()
if (MSVC) set(OPTIMIZE_FLAGS "-O3")
set(OPTIMIZE_FLAGS "-Od") set(DEBUG_FLAGS "-O0 -g3")
set(DEBUG_FLAGS "-ZI")
else()
set(OPTIMIZE_FLAGS "-O0")
set(DEBUG_FLAGS "-g")
endif()
if(ASAN) if(ASAN)
set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer") set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
@ -112,19 +93,15 @@ if(SHADOW)
include_directories(${SHADOW_ROOT}/include) include_directories(${SHADOW_ROOT}/include)
endif() endif()
if (MSVC)
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]") if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
set(OPTIMIZE_FLAGS "")
add_cflags("${DEBUG_FLAGS}") add_cflags("${DEBUG_FLAGS}")
add_cxxflags("${DEBUG_FLAGS}") add_cxxflags("${DEBUG_FLAGS}")
endif() endif()
add_cflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
add_cxxflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
if(SHADOW) if(SHADOW)
add_cflags("-fPIC") add_cflags("-fPIC")
add_cxxflags("-fPIC") add_cxxflags("-fPIC")
@ -156,6 +133,11 @@ else()
) )
endif() endif()
# HeapAlloc(2) on Windows was significantly revamped in 2009
# but the old algorithm isn't too bad either
# this is _the_ system allocator on BSD UNIX
# openbsd replaced it with a secure/randomised malloc not too
# long ago
if(JEMALLOC) if(JEMALLOC)
set(MALLOC_LIB jemalloc) set(MALLOC_LIB jemalloc)
endif() endif()
@ -210,16 +192,12 @@ set(LIBTUNTAP_SRC_BASE
${LIBTUNTAP_IMPL}) ${LIBTUNTAP_IMPL})
if (UNIX) if (UNIX)
set(LIBTUNTAP_SRC set(LIBTUNTAP_SRC
${TT_ROOT}/tuntap-unix.c ${TT_ROOT}/tuntap-unix.c
${LIBTUNTAP_SRC_BASE}) ${LIBTUNTAP_SRC_BASE})
endif() else()
set(LIBTUNTAP_SRC ${LIBTUNTAP_SRC_BASE})
#if(BACKPORT) endif(UNIX)
#else()
#set(CPP_BACKPORT_SRC "")
#endif()
set(CPP_BACKPORT_SRC set(CPP_BACKPORT_SRC
vendor/cppbackport-master/lib/fs/rename.cpp vendor/cppbackport-master/lib/fs/rename.cpp
vendor/cppbackport-master/lib/fs/filestatus.cpp vendor/cppbackport-master/lib/fs/filestatus.cpp
@ -248,7 +226,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(ISOLATE_PROC_SRC llarp/linux/netns.cpp) set(ISOLATE_PROC_SRC llarp/linux/netns.cpp)
endif() endif()
set(LIB_PLATFORM_SRC set(LIB_PLATFORM_SRC
# for outpug # for outpug
llarp/logger.cpp llarp/logger.cpp
@ -270,11 +247,9 @@ set(LIB_PLATFORM_SRC
${ISOLATE_PROC_SRC} ${ISOLATE_PROC_SRC}
# tun # tun
${LIBTUNTAP_SRC} ${LIBTUNTAP_SRC}
# win32 inline procs # win32 inline code
llarp/win32_inet.c llarp/win32_inet.c
llarp/win32_intrnl.c llarp/win32_intrnl.c
contrib/msc/getopt.c
contrib/msc/getopt1.c
) )
set(NTRU_AVX_SRC set(NTRU_AVX_SRC
@ -332,7 +307,6 @@ set(UTP_SRC
libutp/utp_hash.cpp libutp/utp_hash.cpp
) )
if(WIN32) if(WIN32)
set(UTP_SRC ${UTP_SRC} libutp/libutp_inet_ntop.cpp) set(UTP_SRC ${UTP_SRC} libutp/libutp_inet_ntop.cpp)
endif() endif()
@ -456,10 +430,6 @@ include_directories(vendor/cppbackport-master/lib)
include_directories(/usr/local/include) include_directories(/usr/local/include)
include_directories(${sodium_INCLUDE_DIR}) include_directories(${sodium_INCLUDE_DIR})
if (MSVC)
include_directories(contrib/msc/include)
endif()
set(RC_EXE rcutil) set(RC_EXE rcutil)
set(DNS_EXE dns) set(DNS_EXE dns)
@ -469,22 +439,14 @@ add_shadow_plugin(shadow-plugin-${SHARED_LIB} ${EXE_SRC} ${LIB_SRC} ${LIB_PLATFO
target_link_libraries(shadow-plugin-${SHARED_LIB} ${LIBS}) target_link_libraries(shadow-plugin-${SHARED_LIB} ${LIBS})
install(TARGETS shadow-plugin-${SHARED_LIB} DESTINATION plugins) install(TARGETS shadow-plugin-${SHARED_LIB} DESTINATION plugins)
else() else()
add_executable(${RC_EXE} ${RC_SRC}) add_executable(${RC_EXE} ${RC_SRC})
add_executable(${EXE} ${EXE_SRC}) add_executable(${EXE} ${EXE_SRC})
add_executable(${CLIENT_EXE} ${CLIENT_SRC}) add_executable(${CLIENT_EXE} ${CLIENT_SRC})
add_executable(${DNS_EXE} ${DNS_SRC}) add_executable(${DNS_EXE} ${DNS_SRC})
add_subdirectory(${GTEST_DIR}) add_subdirectory(${GTEST_DIR})
include_directories(${GTEST_DIR}/include ${GTEST_DIR}) include_directories(${GTEST_DIR}/include ${GTEST_DIR})
add_executable(${TEST_EXE} ${TEST_SRC}) add_executable(${TEST_EXE} ${TEST_SRC})
if (MSVC)
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ws2_32 iphlpapi)
elseif (MINGW)
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} stdc++fs iphlpapi ws2_32)
else()
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB})
endif(MSVC)
if(WITH_STATIC) if(WITH_STATIC)
add_library(${STATIC_LIB} STATIC ${LIB_SRC}) add_library(${STATIC_LIB} STATIC ${LIB_SRC})
if(NOT HAVE_CXX17_FILESYSTEM) if(NOT HAVE_CXX17_FILESYSTEM)
@ -505,34 +467,28 @@ if(WITH_STATIC)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB}) target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB}) target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB}) target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
if (MINGW) target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi) if (WIN32)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
elseif(MSVC)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi) target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi) target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi) target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
endif(MINGW) target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
endif(WIN32)
else() else()
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB}) target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB}) target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB}) target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
if (MINGW) target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${PLATFORM_LIB})
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi) if (WIN32)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
elseif(MSVC)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi) target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi) target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi) target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
endif(MINGW) target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
endif(WIN32)
endif(NOT HAVE_CXX17_FILESYSTEM) endif(NOT HAVE_CXX17_FILESYSTEM)
if (MINGW) if (WIN32)
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB} ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB} ws2_32 iphlpapi) target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB} ws2_32 iphlpapi)
endif(MINGW) endif(WIN32)
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB}) target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB})
endif(NOT WITH_SHARED) endif(NOT WITH_SHARED)
endif(WITH_STATIC) endif(WITH_STATIC)
@ -546,11 +502,9 @@ if(WITH_STATIC)
set(LIB_SRC ${LIB_SRC} ${CPP_BACKPORT_SRC}) set(LIB_SRC ${LIB_SRC} ${CPP_BACKPORT_SRC})
endif(HAVE_CXX17_FILESYSTEM) endif(HAVE_CXX17_FILESYSTEM)
add_library(${SHARED_LIB} SHARED ${LIB_SRC} ${LIB_PLATFORM_SRC}) add_library(${SHARED_LIB} SHARED ${LIB_SRC} ${LIB_PLATFORM_SRC})
if (MINGW) if (WIN32)
set(${LIBS} ${LIBS} ws2_32 stdc++fs iphlpapi)
elseif(MSVC)
set(${LIBS} ${LIBS} ws2_32 iphlpapi) set(${LIBS} ${LIBS} ws2_32 iphlpapi)
endif(MINGW) endif(WIN32)
target_link_libraries(${SHARED_LIB} ${LIBS} ${THREAD_LIB}) target_link_libraries(${SHARED_LIB} ${LIBS} ${THREAD_LIB})
target_link_libraries(${EXE} ${SHARED_LIB}) target_link_libraries(${EXE} ${SHARED_LIB})
target_link_libraries(${RC_EXE} ${SHARED_LIB}) target_link_libraries(${RC_EXE} ${SHARED_LIB})

File diff suppressed because it is too large Load Diff

@ -1,190 +0,0 @@
#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 */

@ -1,157 +0,0 @@
#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 */

@ -4,7 +4,9 @@
#include <getopt.h> #include <getopt.h>
#include <string> #include <string>
#include <iostream> #include <iostream>
#ifndef _MSC_VER
#include <libgen.h> #include <libgen.h>
#endif
#include "fs.hpp" #include "fs.hpp"
#include "config.hpp" // for ensure_config #include "config.hpp" // for ensure_config
@ -29,6 +31,25 @@ printHelp(const char *argv0, int code = 1)
return code; return code;
} }
#ifdef _WIN32
int
startWinsock()
{
WSADATA wsockd;
int err;
// We used to defer starting winsock until
// we got to the iocp event loop
// but getaddrinfo(3) requires that winsock be in core already
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
if(err)
{
perror("Failed to start Windows Sockets");
return err;
}
return 0;
}
#endif
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -39,6 +60,11 @@ main(int argc, char *argv[])
multiThreaded = false; multiThreaded = false;
} }
#ifdef _WIN32
if(startWinsock())
return -1;
#endif
int opt = 0; int opt = 0;
bool genconfigOnly = false; bool genconfigOnly = false;
bool asRouter = true; bool asRouter = true;
@ -106,7 +132,9 @@ main(int argc, char *argv[])
fs::path fpath = basepath / "lokinet.ini"; fs::path fpath = basepath / "lokinet.ini";
std::error_code ec; std::error_code ec;
if(!fs::create_directories(basepath, ec)) // These paths are guaranteed to exist - $APPDATA or $HOME
// so only create .lokinet/*
if(!fs::create_directory(basepath, ec))
{ {
if(ec) if(ec)
{ {
@ -136,6 +164,9 @@ main(int argc, char *argv[])
code = llarp_main_run(ctx); code = llarp_main_run(ctx);
llarp_main_free(ctx); llarp_main_free(ctx);
} }
#ifdef _WIN32
::WSACleanup();
#endif
exit(code); exit(code);
return code; return code;
} }

@ -7,7 +7,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
#ifndef _WIN32
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <llarp/net.hpp> // for llarp::Addr #include <llarp/net.hpp> // for llarp::Addr

@ -5,13 +5,13 @@
#include <llarp/net.hpp> #include <llarp/net.hpp>
#ifndef _WIN32 #ifndef _WIN32
// unix, linux
#include <sys/types.h> // FreeBSD needs this for uchar for ip.h #include <sys/types.h> // FreeBSD needs this for uchar for ip.h
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#else #else
// windows nt
#include <winsock2.h> #include <winsock2.h>
// Apparently this does not seem to be located _anywhere_ in the windows sdk???
// -despair86
typedef struct ip_hdr typedef struct ip_hdr
{ {
unsigned char unsigned char
@ -46,16 +46,7 @@ typedef struct ip_hdr
#include <memory> #include <memory>
#if !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) \ // anything not win32
&& !defined(__FreeBSD__)
#define iphdr ip
#define saddr ip_src.s_addr
#define daddr ip_dst.s_addr
#define ip_version ip_v
#define check ip_sum
#define ihl ip_hl
#endif
struct ip_header struct ip_header
{ {
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN

@ -10,9 +10,16 @@
#include <stdlib.h> // for itoa #include <stdlib.h> // for itoa
// for addrinfo // for addrinfo
#ifndef _WIN32
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#define inet_aton(x, y) inet_pton(AF_INET, x, y)
#endif
bool bool
operator==(const sockaddr& a, const sockaddr& b); operator==(const sockaddr& a, const sockaddr& b);
@ -466,7 +473,7 @@ namespace llarp
isOneSevenPrivate(uint32_t byte) isOneSevenPrivate(uint32_t byte)
{ {
uint8_t byte1 = byte >> 24 & 0xff; uint8_t byte1 = byte >> 24 & 0xff;
uint8_t byte2 = (0x00ff0000 & byte >> 16); uint8_t byte2 = (0x00ff0000 & byte) >> 16;
return byte1 == 172 && (byte2 >= 16 || byte2 <= 31); return byte1 == 172 && (byte2 >= 16 || byte2 <= 31);
} }
@ -474,7 +481,7 @@ namespace llarp
isOneNinePrivate(uint32_t byte) isOneNinePrivate(uint32_t byte)
{ {
uint8_t byte1 = byte >> 24 & 0xff; uint8_t byte1 = byte >> 24 & 0xff;
uint8_t byte2 = (0x00ff0000 & byte >> 16); uint8_t byte2 = (0x00ff0000 & byte) >> 16;
return byte1 == 192 && byte2 == 168; return byte1 == 192 && byte2 == 168;
} }

@ -136,6 +136,11 @@ namespace llarp
llarp_time_t lifetime = DEFAULT_PATH_LIFETIME; llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
llarp_proto_version_t version; llarp_proto_version_t version;
bool IsEndpoint(const RouterID & us) const
{
return info.upstream == us;
}
llarp_time_t llarp_time_t
ExpireTime() const; ExpireTime() const;
llarp::routing::InboundMessageParser m_MessageParser; llarp::routing::InboundMessageParser m_MessageParser;

@ -113,6 +113,12 @@ namespace llarp
Path* Path*
GetPathByID(const PathID_t& id) const; GetPathByID(const PathID_t& id) const;
bool
GetCurrentIntroductionsWithFilter(
std::set< llarp::service::Introduction >& intros,
std::function< bool(const llarp::service::Introduction&) > filter)
const;
bool bool
GetCurrentIntroductions( GetCurrentIntroductions(
std::set< llarp::service::Introduction >& intros) const; std::set< llarp::service::Introduction >& intros) const;

@ -10,6 +10,7 @@
#include <llarp/service/tag.hpp> #include <llarp/service/tag.hpp>
#include <vector> #include <vector>
#include <algorithm>
namespace llarp namespace llarp
{ {
@ -60,6 +61,7 @@ namespace llarp
IntroSet& IntroSet&
operator=(const IntroSet& other) operator=(const IntroSet& other)
{ {
I.clear();
A = other.A; A = other.A;
I = other.I; I = other.I;
K = other.K; K = other.K;

@ -31,6 +31,9 @@ namespace llarp
llarp_tun_io * llarp_tun_io *
getRange(); getRange();
bool
AddDefaultEndpoint(const std::string & ifaddr, const std::string & ifname);
/// hint at possible path usage and trigger building early /// hint at possible path usage and trigger building early
bool bool
Prefetch(const llarp::service::Address &addr); Prefetch(const llarp::service::Address &addr);

@ -187,6 +187,7 @@ namespace llarp
llarp::SharedSecret sharedKey; llarp::SharedSecret sharedKey;
ServiceInfo remoteIdent; ServiceInfo remoteIdent;
Introduction remoteIntro; Introduction remoteIntro;
ConvoTag currentConvoTag;
PathSet* m_PathSet; PathSet* m_PathSet;
IDataHandler* m_DataHandler; IDataHandler* m_DataHandler;
Endpoint* m_Endpoint; Endpoint* m_Endpoint;
@ -351,7 +352,7 @@ namespace llarp
protected: protected:
void void
RegenAndPublishIntroSet(llarp_time_t now); RegenAndPublishIntroSet(llarp_time_t now, bool forceRebuild = false);
IServiceLookup* IServiceLookup*
GenerateLookupByTag(const Tag& tag); GenerateLookupByTag(const Tag& tag);

@ -32,7 +32,7 @@ namespace llarp
/// determine if this request has timed out /// determine if this request has timed out
bool bool
IsTimedOut(llarp_time_t now, llarp_time_t timeout = 5000) const IsTimedOut(llarp_time_t now, llarp_time_t timeout = 10000) const
{ {
if(now <= m_created) if(now <= m_created)
return false; return false;

@ -92,7 +92,7 @@ typedef struct in6_addr t_tun_in6_addr;
* Windows helpers * Windows helpers
*/ */
#if defined Windows #if defined Windows
#define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z)); //#define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z));
#define strdup(x) _strdup(x) #define strdup(x) _strdup(x)
#endif #endif
@ -119,10 +119,12 @@ typedef struct in6_addr t_tun_in6_addr;
/* Handle Windows symbols export */ /* Handle Windows symbols export */
#if defined Windows #if defined Windows
#if defined(tuntap_EXPORTS) /* CMake generated goo */ #if defined(tuntap_EXPORTS) && defined(_USRDLL) /* CMake generated goo */
#define TUNTAP_EXPORT __declspec(dllexport) #define TUNTAP_EXPORT __declspec(dllexport)
#else #elif defined(tuntap_EXPORTS)
#define TUNTAP_EXPORT __declspec(dllimport) #define TUNTAP_EXPORT __declspec(dllimport)
#else
#define TUNTAP_EXPORT extern
#endif #endif
#else /* Unix */ #else /* Unix */
#define TUNTAP_EXPORT extern #define TUNTAP_EXPORT extern

@ -30,19 +30,21 @@
// we already have our own definition of these // we already have our own definition of these
// -despair // -despair
namespace {
extern "C" { extern "C" {
const char* inet_ntop(int af, const void *src, char *dst, size_t size); const char* inet_ntop(int af, const void *src, char *dst, size_t size);
int inet_pton(int af, const char *src, void *dst); int inet_pton(int af, const char *src, void *dst);
} }
}
//###################################################################### //######################################################################
const char *libutp::inet_ntop(int af, const void *src, char *dest, size_t length) const char *libutp::inet_ntop(int af, const void *src, char *dest, size_t length)
{ {
return inet_ntop(af, src, dest, length); return ::inet_ntop(af, src, dest, length);
} }
//###################################################################### //######################################################################
int libutp::inet_pton(int af, const char* src, void* dest) int libutp::inet_pton(int af, const char* src, void* dest)
{ {
return inet_pton(af, src, dest); return ::inet_pton(af, src, dest);
} }

@ -4,7 +4,7 @@
bool bool
bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz) bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz)
{ {
if(!llarp_buffer_writef(buff, "%ld:", sz)) if(!llarp_buffer_writef(buff, "%zu:", sz))
return false; return false;
return llarp_buffer_write(buff, data, sz); return llarp_buffer_write(buff, data, sz);
} }
@ -12,7 +12,7 @@ bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz)
bool bool
bencode_write_uint64(llarp_buffer_t* buff, uint64_t i) bencode_write_uint64(llarp_buffer_t* buff, uint64_t i)
{ {
return llarp_buffer_writef(buff, "i%lu", i) return llarp_buffer_writef(buff, "i%llu", i)
&& llarp_buffer_write(buff, "e", 1); && llarp_buffer_write(buff, "e", 1);
} }
@ -59,7 +59,7 @@ bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result)
buffer->cur++; buffer->cur++;
numbuf[len] = 0; numbuf[len] = 0;
*result = strtoul(numbuf, nullptr, 10); *result = strtoull(numbuf, nullptr, 10);
return true; return true;
} }

@ -65,7 +65,11 @@ llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
if(basedir) if(basedir)
{ {
basepath = basedir; basepath = basedir;
#ifndef _WIN32
basepath += "/"; basepath += "/";
#else
basepath += "\\";
#endif
} }
// abort if client.ini already exists // abort if client.ini already exists
@ -94,7 +98,7 @@ llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
llarp_generic_ensure_config(f, basepath); llarp_generic_ensure_config(f, basepath);
if(asRouter) if(asRouter)
{ {
llarp_ensure_router_config(f); llarp_ensure_router_config(f, basepath);
} }
else else
{ {
@ -164,24 +168,41 @@ llarp_generic_ensure_config(std::ofstream &f, std::string basepath)
} }
void void
llarp_ensure_router_config(std::ofstream &f) llarp_ensure_router_config(std::ofstream &f, std::string basepath)
{ {
f << "# ROUTERS ONLY: router settings block" << std::endl; f << "# ROUTERS ONLY: router settings block" << std::endl;
f << "# router settings block" << std::endl;
f << "[router]" << std::endl; f << "[router]" << std::endl;
f << "# uncomment these to manually set public address and port" << std::endl; f << "# uncomment these to manually set public address and port"
<< std::endl;
f << "# this is required on providers like AWS because of their firewall " f << "# this is required on providers like AWS because of their firewall "
"rules" "rules"
<< std::endl; << std::endl;
f << "# public-address=your.ip.goes.here" << std::endl; f << "# public-address=your.ip.goes.here" << std::endl;
f << "# public-port=1090" << std::endl; f << "# public-port=1090" << std::endl;
f << std::endl; f << std::endl;
f << "# number of crypto worker threads " << std::endl;
f << "threads=4" << std::endl;
f << "# path to store signed RC" << std::endl;
f << "contact-file=" << basepath << "self.signed" << std::endl;
f << "# path to store transport private key" << std::endl;
f << "transport-privkey=" << basepath << "transport.private" << std::endl;
f << "# path to store identity signing key" << std::endl;
f << "ident-privkey=" << basepath << "identity.private" << std::endl;
f << "# encryption key for onion routing" << std::endl;
f << "encryption-privkey=" << basepath << "encryption.private" << std::endl;
f << std::endl;
f << "# uncomment following line to set router nickname to 'lokinet'"
<< std::endl;
f << "# nickname=lokinet" << std::endl;
f << std::endl << std::endl;
f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic" f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic"
<< std::endl; << std::endl;
f << "[bind]" << std::endl; f << "[bind]" << std::endl;
// get ifname
std::string ifname; std::string ifname;
if(llarp::GetBestNetIF(ifname, AF_INET)) if(llarp::GetBestNetIF(ifname, AF_INET))
f << ifname << "=1090" << std::endl; f << ifname << "=1090" << std::endl;
else else
@ -195,17 +216,32 @@ bool
llarp_ensure_client_config(std::ofstream &f, std::string basepath) llarp_ensure_client_config(std::ofstream &f, std::string basepath)
{ {
f << "# ROUTERS ONLY: router settings block" << std::endl; f << "# ROUTERS ONLY: router settings block" << std::endl;
f << "# router settings block" << std::endl;
f << "[router]" << std::endl; f << "[router]" << std::endl;
f << "# uncomment these to manually set public address and port" << std::endl; f << "# uncomment these to manually set public address and port"
<< std::endl;
f << "# this is required on providers like AWS because of their firewall " f << "# this is required on providers like AWS because of their firewall "
"rules" "rules"
<< std::endl; << std::endl;
f << "# public-address=your.ip.goes.here" << std::endl; f << "#public-address=your.ip.goes.here" << std::endl;
f << "# public-port=1090" << std::endl; f << "#public-port=1090" << std::endl;
f << std::endl; f << std::endl;
f << "# number of crypto worker threads " << std::endl;
f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic" f << "#threads=4" << std::endl;
f << "# path to store signed RC" << std::endl;
f << "#contact-file=" << basepath << "self.signed" << std::endl;
f << "# path to store transport private key" << std::endl;
f << "#transport-privkey=" << basepath << "transport.private" << std::endl;
f << "# path to store identity signing key" << std::endl;
f << "#ident-privkey=" << basepath << "identity.private" << std::endl;
f << "# encryption key for onion routing" << std::endl;
f << "#encryption-privkey=" << basepath << "encryption.private" << std::endl;
f << std::endl;
f << "# uncomment following line to set router nickname to 'lokinet'"
<< std::endl; << std::endl;
f << "#nickname=lokinet" << std::endl;
f << std::endl << std::endl;
f << "[bind]" << std::endl; f << "[bind]" << std::endl;
std::string ifname; std::string ifname;
@ -220,6 +256,13 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
f << "client=" << basepath << "client.ini" << std::endl; f << "client=" << basepath << "client.ini" << std::endl;
f << std::endl; f << std::endl;
f << "# network settings " << std::endl;
f << "[network]" << std::endl;
#ifndef __linux__
f << "# ";
#endif
/*
// done with fname.ini // done with fname.ini
// start client.ini // start client.ini
// write fname ini // write fname ini
@ -231,6 +274,7 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
} }
clientini_f << "[client-hidden-service-name]" << std::endl; clientini_f << "[client-hidden-service-name]" << std::endl;
clientini_f << "keyfile=client-keyfile.private" << std::endl; clientini_f << "keyfile=client-keyfile.private" << std::endl;
*/
// pick ip // pick ip
struct privatesInUse ifsInUse = llarp_getPrivateIfs(); struct privatesInUse ifsInUse = llarp_getPrivateIfs();
@ -255,7 +299,7 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
} }
llarp::LogDebug("Detected " + ip llarp::LogDebug("Detected " + ip
+ " is available for use, configuring as such"); + " is available for use, configuring as such");
clientini_f << "ifaddr=" << ip << std::endl; //clientini_f << "ifaddr=" << ip << std::endl;
// pick interface name // pick interface name
uint8_t num = 0; uint8_t num = 0;
while(num < 255) while(num < 255)
@ -276,12 +320,18 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
llarp::LogError("Could not find any free lokitun interface names"); llarp::LogError("Could not find any free lokitun interface names");
return false; return false;
} }
/*
clientini_f << "ifname=lokinum" << std::to_string(num) << std::endl; clientini_f << "ifname=lokinum" << std::to_string(num) << std::endl;
// prefetch-tags=test // prefetch-tags=test
// enable netns? // enable netns?
llarp::LogInfo("Generated hidden service client as " + basepath llarp::LogInfo("Generated hidden service client as " + basepath
+ "client.ini"); + "client.ini");
*/
f << "ifname=lokinum" << std::to_string(num) << std::endl;
f << "ifaddr=" << ip << std::endl;
return true; return true;
} }

@ -45,7 +45,7 @@ void
llarp_generic_ensure_config(std::ofstream &f, std::string basepath); llarp_generic_ensure_config(std::ofstream &f, std::string basepath);
void void
llarp_ensure_router_config(std::ofstream &f); llarp_ensure_router_config(std::ofstream &f, std::string basepath);
bool bool
llarp_ensure_client_config(std::ofstream &f, std::string basepath); llarp_ensure_client_config(std::ofstream &f, std::string basepath);

@ -471,8 +471,8 @@ raw_resolve_host(struct dnsc_context *dnsc, const char *url,
llarp::LogInfo("Waiting for recv"); llarp::LogInfo("Waiting for recv");
// Timeout? // Timeout?
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0, (struct sockaddr *)&addr, ret = recvfrom(sockfd, (char *)buffer, DNC_BUF_SIZE, 0,
&size); (struct sockaddr *)&addr, &size);
llarp::LogInfo("recv done ", size); llarp::LogInfo("recv done ", size);
if(ret < 0) if(ret < 0)
{ {

@ -121,5 +121,5 @@ bool
llarp_ev_tun_async_write(struct llarp_tun_io *tun, const void *pkt, size_t sz) llarp_ev_tun_async_write(struct llarp_tun_io *tun, const void *pkt, size_t sz)
{ {
// TODO: queue write // TODO: queue write
return static_cast< llarp::ev_io * >(tun->impl)->do_write((void*)pkt, sz); return static_cast< llarp::ev_io * >(tun->impl)->do_write((void *)pkt, sz);
} }

@ -1,8 +1,10 @@
#ifndef LLARP_EV_HPP #ifndef LLARP_EV_HPP
#define LLARP_EV_HPP #define LLARP_EV_HPP
#include <llarp/ev.h> #include <llarp/ev.h>
// witev // writev
#ifndef _WIN32
#include <sys/uio.h> #include <sys/uio.h>
#endif
#ifndef _MSC_VER #ifndef _MSC_VER
#include <unistd.h> #include <unistd.h>
@ -42,104 +44,98 @@ namespace llarp
sendto(const sockaddr* dst, const void* data, size_t sz) = 0; sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
/// used for tun interface /// used for tun interface
bool virtual bool
do_write(void* data, size_t sz) do_write(void* data, size_t sz)
{ {
iovec vecs[2];
// TODO: IPV6
uint32_t t = htonl(AF_INET);
vecs[0].iov_base = &t;
vecs[0].iov_len = sizeof(t);
vecs[1].iov_base = data;
vecs[1].iov_len = sz;
return writev(fd, vecs, 2) != -1;
}
/// called in event loop when fd is ready for writing
/// requeues anything not written
/// this assumes fd is set to non blocking
virtual void
flush_write()
{
m_writeq.Process([&](WriteBuffer& buffer) {
// todo: wtf???
#ifndef _WIN32 #ifndef _WIN32
do_write(buffer.buf, buffer.bufsz); return write(fd, data, sz) != -1;
// if we would block we save the entries for later
// discard entry
#else #else
// writefile return WriteFile((void*)fd, data, sz, nullptr, nullptr);
#endif
}
/// called in event loop when fd is ready for writing
/// requeues anything not written
/// this assumes fd is set to non blocking
virtual void
flush_write()
{
m_writeq.Process([&](WriteBuffer& buffer) {
do_write(buffer.buf, buffer.bufsz);
// if we would block we save the entries for later
// discard entry
});
/// reset errno
errno = 0;
#if _WIN32
SetLastError(0);
#endif #endif
}); }
/// reset errno
errno = 0; struct WriteBuffer
{
llarp_time_t timestamp = 0;
size_t bufsz;
byte_t buf[1500];
WriteBuffer() = default;
WriteBuffer(const void* ptr, size_t sz)
{
if(sz <= sizeof(buf))
{
bufsz = sz;
memcpy(buf, ptr, bufsz);
} }
else
bufsz = 0;
}
struct WriteBuffer struct GetTime
{
llarp_time_t
operator()(const WriteBuffer& w) const
{ {
llarp_time_t timestamp = 0; return w.timestamp;
size_t bufsz; }
byte_t buf[1500]; };
WriteBuffer() = default; struct PutTime
{
WriteBuffer(const void* ptr, size_t sz) void
{ operator()(WriteBuffer& w) const
if(sz <= sizeof(buf)) {
{ w.timestamp = llarp_time_now_ms();
bufsz = sz; }
memcpy(buf, ptr, bufsz); };
}
else struct Compare
bufsz = 0; {
} bool
operator()(const WriteBuffer& left, const WriteBuffer& right) const
struct GetTime
{
llarp_time_t
operator()(const WriteBuffer& w) const
{
return w.timestamp;
}
};
struct PutTime
{
void
operator()(WriteBuffer& w) const
{
w.timestamp = llarp_time_now_ms();
}
};
struct Compare
{
bool
operator()(const WriteBuffer& left, const WriteBuffer& right) const
{
return left.timestamp < right.timestamp;
}
};
};
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
WriteBuffer::PutTime, WriteBuffer::Compare,
llarp::util::NullMutex, llarp::util::NullLock >
m_writeq;
virtual ~ev_io()
{ {
return left.timestamp < right.timestamp;
}
};
};
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
WriteBuffer::PutTime, WriteBuffer::Compare,
llarp::util::NullMutex, llarp::util::NullLock >
m_writeq;
virtual ~ev_io()
{
#ifndef _WIN32 #ifndef _WIN32
::close(fd); ::close(fd);
#else #else
closesocket(fd); closesocket(fd);
#endif #endif
}; };
}; }
;
}; // namespace llarp }
; // namespace llarp
struct llarp_ev_loop struct llarp_ev_loop
{ {

@ -96,10 +96,10 @@ namespace llarp
read(void* buf, size_t sz) read(void* buf, size_t sz)
{ {
ssize_t ret = tuntap_read(tunif, buf, sz); ssize_t ret = tuntap_read(tunif, buf, sz);
if(ret > 4 && t->recvpkt) if(ret > 0 && t->recvpkt)
{ {
// don't include packet info // does not have pktinfo
t->recvpkt(t, ((byte_t*)buf) + 4, ret - 4); t->recvpkt(t, buf, ret);
} }
return ret; return ret;
} }

@ -94,6 +94,19 @@ namespace llarp
return -1; return -1;
} }
bool
do_write(void* buf, size_t sz)
{
iovec vecs[2];
// TODO: IPV6
uint32_t t = htonl(AF_INET);
vecs[0].iov_base = &t;
vecs[0].iov_len = sizeof(t);
vecs[1].iov_base = buf;
vecs[1].iov_len = sz;
return writev(fd, vecs, 2) != -1;
}
void void
flush_write() flush_write()
{ {
@ -109,7 +122,7 @@ namespace llarp
{ {
ssize_t ret = tuntap_read(tunif, buf, sz); ssize_t ret = tuntap_read(tunif, buf, sz);
if(ret > 4 && t->recvpkt) if(ret > 4 && t->recvpkt)
t->recvpkt(t, ((byte_t *)buf) + 4, ret - 4); t->recvpkt(t, ((byte_t*)buf) + 4, ret - 4);
return ret; return ret;
} }

@ -85,6 +85,80 @@ namespace llarp
return 0; return 0;
} }
}; };
struct tun : public ev_io
{
llarp_tun_io* t;
device* tunif;
tun(llarp_tun_io* tio)
: ev_io(-1)
, t(tio)
, tunif(tuntap_init())
{
};
int
sendto(const sockaddr* to, const void* data, size_t sz)
{
return -1;
}
void
flush_write()
{
if(t->before_write)
{
t->before_write(t);
}
ev_io::flush_write();
}
int
read(void* buf, size_t sz)
{
ssize_t ret = tuntap_read(tunif, buf, sz);
if(ret > 4 && t->recvpkt)
// should have pktinfo
t->recvpkt(t, ((byte_t*)buf) + 4, ret - 4);
return ret;
}
bool
setup()
{
llarp::LogDebug("set ifname to ", t->ifname);
strncpy(tunif->if_name, t->ifname, sizeof(tunif->if_name));
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1)
{
llarp::LogWarn("failed to start interface");
return false;
}
if(tuntap_up(tunif) == -1)
{
llarp::LogWarn("failed to put interface up: ", strerror(errno));
return false;
}
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
{
llarp::LogWarn("failed to set ip");
return false;
}
fd = (SOCKET)tunif->tun_fd;
if(fd == -1)
return false;
// set non blocking
int on = 1;
return ioctlsocket(fd, FIONBIO, (u_long*)&on) != -1;
}
~tun()
{
}
};
}; // namespace llarp }; // namespace llarp
struct llarp_win32_loop : public llarp_ev_loop struct llarp_win32_loop : public llarp_ev_loop
@ -93,22 +167,12 @@ struct llarp_win32_loop : public llarp_ev_loop
llarp_win32_loop() : iocpfd(INVALID_HANDLE_VALUE) 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() ~llarp_win32_loop()
{ {
if(iocpfd != INVALID_HANDLE_VALUE) if(iocpfd != INVALID_HANDLE_VALUE)
::CloseHandle(iocpfd); ::CloseHandle(iocpfd);
::WSACleanup();
} }
bool bool
@ -287,7 +351,10 @@ struct llarp_win32_loop : public llarp_ev_loop
llarp::ev_io* llarp::ev_io*
create_tun(llarp_tun_io* tun) create_tun(llarp_tun_io* tun)
{ {
// TODO implement me llarp::tun* t = new llarp::tun(tun);
if(t->setup())
return t;
delete t;
return nullptr; return nullptr;
} }

@ -1,6 +1,7 @@
#ifndef LLARP_FS_HPP #ifndef LLARP_FS_HPP
#define LLARP_FS_HPP #define LLARP_FS_HPP
#include <functional> #include <functional>
#if defined(WIN32) || defined(_WIN32) #if defined(WIN32) || defined(_WIN32)
#define PATH_SEP "\\" #define PATH_SEP "\\"
#else #else
@ -8,21 +9,13 @@
#endif #endif
#include "filesystem.h" #include "filesystem.h"
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM) #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) || defined(__sun)
namespace fs = std::experimental::filesystem; namespace fs = std::experimental::filesystem;
#else #else
namespace fs = std::experimental::filesystem;
#endif // end win32
#else
// not CPP17 needs this
// openbsd needs this
// linux gcc 7.2 needs this
namespace fs = cpp17::filesystem; namespace fs = cpp17::filesystem;
#endif #endif
#include <dirent.h> #include <dirent.h>
namespace llarp namespace llarp

@ -3,8 +3,10 @@
#include <llarp/handlers/tun.hpp> #include <llarp/handlers/tun.hpp>
#include "router.hpp" #include "router.hpp"
#include <sys/types.h> #include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
#endif
#ifndef DNS_PORT #ifndef DNS_PORT
#define DNS_PORT (53) #define DNS_PORT (53)
@ -102,11 +104,11 @@ namespace llarp
strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1); strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1);
// set up address in dotLokiLookup // set up address in dotLokiLookup
struct sockaddr_in s_addr; struct sockaddr_in source_addr;
s_addr.sin_addr.s_addr = inet_addr(tunif.ifaddr); source_addr.sin_addr.s_addr = inet_addr(tunif.ifaddr);
s_addr.sin_family = AF_INET; source_addr.sin_family = AF_INET;
llarp::Addr tunIp(s_addr); llarp::Addr tunIp(source_addr);
// related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp); // related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
dns_iptracker_setup(tunIp); // claim GW IP to make sure it's not inuse dns_iptracker_setup(tunIp); // claim GW IP to make sure it's not inuse
return true; return true;

@ -14,6 +14,12 @@
#include <netinet/ip_icmp.h> #include <netinet/ip_icmp.h>
#endif #endif
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#endif
namespace llarp namespace llarp
{ {
namespace utp namespace utp
@ -342,8 +348,8 @@ namespace llarp
static_cast< LinkLayer* >(utp_context_get_userdata(arg->context)); static_cast< LinkLayer* >(utp_context_get_userdata(arg->context));
llarp::LogDebug("utp_sendto ", Addr(*arg->address), " ", arg->len, llarp::LogDebug("utp_sendto ", Addr(*arg->address), " ", arg->len,
" bytes"); " bytes");
if(sendto(l->m_udp.fd, arg->buf, arg->len, arg->flags, arg->address, if(::sendto(l->m_udp.fd, (char*)arg->buf, arg->len, arg->flags,
arg->address_len) arg->address, arg->address_len)
== -1) == -1)
{ {
llarp::LogError("sendto failed: ", strerror(errno)); llarp::LogError("sendto failed: ", strerror(errno));

@ -118,7 +118,9 @@ _llarp_nt_heap_free(void* mem)
int int
llarp_nt_sockaddr_pton(const char* src, struct sockaddr* dst) llarp_nt_sockaddr_pton(const char* src, struct sockaddr* dst)
{ {
struct addrinfo hints = {0}, *result = nullptr; struct addrinfo hints;
struct addrinfo* result = nullptr;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
@ -261,6 +263,10 @@ _llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1); ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1);
ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next); ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next);
} }
else
{
ift->_ifa.ifa_next = nullptr;
}
} }
} }
@ -866,7 +872,7 @@ namespace llarp
if(i->ifa_addr->sa_family == af) if(i->ifa_addr->sa_family == af)
{ {
llarp::Addr a(*i->ifa_addr); llarp::Addr a(*i->ifa_addr);
if(!(a.isPrivate() || a.isLoopback())) if(!(a.isPrivate() || a.isLoopback() || (a.getHostLong() == 0)))
{ {
ifname = i->ifa_name; ifname = i->ifa_name;
found = true; found = true;

@ -96,7 +96,7 @@ struct llarp_nodedb
llarp::LogDebug("saving RC.pubkey ", filepath); llarp::LogDebug("saving RC.pubkey ", filepath);
std::ofstream ofs( std::ofstream ofs(
filepath, filepath,
std::ofstream::out & std::ofstream::binary & std::ofstream::trunc); std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
ofs.write((char *)buf.base, buf.sz); ofs.write((char *)buf.base, buf.sz);
ofs.close(); ofs.close();
if(!ofs) if(!ofs)
@ -313,7 +313,7 @@ llarp_nodedb_ensure_dir(const char *dir)
std::error_code ec; std::error_code ec;
if(!fs::exists(dir, ec)) if(!fs::exists(dir, ec))
fs::create_directories(path, ec); fs::create_directory(path, ec);
if(ec) if(ec)
return false; return false;

@ -165,6 +165,26 @@ namespace llarp
" rx=", path->RXID()); " rx=", path->RXID());
} }
bool
PathSet::GetCurrentIntroductionsWithFilter(
std::set< llarp::service::Introduction >& intros,
std::function< bool(const llarp::service::Introduction&) > filter) const
{
intros.clear();
size_t count = 0;
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->IsReady() && filter(itr->second->intro))
{
intros.insert(itr->second->intro);
++count;
}
++itr;
}
return count > 0;
}
bool bool
PathSet::GetCurrentIntroductions( PathSet::GetCurrentIntroductions(
std::set< llarp::service::Introduction >& intros) const std::set< llarp::service::Introduction >& intros) const

@ -760,6 +760,9 @@ llarp_router::Run()
return; return;
} }
// generate default hidden service
if(!CreateDefaultHiddenService())
return;
// delayed connect all for clients // delayed connect all for clients
uint64_t delay = ((llarp_randint() % 10) * 500) + 500; uint64_t delay = ((llarp_randint() % 10) * 500) + 500;
llarp_logic_call_later(logic, {delay, this, &ConnectAll}); llarp_logic_call_later(logic, {delay, this, &ConnectAll});
@ -855,6 +858,12 @@ llarp_router::InitOutboundLink()
return false; return false;
} }
bool
llarp_router::CreateDefaultHiddenService()
{
return hiddenServiceContext.AddDefaultEndpoint(defaultIfAddr, defaultIfName);
}
bool bool
llarp_router::HasPendingConnectJob(const llarp::RouterID &remote) llarp_router::HasPendingConnectJob(const llarp::RouterID &remote)
{ {
@ -1054,6 +1063,17 @@ namespace llarp
llarp::LogError("Failed to set up curvecp link"); llarp::LogError("Failed to set up curvecp link");
} }
} }
else if(StrEq(section, "network"))
{
if(StrEq(key, "ifaddr"))
{
self->defaultIfAddr = val;
}
if(StrEq(key, "ifname"))
{
self->defaultIfAddr = val;
}
}
else if(StrEq(section, "services")) else if(StrEq(section, "services"))
{ {
if(self->LoadHiddenServiceConfig(val)) if(self->LoadHiddenServiceConfig(val))

@ -93,6 +93,13 @@ struct llarp_router
llarp::service::Context hiddenServiceContext; llarp::service::Context hiddenServiceContext;
std::string defaultIfAddr = "10.200.0.1/24";
std::string defaultIfName = "lokitun0";
bool
CreateDefaultHiddenService();
std::unique_ptr< llarp::ILinkLayer > outboundLink; std::unique_ptr< llarp::ILinkLayer > outboundLink;
std::vector< std::unique_ptr< llarp::ILinkLayer > > inboundLinks; std::vector< std::unique_ptr< llarp::ILinkLayer > > inboundLinks;

@ -106,6 +106,12 @@ namespace llarp
return tunEndpoint->MapAddress(addr, ip); return tunEndpoint->MapAddress(addr, ip);
} }
bool
Context::AddDefaultEndpoint(const std::string & ifaddr, const std::string & ifname)
{
return AddEndpoint({ "default", {{"type", "tun"}, {"ifaddr", ifaddr}, {"ifname", ifname}}});
}
bool bool
Context::AddEndpoint(const Config::section_t &conf) Context::AddEndpoint(const Config::section_t &conf)
{ {

@ -91,22 +91,25 @@ namespace llarp
} }
void void
Endpoint::RegenAndPublishIntroSet(llarp_time_t now) Endpoint::RegenAndPublishIntroSet(llarp_time_t now, bool forceRebuild)
{ {
std::set< Introduction > I; std::set< Introduction > I;
if(!GetCurrentIntroductions(I)) if(!GetCurrentIntroductionsWithFilter(
I, [now](const service::Introduction& intro) -> bool {
return now < intro.expiresAt
&& intro.expiresAt - now > (2 * 60 * 1000);
}))
{ {
llarp::LogWarn("could not publish descriptors for endpoint ", Name(), llarp::LogWarn("could not publish descriptors for endpoint ", Name(),
" because we couldn't get any introductions"); " because we couldn't get enough valid introductions");
if(ShouldBuildMore()) if(ShouldBuildMore() || forceRebuild)
ManualRebuild(1); ManualRebuild(1);
return; return;
} }
m_IntroSet.I.clear(); m_IntroSet.I.clear();
for(const auto& intro : I) for(const auto& intro : I)
{ {
if(now < intro.expiresAt && intro.expiresAt - now > 60000) m_IntroSet.I.push_back(intro);
m_IntroSet.I.push_back(intro);
} }
if(m_IntroSet.I.size() == 0) if(m_IntroSet.I.size() == 0)
{ {
@ -760,6 +763,7 @@ namespace llarp
if(MarkCurrentIntroBad(llarp_time_now_ms())) if(MarkCurrentIntroBad(llarp_time_now_ms()))
llarp::LogInfo(Name(), " switched intros to ", remoteIntro.router, llarp::LogInfo(Name(), " switched intros to ", remoteIntro.router,
" via ", remoteIntro.pathID); " via ", remoteIntro.pathID);
UpdateIntroSet();
} }
return true; return true;
} }
@ -815,7 +819,7 @@ namespace llarp
Endpoint::HandlePathDead(void* user) Endpoint::HandlePathDead(void* user)
{ {
Endpoint* self = static_cast< Endpoint* >(user); Endpoint* self = static_cast< Endpoint* >(user);
self->RegenAndPublishIntroSet(llarp_time_now_ms()); self->RegenAndPublishIntroSet(llarp_time_now_ms(), true);
} }
bool bool
@ -918,10 +922,18 @@ namespace llarp
{ {
if(markedBad) if(markedBad)
return true; return true;
if(i && currentIntroSet.T < i->T) if(i)
{ {
if(currentIntroSet.T >= i->T)
{
llarp::LogInfo("introset is old, dropping");
return true;
}
currentIntroSet = *i; currentIntroSet = *i;
ShiftIntroduction(); if(!ShiftIntroduction())
{
llarp::LogWarn("failed to pick new intro during introset update");
}
if(GetPathByRouter(remoteIntro.router) == nullptr) if(GetPathByRouter(remoteIntro.router) == nullptr)
BuildOneAlignedTo(remoteIntro.router); BuildOneAlignedTo(remoteIntro.router);
} }
@ -1013,42 +1025,13 @@ namespace llarp
} }
++itr; ++itr;
} }
llarp::LogWarn("No path ready to send yet");
// all paths are not ready? // all paths are not ready?
return false; return false;
} }
// no converstation // no converstation
auto itr = m_PendingTraffic.find(remote); EnsurePathToService(remote, [](Address, OutboundContext*) {}, 5000);
if(itr == m_PendingTraffic.end()) return false;
{
m_PendingTraffic.insert(std::make_pair(remote, PendingBufferQueue()));
EnsurePathToService(
remote,
[&](Address addr, OutboundContext* ctx) {
if(ctx)
{
auto itr = m_PendingTraffic.find(addr);
if(itr != m_PendingTraffic.end())
{
while(itr->second.size())
{
auto& front = itr->second.front();
ctx->AsyncEncryptAndSendTo(front.Buffer(), front.protocol);
itr->second.pop();
}
}
}
else
{
llarp::LogWarn("failed to obtain outbound context to ", addr,
" within timeout");
}
m_PendingTraffic.erase(addr);
},
10000);
}
m_PendingTraffic[remote].emplace(data, t);
return true;
} }
bool bool
@ -1090,9 +1073,51 @@ namespace llarp
Endpoint::OutboundContext::MarkCurrentIntroBad(llarp_time_t now) Endpoint::OutboundContext::MarkCurrentIntroBad(llarp_time_t now)
{ {
// insert bad intro // insert bad intro
m_BadIntros.insert(std::make_pair(remoteIntro, now)); m_BadIntros[remoteIntro] = now;
// shift // unconditional shift
return ShiftIntroduction(); bool shiftedRouter = false;
bool shiftedIntro = false;
// try same router
for(const auto& intro : currentIntroSet.I)
{
llarp::LogInfo("have intro: ", intro);
if(intro.ExpiresSoon(now))
{
llarp::LogInfo("skipping intro, expires soon");
continue;
}
auto itr = m_BadIntros.find(intro);
if(itr == m_BadIntros.end() && intro.router == remoteIntro.router)
{
shiftedIntro = true;
remoteIntro = intro;
break;
}
}
if(!shiftedIntro)
{
// try any router
for(const auto& intro : currentIntroSet.I)
{
if(intro.ExpiresSoon(now))
continue;
auto itr = m_BadIntros.find(intro);
if(itr == m_BadIntros.end())
{
// TODO: this should always be true but idk if it really is
shiftedRouter = remoteIntro.router != intro.router;
shiftedIntro = true;
remoteIntro = intro;
break;
}
}
}
if(shiftedRouter)
{
lastShift = now;
ManualRebuild(1);
}
return shiftedIntro;
} }
bool bool
@ -1167,11 +1192,13 @@ namespace llarp
Introduction remoteIntro; Introduction remoteIntro;
std::function< void(ProtocolFrame&) > hook; std::function< void(ProtocolFrame&) > hook;
IDataHandler* handler; IDataHandler* handler;
ConvoTag tag;
AsyncKeyExchange(llarp_logic* l, llarp_crypto* c, const ServiceInfo& r, AsyncKeyExchange(llarp_logic* l, llarp_crypto* c, const ServiceInfo& r,
const Identity& localident, const Identity& localident,
const PQPubKey& introsetPubKey, const PQPubKey& introsetPubKey,
const Introduction& remote, IDataHandler* h) const Introduction& remote, IDataHandler* h,
const ConvoTag& t)
: logic(l) : logic(l)
, crypto(c) , crypto(c)
, remote(r) , remote(r)
@ -1179,6 +1206,7 @@ namespace llarp
, introPubKey(introsetPubKey) , introPubKey(introsetPubKey)
, remoteIntro(remote) , remoteIntro(remote)
, handler(h) , handler(h)
, tag(t)
{ {
} }
@ -1215,8 +1243,8 @@ namespace llarp
// H (K + PKE(A, B, N)) // H (K + PKE(A, B, N))
self->crypto->shorthash(self->sharedKey, self->crypto->shorthash(self->sharedKey,
llarp::StackBuffer< decltype(tmp) >(tmp)); llarp::StackBuffer< decltype(tmp) >(tmp));
// randomize tag // set tag
self->msg.tag.Randomize(); self->msg.tag = self->tag;
// set sender // set sender
self->msg.sender = self->m_LocalIdentity.pub; self->msg.sender = self->m_LocalIdentity.pub;
// set version // set version
@ -1238,9 +1266,7 @@ namespace llarp
void void
Endpoint::EnsureReplyPath(const ServiceInfo& ident) Endpoint::EnsureReplyPath(const ServiceInfo& ident)
{ {
auto itr = m_AddressToService.find(ident.Addr()); m_AddressToService[ident.Addr()] = ident;
if(itr == m_AddressToService.end())
m_AddressToService.insert(std::make_pair(ident.Addr(), ident));
} }
void void
@ -1259,13 +1285,15 @@ namespace llarp
return; return;
} }
} }
currentConvoTag.Randomize();
AsyncKeyExchange* ex = new AsyncKeyExchange(
m_Endpoint->RouterLogic(), m_Endpoint->Crypto(), remoteIdent,
m_Endpoint->GetIdentity(), currentIntroSet.K, remoteIntro,
m_DataHandler, currentConvoTag);
AsyncKeyExchange* ex =
new AsyncKeyExchange(m_Endpoint->RouterLogic(), m_Endpoint->Crypto(),
remoteIdent, m_Endpoint->GetIdentity(),
currentIntroSet.K, remoteIntro, m_DataHandler);
ex->hook = std::bind(&Endpoint::OutboundContext::Send, this, ex->hook = std::bind(&Endpoint::OutboundContext::Send, this,
std::placeholders::_1); std::placeholders::_1);
ex->msg.PutBuffer(payload); ex->msg.PutBuffer(payload);
ex->msg.introReply = path->intro; ex->msg.introReply = path->intro;
llarp_threadpool_queue_job(m_Endpoint->Worker(), llarp_threadpool_queue_job(m_Endpoint->Worker(),
@ -1426,18 +1454,12 @@ namespace llarp
Endpoint::SendContext::EncryptAndSendTo(llarp_buffer_t payload, Endpoint::SendContext::EncryptAndSendTo(llarp_buffer_t payload,
ProtocolType t) ProtocolType t)
{ {
std::set< ConvoTag > tags;
if(!m_DataHandler->GetConvoTagsForService(remoteIdent, tags))
{
llarp::LogError("no open converstations with remote endpoint?");
return;
}
auto crypto = m_Endpoint->Router()->crypto; auto crypto = m_Endpoint->Router()->crypto;
const byte_t* shared = nullptr; const byte_t* shared = nullptr;
routing::PathTransferMessage msg; routing::PathTransferMessage msg;
ProtocolFrame& f = msg.T; ProtocolFrame& f = msg.T;
f.N.Randomize(); f.N.Randomize();
f.T = *tags.begin(); f.T = currentConvoTag;
f.S = m_Endpoint->GetSeqNoForConvo(f.T); f.S = m_Endpoint->GetSeqNoForConvo(f.T);
auto now = llarp_time_now_ms(); auto now = llarp_time_now_ms();
@ -1486,8 +1508,8 @@ namespace llarp
++sequenceNo; ++sequenceNo;
if(path->SendRoutingMessage(&msg, m_Endpoint->Router())) if(path->SendRoutingMessage(&msg, m_Endpoint->Router()))
{ {
llarp::LogInfo("sent message via ", remoteIntro.pathID, " on ", llarp::LogDebug("sent message via ", remoteIntro.pathID, " on ",
remoteIntro.router); remoteIntro.router);
} }
else else
{ {

@ -1,28 +1,31 @@
#include <llarp/time.h> #include <llarp/time.h>
#include <chrono> #include <time.h>
#include <sys/time.h>
namespace llarp
{
typedef std::chrono::system_clock clock_t;
template < typename Res, typename IntType >
static IntType
time_since_epoch()
{
return std::chrono::duration_cast< Res >(
llarp::clock_t::now().time_since_epoch())
.count();
}
} // namespace llarp
// these _should_ be 32-bit safe...
llarp_time_t llarp_time_t
llarp_time_now_ms() llarp_time_now_ms()
{ {
return llarp::time_since_epoch< std::chrono::milliseconds, llarp_time_t >(); struct timeval tv;
struct timezone z;
z.tz_minuteswest = 0;
time_t t = time(nullptr);
z.tz_dsttime = gmtime(&t)->tm_isdst;
gettimeofday(&tv, &z);
llarp_time_t timeNow =
(llarp_time_t)(tv.tv_sec) * 1000 + (llarp_time_t)(tv.tv_usec) / 1000;
return timeNow;
} }
llarp_seconds_t llarp_seconds_t
llarp_time_now_sec() llarp_time_now_sec()
{ {
return llarp::time_since_epoch< std::chrono::seconds, llarp_seconds_t >(); struct timeval tv;
struct timezone z;
z.tz_minuteswest = 0;
time_t t = time(nullptr);
z.tz_dsttime = gmtime(&t)->tm_isdst;
gettimeofday(&tv, &z);
llarp_time_t timeNow = tv.tv_sec;
return timeNow;
} }

@ -15,7 +15,7 @@ namespace llarp
bool bool
TransitHop::Expired(llarp_time_t now) const TransitHop::Expired(llarp_time_t now) const
{ {
return now - started > lifetime; return now > ExpireTime();
} }
llarp_time_t llarp_time_t
@ -54,7 +54,9 @@ namespace llarp
TransitHop::SendRoutingMessage(llarp::routing::IMessage* msg, TransitHop::SendRoutingMessage(llarp::routing::IMessage* msg,
llarp_router* r) llarp_router* r)
{ {
byte_t tmp[MAX_LINK_MSG_SIZE - 1024]; if(!IsEndpoint(r->pubkey()))
return false;
byte_t tmp[MAX_LINK_MSG_SIZE - 128];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf)) if(!msg->BEncode(&buf))
{ {
@ -64,12 +66,14 @@ namespace llarp
TunnelNonce N; TunnelNonce N;
N.Randomize(); N.Randomize();
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
// pad smaller messages // pad to nearest MESSAGE_PAD_SIZE bytes
if(buf.sz < MESSAGE_PAD_SIZE) auto dlt = buf.sz % MESSAGE_PAD_SIZE;
if(dlt)
{ {
dlt = MESSAGE_PAD_SIZE - dlt;
// randomize padding // randomize padding
r->crypto.randbytes(buf.cur, MESSAGE_PAD_SIZE - buf.sz); r->crypto.randbytes(buf.cur, dlt);
buf.sz = MESSAGE_PAD_SIZE; buf.sz += dlt;
} }
buf.cur = buf.base; buf.cur = buf.base;
return HandleDownstream(buf, N, r); return HandleDownstream(buf, N, r);
@ -94,7 +98,7 @@ namespace llarp
llarp_router* r) llarp_router* r)
{ {
r->crypto.xchacha20(buf, pathKey, Y); r->crypto.xchacha20(buf, pathKey, Y);
if(info.upstream == RouterID(r->pubkey())) if(IsEndpoint(r->pubkey()))
{ {
return m_MessageParser.ParseMessageBuffer(buf, this, info.rxID, r); return m_MessageParser.ParseMessageBuffer(buf, this, info.rxID, r);
} }
@ -166,7 +170,6 @@ namespace llarp
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
buf.cur = buf.base; buf.cur = buf.base;
// send // send
llarp::LogInfo("Transfer ", buf.sz, " bytes", " to ", msg->P);
return path->HandleDownstream(buf, msg->Y, r); return path->HandleDownstream(buf, msg->Y, r);
} }

@ -20,12 +20,11 @@ option(gtest_build_tests "Build all of gtest's own tests." OFF)
option(gtest_build_samples "Build gtest's sample programs." OFF) option(gtest_build_samples "Build gtest's sample programs." OFF)
if (NOT WIN32)
option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF) option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
else()
# use native windows nt threading even in gcc or clang option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON)
if (WIN32) endif(NOT WIN32)
option(gtest_disable_pthreads ON)
endif(WIN32)
option( option(
gtest_hide_internal_symbols gtest_hide_internal_symbols

@ -30,7 +30,7 @@
#ifndef PBL_CPP_FILESYSTEM_H #ifndef PBL_CPP_FILESYSTEM_H
#define PBL_CPP_FILESYSTEM_H #define PBL_CPP_FILESYSTEM_H
#if _MSC_VER >= 1910 #if _MSC_VER >= 1900
#define CPP17 #define CPP17
#define CPP11 #define CPP11
#define CPP14 #define CPP14
@ -39,13 +39,8 @@
#include "version.h" #include "version.h"
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM) #if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
#if defined(__MINGW32__) || defined(_MSC_VER) || defined(__sun)
// win32 needs experimental
#include <experimental/filesystem> #include <experimental/filesystem>
#else #else
#include <experimental/filesystem>
#endif
#else
// OpenBSD needs this // OpenBSD needs this
// MacOS llvm 3.8 needs this // MacOS llvm 3.8 needs this
#include "fs/absolute.h" #include "fs/absolute.h"

@ -1,30 +1,31 @@
/* Copyright (c) 2014, Pollard Banknote Limited /* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without
are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or this list of conditions and the following disclaimer in the documentation
other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without may be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "basename.h" #include "basename.h"
@ -33,168 +34,174 @@
namespace namespace
{ {
// the position following the previous occurrence of c (relative to position j), // the position following the previous occurrence of c (relative to position
// or 0 if not. In this file, the first letter of a path component. // j), or 0 if not. In this file, the first letter of a path component.
std::size_t after_last( std::size_t
const std::string& s, after_last(const std::string& s, char c, std::size_t j)
char c, {
std::size_t j std::size_t i = s.find_last_of(c, j);
)
{ return i == std::string::npos ? 0 : i + 1;
std::size_t i = s.find_last_of(c, j); }
return i == std::string::npos ? 0 : i + 1; // (first character, length) of last path component in s or (0,0) for "."
} // or (npos, 0) if error
std::pair< std::size_t, std::size_t >
// (first character, length) of last path component in s or (0,0) for "." locate_last_path_component(const std::string& s)
// or (npos, 0) if error {
std::pair< std::size_t, std::size_t > locate_last_path_component(const std::string& s) if(s.empty())
{ {
if ( s.empty() ) // error
{ return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
}
// error
return std::pair< std::size_t, std::size_t >(std::string::npos, 0); // j points to the last character in a component
} std::size_t j = s.find_last_not_of('/');
unsigned depth = 0;
// j points to the last character in a component
std::size_t j = s.find_last_not_of('/'); while(j != std::string::npos)
unsigned depth = 0; {
// i points to first character of a component
while ( j != std::string::npos ) // i <= j, because j never points to a '/'
{ const std::size_t i = after_last(s, '/', j);
// i points to first character of a component
// i <= j, because j never points to a '/' if(j - i + 1 == 1 && s[i] == '.')
const std::size_t i = after_last(s, '/', j); {
// component is ".", basically ignore this component
if ( j - i + 1 == 1 && s[i] == '.' ) }
{ else if(j - i + 1 == 2 && s[i] == '.' && s[i + 1] == '.')
// component is ".", basically ignore this component {
} // component is "..", ignore the next component
else if ( j - i + 1 == 2 && s[i] == '.' && s[i + 1] == '.' ) ++depth;
{ }
// component is "..", ignore the next component else
++depth; {
} // found a "normal" path component
else if(depth == 0)
{ {
// found a "normal" path component return std::pair< std::size_t, std::size_t >(i, j - i + 1);
if ( depth == 0 ) }
{
return std::pair< std::size_t, std::size_t >(i, j - i + 1); // ..but we're ignoring it
} --depth;
}
// ..but we're ignoring it
--depth; if(i == 0)
} {
if(depth == 0)
if ( i == 0 ) {
{ // "."
if ( depth == 0 ) return std::pair< std::size_t, std::size_t >(0, 0);
{ }
else
// "." {
return std::pair< std::size_t, std::size_t >(0, 0); // error, path is malformed
} return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
else }
{ }
// error, path is malformed j = s.find_last_not_of('/', i - 1);
return std::pair< std::size_t, std::size_t >(std::string::npos, 0); }
}
} // all slashes
return std::pair< std::size_t, std::size_t >(0, 1);
j = s.find_last_not_of('/', i - 1); }
}
std::string
// all slashes basename_posix(const std::string& s)
return std::pair< std::size_t, std::size_t >(0, 1); {
} const std::pair< std::size_t, std::size_t > range =
locate_last_path_component(s);
std::string basename_posix(const std::string& s)
{ if(range.first == std::string::npos)
const std::pair< std::size_t, std::size_t > range = locate_last_path_component(s); {
return std::string();
if ( range.first == std::string::npos ) }
{
return std::string(); if(range.first == 0 && range.second == 0)
} {
return ".";
if ( range.first == 0 && range.second == 0 ) }
{
return "."; return s.substr(range.first, range.second);
} }
std::string
return s.substr(range.first, range.second); dirname_posix(const std::string& s)
} {
const std::pair< std::size_t, std::size_t > range =
std::string dirname_posix(const std::string& s) locate_last_path_component(s);
{
const std::pair< std::size_t, std::size_t > range = locate_last_path_component(s); // path was malformed
if(range.first == std::string::npos)
// path was malformed {
if ( range.first == std::string::npos ) return std::string();
{ }
return std::string();
} if(range.first == 0)
{
if ( range.first == 0 ) if(range.second == 0)
{ {
if ( range.second == 0 ) return "..";
{ }
return "..";
} // could be '/', or could be a unpathed filename
if(s[0] == '/')
// could be '/', or could be a unpathed filename {
if ( s[0] == '/' ) return "/";
{ }
return "/";
} return ".";
}
return "."; else
} {
else // leading directory
{ return s.substr(0, range.first);
}
// leading directory }
return s.substr(0, range.first);
} } // namespace
}
}
namespace cpp17 namespace cpp17
{ {
namespace filesystem namespace filesystem
{ {
// Calls the basename_xxx appropriate for this platform // Calls the basename_xxx appropriate for this platform
std::string basename(const std::string& s) std::string
{ basename(const std::string& s)
#ifdef OS_POSIX {
#ifdef OS_POSIX
return basename_posix(s); return basename_posix(s);
#else
#else std::string t;
#error "No implementation of basename is available for this platform" char fname[_MAX_FNAME], ext[_MAX_EXT];
#endif _splitpath(s.c_str(), nullptr, nullptr, fname, ext);
} t = fname;
t += ext;
std::string dirname(const std::string& s) return t;
{ #endif
#ifdef OS_POSIX }
const std::string& t = dirname_posix(s);
std::string
if ( t == "." ) dirname(const std::string& s)
{ {
return t; #ifdef OS_POSIX
} const std::string& t = dirname_posix(s);
return cleanpath(t); if(t == ".")
{
#else return t;
#error "No implementation of dirname is available for this platform" }
#endif
} return cleanpath(t);
} #else
} std::string t;
char _dirname[_MAX_DIR];
_splitpath(s.c_str(), nullptr, _dirname, nullptr, nullptr);
t = _dirname;
return t;
#endif
}
} // namespace filesystem
} // namespace cpp17

@ -1,138 +1,144 @@
/* Copyright (c) 2014, Pollard Banknote Limited /* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without
are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or this list of conditions and the following disclaimer in the documentation
other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without may be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "cleanpath.h" #include "cleanpath.h"
#include <algorithm>
#if defined(_WIN32) && !defined(NOMINMAX)
#define NOMINMAX
#endif
namespace cpp17 namespace cpp17
{ {
namespace filesystem namespace filesystem
{ {
/// @todo Probably belongs in path.cpp /// @todo Probably belongs in path.cpp
std::string cleanpath(const std::string& s) std::string
{ cleanpath(const std::string& s)
std::string t; {
std::string t;
if ( s.empty() )
{ if(s.empty())
{
// error // error
return t; return t;
} }
const std::size_t n = s.length(); const std::size_t n = s.length();
for ( std::size_t i = 0; i < n;) for(std::size_t i = 0; i < n;)
{ {
if ( s[i] == '/' ) if(s[i] == '/')
{ {
// directory separator // directory separator
t.push_back('/'); t.push_back('/');
i = s.find_first_not_of('/', i); i = s.find_first_not_of('/', i);
} }
else else
{ {
// path component // path component
const std::size_t j = std::min(s.find('/', i), n); const std::size_t j = std::min(s.find('/', i), n);
if ( s.compare(i, j - i, ".", 1) == 0 ) if(s.compare(i, j - i, ".", 1) == 0)
{ {
// handle dot // handle dot
if ( j < n ) if(j < n)
{ {
i = s.find_first_not_of('/', j); i = s.find_first_not_of('/', j);
} }
else else
{ {
i = n; i = n;
} }
} }
else if ( s.compare(i, j - i, "..", 2) == 0 ) else if(s.compare(i, j - i, "..", 2) == 0)
{ {
// handle dot-dot // handle dot-dot
const std::size_t l = t.length(); const std::size_t l = t.length();
if ( l == 0 ) if(l == 0)
{ {
// no previous component (ex., "../src") // no previous component (ex., "../src")
t.assign("..", 2); t.assign("..", 2);
i = j; i = j;
} }
else else
{ {
// remove previously copied component (unless root) // remove previously copied component (unless root)
if ( l >= 2 ) if(l >= 2)
{ {
const std::size_t k = t.find_last_of('/', l - 2); const std::size_t k = t.find_last_of('/', l - 2);
if ( k == std::string::npos ) if(k == std::string::npos)
{ {
t.clear(); t.clear();
} }
else else
{ {
t.resize(k + 1); t.resize(k + 1);
} }
} }
if ( j < n ) if(j < n)
{ {
i = s.find_first_not_of('/', j); i = s.find_first_not_of('/', j);
} }
else else
{ {
i = n; i = n;
} }
} }
} }
else else
{ {
// append path component // append path component
t.append(s, i, j - i); t.append(s, i, j - i);
i = j; i = j;
} }
} }
} }
if ( t.empty() ) if(t.empty())
{ {
return "."; return ".";
} }
// drop trailing slashes // drop trailing slashes
const std::size_t i = t.find_last_not_of('/'); const std::size_t i = t.find_last_not_of('/');
if ( i != std::string::npos ) if(i != std::string::npos)
{ {
t.resize(i + 1); t.resize(i + 1);
} }
return t; return t;
} }
} } // namespace filesystem
} } // namespace cpp17

@ -1,30 +1,31 @@
/* Copyright (c) 2015, Pollard Banknote Limited /* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without
are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or this list of conditions and the following disclaimer in the documentation
other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without may be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef PBL_CPP_FS_CLEANPATH_H #ifndef PBL_CPP_FS_CLEANPATH_H
#define PBL_CPP_FS_CLEANPATH_H #define PBL_CPP_FS_CLEANPATH_H
@ -33,29 +34,31 @@
namespace cpp17 namespace cpp17
{ {
namespace filesystem namespace filesystem
{ {
/** Return a simplified version of path /** Return a simplified version of path
* *
* @param path A file system path * @param path A file system path
* *
* Collapses multiple path separators (ex., as in "/home//user"); replaces * Collapses multiple path separators (ex., as in "/home//user"); replaces
* "name/." with "name" and "parent/child/.." with "parent"; removes trailing * "name/." with "name" and "parent/child/.." with "parent"; removes
* slashes. * trailing slashes.
* *
* The returned path is equivalent to the original path in the sense that it * The returned path is equivalent to the original path in the sense that it
* identifies the same file system object. Specifically, relative paths are * identifies the same file system object. Specifically, relative paths are
* preserved (ex., no simplification is done to the dot-dot in "../here"). * preserved (ex., no simplification is done to the dot-dot in "../here").
* *
* If the path is malformed, the empty string is returned. For this function, * If the path is malformed, the empty string is returned. For this
* really only the empty string itself is "malformed". * function, really only the empty string itself is "malformed".
* *
* @note This is a textual operation. It does not validate the string against * @note This is a textual operation. It does not validate the string
* the file system or otherwise touch the file system. * against the file system or otherwise touch the file system.
* @bug foo/bar/../baz may not point to /foo/baz if bar symlinks to flip/flop * @bug foo/bar/../baz may not point to /foo/baz if bar symlinks to
*/ * flip/flop
std::string cleanpath(const std::string& path); */
} std::string
} cleanpath(const std::string& path);
} // namespace filesystem
} // namespace cpp17
#endif // PBL_FS_CLEANPATH_H #endif // PBL_FS_CLEANPATH_H

@ -1,30 +1,31 @@
/* Copyright (c) 2016, Pollard Banknote Limited /* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without
are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or this list of conditions and the following disclaimer in the documentation
other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without may be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "create_directory.h" #include "create_directory.h"
@ -33,37 +34,43 @@
#include "perms.h" #include "perms.h"
#include "filestatus.h" #include "filestatus.h"
namespace cpp17 #ifdef _WIN32
{ #include <direct.h>
namespace filesystem #define mkdir(x, y) mkdir(x)
{ #endif
bool create_directory(const path& s, std::error_code& ec) namespace cpp17
{ {
if ( s.empty() ) namespace filesystem
{ {
return false; bool
} create_directory(const path& s, std::error_code& ec)
{
if(s.empty())
{
return false;
}
return ::mkdir( s.c_str(), static_cast< int >( perms::all ) ) == 0; return ::mkdir(s.c_str(), static_cast< int >(perms::all)) == 0;
} }
bool create_directories(const path& s, std::error_code& ec) bool
{ create_directories(const path& s, std::error_code& ec)
path p = s.parent_path(); {
path p = s.parent_path();
if ( !p.empty() ) if(!p.empty())
{ {
std::error_code ec, ec2; std::error_code ec, ec2;
if ( !exists(p, ec) && !create_directories(p, ec2) ) if(!exists(p, ec) && !create_directories(p, ec2))
{ {
return false; return false;
} }
} }
std::error_code ec3; std::error_code ec3;
return create_directory(s, ec3); return create_directory(s, ec3);
} }
} } // namespace filesystem
} } // namespace cpp17

@ -1,81 +1,87 @@
/* Copyright (c) 2016, Pollard Banknote Limited /* Copyright (c) 2016, Pollard Banknote Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without
are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or this list of conditions and the following disclaimer in the documentation
other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without may be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "current_path.h" #include "current_path.h"
#include <cerrno> #include <cerrno>
#ifndef _MSC_VER
#include <unistd.h> #include <unistd.h>
#else
#include <direct.h>
#endif
namespace cpp17 namespace cpp17
{ {
namespace filesystem namespace filesystem
{ {
path current_path() path
{ current_path()
char buf[4096]; {
char buf[4096];
if ( ::getcwd( buf, sizeof( buf ) ) ) if(::getcwd(buf, sizeof(buf)))
{ {
return buf; return buf;
} }
// Dynamically allocate larger buffers until cwd fits // Dynamically allocate larger buffers until cwd fits
std::size_t size = 2 * sizeof( buf ); std::size_t size = 2 * sizeof(buf);
while ( true ) while(true)
{ {
char* q = new char[size]; char* q = new char[size];
if ( ::getcwd(q, size) ) if(::getcwd(q, size))
{ {
path p = q; path p = q;
delete[] q; delete[] q;
return p; return p;
} }
else else
{ {
if ( errno == ERANGE ) if(errno == ERANGE)
{ {
delete[] q; delete[] q;
size *= 2; size *= 2;
} }
else else
{ {
delete[] q; delete[] q;
break; break;
} }
} }
} }
return path(); return path();
} }
} } // namespace filesystem
} } // namespace cpp17

@ -1,30 +1,31 @@
/* Copyright (c) 2014, Pollard Banknote Limited /* Copyright (c) 2014, Pollard Banknote Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without
are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or this list of conditions and the following disclaimer in the documentation
other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without may be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "diriter.h" #include "diriter.h"
@ -33,442 +34,473 @@
#include <climits> #include <climits>
#include <dirent.h> #include <dirent.h>
#ifdef _WIN32
#include <io.h>
#endif
#include "direntry.h" #include "direntry.h"
#include "path.h" #include "path.h"
namespace cpp17 namespace cpp17
{ {
namespace filesystem namespace filesystem
{ {
/// @todo Could save the malloc/free (of e) if we mark end-of-directory
/// @todo Could save the malloc/free (of e) if we mark end-of-directory class directory_iterator::impl
class directory_iterator::impl {
{ public:
public: impl() : p(), d(0), e(0), info(), valid_info(false)
impl() {
: p(), d(0), e(0), info(), valid_info(false) // printf("directory_iterator::impl::cstr\n");
{
//printf("directory_iterator::impl::cstr\n");
pos = 0; pos = 0;
} }
explicit impl(const path& path_) explicit impl(const path& path_)
: p(path_), d(0), e(0), info(), valid_info(false) : p(path_), d(0), e(0), info(), valid_info(false)
{ {
//printf("directory_iterator::impl::cstr path[%s]\n", path_.c_str()); // printf("directory_iterator::impl::cstr path[%s]\n", path_.c_str());
this->cPath = path_; this->cPath = path_;
d = ::opendir( path_.c_str() ); d = ::opendir(path_.c_str());
if ( d ) if(d)
{ {
e = acquire(); e = acquire();
next(); next();
} }
} }
~impl() ~impl()
{ {
//printf("directory_iterator::impl::dstr [%s]\n", this->cPath.c_str()); // printf("directory_iterator::impl::dstr [%s]\n", this->cPath.c_str());
if ( d ) if(d)
{
release(); // free e
::closedir(d);
d = 0;
}
}
void rewind() {
//printf("directory_iterator::impl::rewind\n");
if ( d )
{ {
release(); release(); // free e
::closedir(d); ::closedir(d);
d = 0;
} }
d = ::opendir( this->cPath.c_str() ); }
void
rewind()
{
// printf("directory_iterator::impl::rewind\n");
if(d)
{
release();
::closedir(d);
}
d = ::opendir(this->cPath.c_str());
pos = 0; pos = 0;
if ( d ) if(d)
{ {
e = acquire(); e = acquire();
next(); next();
} }
} }
void seek(size_t seekPos) { void
//printf("directory_iterator::impl::seek\n"); seek(size_t seekPos)
{
// printf("directory_iterator::impl::seek\n");
this->rewind(); this->rewind();
for(size_t i = 0; i < seekPos; i++) { for(size_t i = 0; i < seekPos; i++)
this->next(); {
this->next();
} }
} }
/** Test if this is an end iterator
*/
bool is_end() const
{
//printf("directory_iterator::impl::is_end\n");
return !e;
}
bool next() /** Test if this is an end iterator
{ */
//printf("directory_iterator::impl::next\n"); bool
if ( d ) is_end() const
{ {
valid_info = false; // printf("directory_iterator::impl::is_end\n");
return !e;
}
do bool
{ next()
dirent* ptr = 0; {
// printf("directory_iterator::impl::next\n");
if(d)
{
valid_info = false;
const int res = ::readdir_r(d, e, &ptr); do
{
dirent* ptr = 0;
if ( res != 0 || ptr == 0 ) const int res = ::readdir_r(d, e, &ptr);
{
// error, or end of directory
pos = 0;
release();
return false; if(res != 0 || ptr == 0)
} {
} // error, or end of directory
while ( std::strcmp(e->d_name, ".") == 0 || std::strcmp(e->d_name, "..") == 0 ); pos = 0;
release();
pos++; return false;
}
return true; } while(std::strcmp(e->d_name, ".") == 0
} || std::strcmp(e->d_name, "..") == 0);
return false;
}
path get_path() const
{
//printf("directory_iterator::impl::get_path\n");
return e ? ( p / e->d_name ) : path();
}
file_type type() const
{
//printf("directory_iterator::impl::type\n");
if ( e )
{
switch ( e->d_type )
{
case DT_FIFO:
return file_type::fifo;
case DT_CHR:
return file_type::character;
case DT_DIR:
return file_type::directory;
case DT_BLK:
return file_type::block;
case DT_REG:
return file_type::regular;
case DT_LNK:
return file_type::symlink;
case DT_SOCK:
return file_type::socket;
default:
break;
} // switch
}
return file_type::unknown;
}
const directory_entry& get_reference()
{
//printf("directory_iterator::impl::get_reference\n");
update();
return info;
}
const directory_entry* get_pointer()
{
//printf("directory_iterator::impl::get_pointer\n");
update();
return &info;
}
/// Position
size_t pos;
// Path to directory
path p;
private:
void update()
{
//printf("directory_iterator::impl::update\n");
if ( !valid_info && e )
{
const path q = p / e->d_name;
info.assign(q);
valid_info = true;
}
}
static dirent* acquire() pos++;
{
//printf("directory_iterator::impl::acquire\n");
/* dirent::d_name is required to be at least NAME_MAX + 1 bytes.
* However, some implementations use the struct hack and make d_name
* 1 byte. Watch for this scenario and adjust accordingly.
*/
if ( sizeof( static_cast< dirent* >( 0 )->d_name ) < NAME_MAX + 1 )
{
return static_cast< dirent* >( ::malloc(sizeof( dirent ) + NAME_MAX + 1) );
}
else
{
return static_cast< dirent* >( ::malloc( sizeof( dirent ) ) );
}
}
void release() return true;
{ }
//printf("directory_iterator::impl::release\n");
::free(e); return false;
e = 0; }
}
// constructor path path
path cPath; get_path() const
{
// printf("directory_iterator::impl::get_path\n");
return e ? (p / e->d_name) : path();
}
/// Platform information file_type
DIR* d; type() const
{
// printf("directory_iterator::impl::type\n");
if(e)
{
switch(e->d_type)
{
case DT_FIFO:
/// Platform information return file_type::fifo;
dirent* e;
directory_entry info;
bool valid_info; // info has been populated case DT_CHR:
};
directory_iterator::directory_iterator() return file_type::character;
: pimpl(new impl)
{
}
directory_iterator::directory_iterator(const path& path_) case DT_DIR:
: pimpl( new impl(path_) )
{ return file_type::directory;
}
case DT_BLK:
// is this right
directory_iterator::directory_iterator(directory_iterator const &src) return file_type::block;
{
//printf("directory_iterator::directory_iterator copy - pimpl[%x] from[%s]\n", pimpl, src->path().c_str()); case DT_REG:
if (pimpl)
return file_type::regular;
case DT_LNK:
return file_type::symlink;
case DT_SOCK:
return file_type::socket;
default:
break;
} // switch
}
return file_type::unknown;
}
const directory_entry&
get_reference()
{
// printf("directory_iterator::impl::get_reference\n");
update();
return info;
}
const directory_entry*
get_pointer()
{
// printf("directory_iterator::impl::get_pointer\n");
update();
return &info;
}
/// Position
size_t pos;
// Path to directory
path p;
private:
void
update()
{
// printf("directory_iterator::impl::update\n");
if(!valid_info && e)
{
const path q = p / e->d_name;
info.assign(q);
valid_info = true;
}
}
static dirent*
acquire()
{
// printf("directory_iterator::impl::acquire\n");
/* dirent::d_name is required to be at least NAME_MAX + 1 bytes.
* However, some implementations use the struct hack and make d_name
* 1 byte. Watch for this scenario and adjust accordingly.
*/
if(sizeof(static_cast< dirent* >(0)->d_name) < NAME_MAX + 1)
{
return static_cast< dirent* >(
::malloc(sizeof(dirent) + NAME_MAX + 1));
}
else
{
return static_cast< dirent* >(::malloc(sizeof(dirent)));
}
}
void
release()
{
// printf("directory_iterator::impl::release\n");
::free(e);
e = 0;
}
// constructor path
path cPath;
/// Platform information
DIR* d;
/// Platform information
dirent* e;
directory_entry info;
bool valid_info; // info has been populated
};
directory_iterator::directory_iterator() : pimpl(new impl)
{ {
//delete pimpl;
} }
pimpl = new impl(src.pimpl->p.c_str());
pimpl->seek(src.pimpl->pos);
}
directory_iterator::~directory_iterator() directory_iterator::directory_iterator(const path& path_)
{ : pimpl(new impl(path_))
delete pimpl; {
} }
directory_iterator::directory_iterator(directory_iterator const &src, int pos) {
//printf("directory_iterator::directory_iterator copy at pos - pimpl[%x] from[%s]\n", pimpl, src->path().c_str());
pimpl = new impl(src.pimpl->p.c_str());
pimpl->seek(pos);
}
bool directory_iterator::operator==(const directory_iterator& i) const
{
// only equal if both are end iterators // is this right
return pimpl->is_end() && i.pimpl->is_end(); directory_iterator::directory_iterator(directory_iterator const& src)
} {
// printf("directory_iterator::directory_iterator copy - pimpl[%x]
// from[%s]\n", pimpl, src->path().c_str());
if(pimpl)
{
// delete pimpl;
}
pimpl = new impl(src.pimpl->p.c_str());
pimpl->seek(src.pimpl->pos);
}
bool directory_iterator::operator!=(const directory_iterator& i) const directory_iterator::~directory_iterator()
{ {
return !( pimpl->is_end() && i.pimpl->is_end() ); delete pimpl;
} }
directory_iterator& directory_iterator::operator++() directory_iterator::directory_iterator(directory_iterator const& src,
{ int pos)
pimpl->next(); {
// printf("directory_iterator::directory_iterator copy at pos - pimpl[%x]
// from[%s]\n", pimpl, src->path().c_str());
pimpl = new impl(src.pimpl->p.c_str());
pimpl->seek(pos);
}
return *this; bool
} directory_iterator::operator==(const directory_iterator& i) const
{
// only equal if both are end iterators
return pimpl->is_end() && i.pimpl->is_end();
}
const directory_entry& directory_iterator::operator*() const bool
{ directory_iterator::operator!=(const directory_iterator& i) const
return pimpl->get_reference(); {
} return !(pimpl->is_end() && i.pimpl->is_end());
}
const directory_entry* directory_iterator::operator->() const directory_iterator&
{ directory_iterator::operator++()
return pimpl->get_pointer(); {
} pimpl->next();
file_type directory_iterator::type() const return *this;
{ }
return pimpl->type();
} const directory_entry& directory_iterator::operator*() const
void directory_iterator::swap(directory_iterator& d)
{
std::swap(pimpl, d.pimpl);
}
// FIXME: this isn't right
directory_iterator directory_iterator::begin() {
return directory_iterator( *this, 0 );
/*
printf("directory_iterator::directory_iterator::begin - start\n");
size_t cur = pimpl->pos; // backup state
printf("directory_iterator::directory_iterator::begin - was at [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
pimpl->rewind();
directory_iterator *ret = new directory_iterator(*this); // copy ourself
pimpl->seek(cur); // restore state
printf("directory_iterator::directory_iterator::begin - end\n");
return *ret;
*/
}
directory_iterator directory_iterator::end() {
//return *(directory_iterator *)endPtr;
//printf("directory_iterator::directory_iterator::end - start\n");
size_t cur = pimpl->pos; // backup state
//printf("directory_iterator::directory_iterator::end - was at [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
// spool to the end
size_t finalPos = pimpl->pos;
while( !pimpl->is_end() )
{ {
if (pimpl->next()) { return pimpl->get_reference();
finalPos = pimpl->pos; }
const directory_entry* directory_iterator::operator->() const
{
return pimpl->get_pointer();
}
file_type
directory_iterator::type() const
{
return pimpl->type();
}
void
directory_iterator::swap(directory_iterator& d)
{
std::swap(pimpl, d.pimpl);
}
// FIXME: this isn't right
directory_iterator
directory_iterator::begin()
{
return directory_iterator(*this, 0);
/*
printf("directory_iterator::directory_iterator::begin - start\n");
size_t cur = pimpl->pos; // backup state
printf("directory_iterator::directory_iterator::begin - was at
[%zu][%s]\n", cur, this->pimpl->get_path().c_str()); pimpl->rewind();
directory_iterator *ret = new directory_iterator(*this); // copy ourself
pimpl->seek(cur); // restore state
printf("directory_iterator::directory_iterator::begin - end\n");
return *ret;
*/
}
directory_iterator
directory_iterator::end()
{
// return *(directory_iterator *)endPtr;
// printf("directory_iterator::directory_iterator::end - start\n");
size_t cur = pimpl->pos; // backup state
// printf("directory_iterator::directory_iterator::end - was at
// [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
// spool to the end
size_t finalPos = pimpl->pos;
while(!pimpl->is_end())
{
if(pimpl->next())
{
finalPos = pimpl->pos;
}
} }
// directory_iterator *ret = new directory_iterator(*this); // copy
// ourself printf("directory_iterator::directory_iterator::end - now at
// [%zu][%s]\n", pimpl->pos, this->pimpl->get_path().c_str());
pimpl->seek(cur); // restore state
return directory_iterator(*this, finalPos);
// printf("directory_iterator::directory_iterator::end - end\n");
// return *ret;
} }
//directory_iterator *ret = new directory_iterator(*this); // copy ourself
//printf("directory_iterator::directory_iterator::end - now at [%zu][%s]\n", pimpl->pos, this->pimpl->get_path().c_str());
pimpl->seek(cur); // restore state
return directory_iterator( *this, finalPos);
//printf("directory_iterator::directory_iterator::end - end\n");
//return *ret;
}
//
// recursive_directory_iterator
//
recursive_directory_iterator::recursive_directory_iterator()
{
}
recursive_directory_iterator::recursive_directory_iterator(const path& p) //
{ // recursive_directory_iterator
descend(p); //
}
recursive_directory_iterator::~recursive_directory_iterator() recursive_directory_iterator::recursive_directory_iterator()
{ {
while ( !stack.empty() ) }
{
ascend();
}
}
bool recursive_directory_iterator::descend(const path& p) recursive_directory_iterator::recursive_directory_iterator(const path& p)
{ {
directory_iterator it(p), end; descend(p);
}
if ( it != end ) recursive_directory_iterator::~recursive_directory_iterator()
{ {
directory_iterator* jt = new directory_iterator(); while(!stack.empty())
jt->swap(it); {
stack.push(jt); ascend();
}
}
return true; bool
} recursive_directory_iterator::descend(const path& p)
{
directory_iterator it(p), end;
return false; if(it != end)
} {
directory_iterator* jt = new directory_iterator();
jt->swap(it);
stack.push(jt);
void recursive_directory_iterator::ascend() return true;
{ }
delete stack.top();
stack.pop();
}
const directory_entry& recursive_directory_iterator::operator*() const return false;
{ }
return *( *stack.top() );
}
const directory_entry* recursive_directory_iterator::operator->() const void
{ recursive_directory_iterator::ascend()
return stack.top()->operator->(); {
} delete stack.top();
stack.pop();
}
recursive_directory_iterator& recursive_directory_iterator::operator++() const directory_entry& recursive_directory_iterator::operator*() const
{ {
if ( stack.top()->type() == file_type::directory ) return *(*stack.top());
{ }
// go to directory's first child (if any)
if ( descend( ( *stack.top() )->path() ) )
{
return *this;
}
}
do
{
// move to sibling
stack.top()->operator++();
directory_iterator end;
if ( *( stack.top() ) != end )
{
return *this;
}
// move to parent
ascend();
}
while ( !stack.empty() );
return *this;
}
bool recursive_directory_iterator::operator==(const recursive_directory_iterator& i) const
{
return stack.empty() && i.stack.empty();
}
bool recursive_directory_iterator::operator!=(const recursive_directory_iterator& i) const const directory_entry* recursive_directory_iterator::operator->() const
{ {
return !( stack.empty() && i.stack.empty() ); return stack.top()->operator->();
} }
recursive_directory_iterator&
recursive_directory_iterator::operator++()
{
if(stack.top()->type() == file_type::directory)
{
// go to directory's first child (if any)
if(descend((*stack.top())->path()))
{
return *this;
}
}
do
{
// move to sibling
stack.top()->operator++();
directory_iterator end;
if(*(stack.top()) != end)
{
return *this;
}
// move to parent
ascend();
} while(!stack.empty());
return *this;
}
bool
recursive_directory_iterator::operator==(
const recursive_directory_iterator& i) const
{
return stack.empty() && i.stack.empty();
}
bool
recursive_directory_iterator::operator!=(
const recursive_directory_iterator& i) const
{
return !(stack.empty() && i.stack.empty());
}
} } // namespace filesystem
} } // namespace cpp17

@ -30,7 +30,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifndef _MSC_VER
#include <unistd.h> #include <unistd.h>
#endif
namespace cpp17 namespace cpp17
{ {

@ -1,281 +1,404 @@
/* Copyright (c) 2015, Pollard Banknote Limited /* Copyright (c) 2015, Pollard Banknote Limited
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without
are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or this list of conditions and the following disclaimer in the documentation
other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without may be used to endorse or promote products derived from this software without
specific prior written permission. specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "filestatus.h" #include "filestatus.h"
#include <iostream> #include <iostream>
#ifndef _MSC_VER
#include <unistd.h> #include <unistd.h>
#endif
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include "path.h" #include "path.h"
namespace #ifdef _MSC_VER
{ #include <Windows.h>
::cpp17::filesystem::file_status from_mode_t(mode_t m) #include <stdint.h>
{ #include <io.h>
::cpp17::filesystem::perms p = static_cast< ::cpp17::filesystem::perms >( m & 0xFFF );
::cpp17::filesystem::file_type t = file_type::unknown;
if ( S_ISREG(m) )
{
t = file_type::regular;
}
else if ( S_ISDIR(m) )
{
t = file_type::directory;
}
else if ( S_ISCHR(m) )
{
t = file_type::character;
}
else if ( S_ISBLK(m) )
{
t = file_type::block;
}
else if ( S_ISFIFO(m) )
{
t = file_type::fifo;
}
#ifndef _WIN32 // these only work on cygnus or msys2!
else if(S_ISLNK(m))
{
t = file_type::symlink;
}
else if ( S_ISSOCK(m) )
{
t = file_type::socket;
}
#endif
return ::cpp17::filesystem::file_status(t, p);
}
}
namespace cpp17
{
namespace filesystem
{
file_status::file_status(const file_status& s)
: t(s.t), p(s.p)
{
}
file_status::file_status(
file_type t_,
perms p_
)
: t(t_), p(p_)
{
}
file_status& file_status::operator=(const file_status& s)
{
t = s.t;
p = s.p;
return *this; typedef unsigned short mode_t;
} typedef uint32_t id_t; /* Internal uids/gids are 32-bits */
file_type file_status::type() const
{
return t;
}
void file_status::type(file_type t_) typedef SSIZE_T ssize_t;
{ #ifndef _OFF_T_DEFINED
t = t_; typedef DWORD64 off_t;
} #endif
typedef uint32_t uid_t; /* [???] user IDs */
perms file_status::permissions() const
{
return p;
}
void file_status::permissions(perms p_)
{
p = p_;
}
std::ostream& operator<<(
std::ostream& os,
const file_status& fs
)
{
os << fs.type() << "; " << fs.permissions();
return os; #ifndef S_IFIFO
} #define S_IFIFO 0010000 /* [XSI] named pipe (fifo) */
#endif
file_status status(const path& path_) #ifndef S_IFBLK
{ #define S_IFBLK 0060000 /* [XSI] block special */
if ( !path_.empty() ) #endif
{
struct stat st;
if ( ::stat(path_.c_str(), &st) == 0 ) #ifndef S_IFLNK
{ #define S_IFLNK 0120000 /* [XSI] symbolic link */
return from_mode_t(st.st_mode); #endif
}
}
return file_status(); #ifndef S_IFSOCK
} #define S_IFSOCK 0140000 /* [XSI] socket */
#endif
file_status symlink_status(const path& path_) #ifndef S_ISBLK
{ #define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block special */
if ( !path_.empty() )
{
struct stat st;
#ifndef _WIN32
if(::lstat(path_.c_str(), &st) == 0)
#else
if(::stat(path_.c_str(), &st) == 0)
#endif #endif
{
return from_mode_t(st.st_mode);
}
}
return file_status();
}
bool status_known(file_status s)
{
return s.type() != file_type::none;
}
bool exists(file_status s) #ifndef S_ISCHR
{ #define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* char special */
return status_known(s) && s.type() != file_type::not_found; #endif
}
bool exists(const path& p, std::error_code& ec) #ifndef S_ISDIR
{ #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */
return exists( status(p) ); #endif
}
bool is_block_file(file_status s) #ifndef S_ISFIFO
{ #define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo or socket */
return s.type() == file_type::block; #endif
}
bool is_block_file(const path& p) #ifndef S_ISREG
{ #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* regular file */
return is_block_file( status(p) ); #endif
}
bool is_character_file(file_status s) #ifndef S_ISLNK
{ #define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */
return s.type() == file_type::character; #endif
}
bool is_character_file(const path& p) #ifndef S_ISSOCK
{ #define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */
return is_character_file( status(p) ); #endif
}
bool is_fifo(file_status s) #ifndef makedev
{ #define makedev(x, y) ((dev_t)(((x) << 24) | (y)))
return s.type() == file_type::fifo; #endif
}
bool is_fifo(const path& p) #ifndef DT_UNKNOWN
{ #define DT_UNKNOWN 0
return is_fifo( status(p) ); #endif
}
bool is_other(file_status s) #ifndef DT_FIFO
{ #define DT_FIFO 1
return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s); #endif
}
bool is_other(const path& p) #ifndef DT_CHR
{ #define DT_CHR 2
return is_other( status(p) ); #endif
}
bool is_regular_file(file_status s) #ifndef DT_DIR
{ #define DT_DIR 4
return s.type() == file_type::regular; #endif
}
bool is_regular_file(const path& p) #ifndef DT_BLK
{ #define DT_BLK 6
return is_regular_file( status(p) ); #endif
}
bool is_socket(file_status s) #ifndef DT_REG
{ #define DT_REG 8
return s.type() == file_type::socket; #endif
}
bool is_socket(const path& p) #ifndef DT_LNK
{ #define DT_LNK 10
return is_socket( status(p) ); #endif
}
bool is_symlink(file_status s) #ifndef DT_SOCK
{ #define DT_SOCK 12
return s.type() == file_type::symlink; #endif
}
bool is_symlink(const path& p) #ifndef DT_WHT
{ #define DT_WHT 14
return is_symlink( status(p) ); #endif
} #endif
bool is_directory(file_status s) namespace
{ {
return s.type() == file_type::directory; ::cpp17::filesystem::file_status
} from_mode_t(mode_t m)
{
::cpp17::filesystem::perms p =
static_cast<::cpp17::filesystem::perms >(m & 0xFFF);
::cpp17::filesystem::file_type t = file_type::unknown;
if(S_ISREG(m))
{
t = file_type::regular;
}
else if(S_ISDIR(m))
{
t = file_type::directory;
}
else if(S_ISCHR(m))
{
t = file_type::character;
}
else if(S_ISBLK(m))
{
t = file_type::block;
}
else if(S_ISFIFO(m))
{
t = file_type::fifo;
}
#ifndef _WIN32 // these only work on cygnus or msys2!
else if(S_ISLNK(m))
{
t = file_type::symlink;
}
else if(S_ISSOCK(m))
{
t = file_type::socket;
}
#endif
return ::cpp17::filesystem::file_status(t, p);
}
bool is_directory(const path& p) } // namespace
{
return is_directory( status(p) );
}
std::size_t file_size(const path& p) namespace cpp17
{ {
if ( !p.empty() ) namespace filesystem
{ {
struct stat st; file_status::file_status(const file_status& s) : t(s.t), p(s.p)
{
if ( ::stat(p.c_str(), &st) == 0 ) }
{
return st.st_size; file_status::file_status(file_type t_, perms p_) : t(t_), p(p_)
} {
} }
return std::size_t(-1); file_status&
} file_status::operator=(const file_status& s)
} {
} t = s.t;
p = s.p;
return *this;
}
file_type
file_status::type() const
{
return t;
}
void
file_status::type(file_type t_)
{
t = t_;
}
perms
file_status::permissions() const
{
return p;
}
void
file_status::permissions(perms p_)
{
p = p_;
}
std::ostream&
operator<<(std::ostream& os, const file_status& fs)
{
os << fs.type() << "; " << fs.permissions();
return os;
}
file_status
status(const path& path_)
{
if(!path_.empty())
{
struct stat st;
if(::stat(path_.c_str(), &st) == 0)
{
return from_mode_t(st.st_mode);
}
}
return file_status();
}
file_status
symlink_status(const path& path_)
{
if(!path_.empty())
{
struct stat st;
#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();
}
bool
status_known(file_status s)
{
return s.type() != file_type::none;
}
bool
exists(file_status s)
{
return status_known(s) && s.type() != file_type::not_found;
}
bool
exists(const path& p, std::error_code& ec)
{
return exists(status(p));
}
bool
is_block_file(file_status s)
{
return s.type() == file_type::block;
}
bool
is_block_file(const path& p)
{
return is_block_file(status(p));
}
bool
is_character_file(file_status s)
{
return s.type() == file_type::character;
}
bool
is_character_file(const path& p)
{
return is_character_file(status(p));
}
bool
is_fifo(file_status s)
{
return s.type() == file_type::fifo;
}
bool
is_fifo(const path& p)
{
return is_fifo(status(p));
}
bool
is_other(file_status s)
{
return exists(s) && !is_regular_file(s) && !is_directory(s)
&& !is_symlink(s);
}
bool
is_other(const path& p)
{
return is_other(status(p));
}
bool
is_regular_file(file_status s)
{
return s.type() == file_type::regular;
}
bool
is_regular_file(const path& p)
{
return is_regular_file(status(p));
}
bool
is_socket(file_status s)
{
return s.type() == file_type::socket;
}
bool
is_socket(const path& p)
{
return is_socket(status(p));
}
bool
is_symlink(file_status s)
{
return s.type() == file_type::symlink;
}
bool
is_symlink(const path& p)
{
return is_symlink(status(p));
}
bool
is_directory(file_status s)
{
return s.type() == file_type::directory;
}
bool
is_directory(const path& p)
{
return is_directory(status(p));
}
std::size_t
file_size(const path& p)
{
if(!p.empty())
{
struct stat st;
if(::stat(p.c_str(), &st) == 0)
{
return st.st_size;
}
}
return std::size_t(-1);
}
} // namespace filesystem
} // namespace cpp17

File diff suppressed because it is too large Load Diff

@ -72,7 +72,7 @@ tuntap_sys_start(struct device *dev, int mode, int tun)
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'"); tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
return -1; return -1;
} }
// ifr.ifr_flags |= IFF_NO_PI; ifr.ifr_flags |= IFF_NO_PI;
if(tun < 0) if(tun < 0)
{ {

@ -135,7 +135,6 @@ tuntap_sys_start(struct device *dev, int mode, int tun) {
"Can't get link-layer address"); "Can't get link-layer address");
return fd; return fd;
} }
(void)memcpy(dev->hwaddr, &addr, ETHER_ADDR_LEN);
} }
return fd; return fd;
} }

@ -21,353 +21,427 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <strsafe.h> /*#include <strsafe.h>*/
#include "tuntap.h" #include "tuntap.h"
// DDK macros
#define CTL_CODE(DeviceType, Function, Method, Access) \
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
#define FILE_DEVICE_UNKNOWN 0x00000022
#define FILE_ANY_ACCESS 0x00000000
#define METHOD_BUFFERED 0
/* From OpenVPN tap driver, common.h */ /* From OpenVPN tap driver, common.h */
#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) #define TAP_CONTROL_CODE(request, method) \
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE(2, METHOD_BUFFERED)
#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) #define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE(3, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) #define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE(4, METHOD_BUFFERED)
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE(5, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(6, METHOD_BUFFERED)
#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) #define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE(7, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) #define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE(8, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE (10, METHOD_BUFFERED) #define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE(9, METHOD_BUFFERED)
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE(10, METHOD_BUFFERED)
/* Windows registry crap */ /* Windows registry crap */
#define MAX_KEY_LENGTH 255 #define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383 #define MAX_VALUE_NAME 16383
#define NETWORK_ADAPTERS "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" #define NETWORK_ADAPTERS \
"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-" \
"08002BE10318}"
#define ETHER_ADDR_LEN 6
/* From OpenVPN tap driver, proto.h */ /* From OpenVPN tap driver, proto.h */
typedef unsigned long IPADDR; typedef unsigned long IPADDR;
/* This one is from Fabien Pichot, in the tNETacle source code */ /* This one is from Fabien Pichot, in the tNETacle source code */
static LPWSTR static LPWSTR
formated_error(LPWSTR pMessage, DWORD m, ...) { formated_error(LPWSTR pMessage, DWORD m, ...)
LPWSTR pBuffer = NULL; {
LPWSTR pBuffer = NULL;
va_list args = NULL; va_list args = NULL;
va_start(args, pMessage); va_start(args, pMessage);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
FORMAT_MESSAGE_ALLOCATE_BUFFER, pMessage, m, 0, (LPSTR)&pBuffer, 0, &args);
pMessage,
m,
0,
(LPSTR)&pBuffer,
0,
&args);
va_end(args); va_end(args);
return pBuffer; return pBuffer;
} }
/* TODO: Rework to be more generic and allow arbitrary key modification (MTU and stuff) */ /* TODO: Rework to be more generic and allow arbitrary key modification (MTU and
* stuff) */
static char * static char *
reg_query(char *key_name) { reg_query(char *key_name)
HKEY adapters, adapter; {
DWORD i, ret, len; HKEY adapters, adapter;
char *deviceid = NULL; DWORD i, ret, len;
DWORD sub_keys = 0; char *deviceid = NULL;
DWORD sub_keys = 0;
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key_name), 0, KEY_READ, &adapters);
if (ret != ERROR_SUCCESS) { ret =
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret)); RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key_name), 0, KEY_READ, &adapters);
return NULL; if(ret != ERROR_SUCCESS)
} {
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
ret = RegQueryInfoKey(adapters, NULL, NULL, NULL, &sub_keys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); return NULL;
if (ret != ERROR_SUCCESS) { }
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
return NULL; ret = RegQueryInfoKey(adapters, NULL, NULL, NULL, &sub_keys, NULL, NULL, NULL,
} NULL, NULL, NULL, NULL);
if(ret != ERROR_SUCCESS)
if (sub_keys <= 0) { {
tuntap_log(TUNTAP_LOG_DEBUG, "Wrong registry key"); tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
return NULL; return NULL;
} }
/* Walk througt all adapters */ if(sub_keys <= 0)
for (i = 0; i < sub_keys; i++) { {
char new_key[MAX_KEY_LENGTH]; tuntap_log(TUNTAP_LOG_DEBUG, "Wrong registry key");
char data[256]; return NULL;
TCHAR key[MAX_KEY_LENGTH]; }
DWORD keylen = MAX_KEY_LENGTH;
/* Walk througt all adapters */
/* Get the adapter key name */ for(i = 0; i < sub_keys; i++)
ret = RegEnumKeyEx(adapters, i, key, &keylen, NULL, NULL, NULL, NULL); {
if (ret != ERROR_SUCCESS) { char new_key[MAX_KEY_LENGTH];
continue; char data[256];
} TCHAR key[MAX_KEY_LENGTH];
DWORD keylen = MAX_KEY_LENGTH;
/* Append it to NETWORK_ADAPTERS and open it */
snprintf(new_key, sizeof new_key, "%s\\%s", key_name, key); /* Get the adapter key name */
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(new_key), 0, KEY_READ, &adapter); ret = RegEnumKeyEx(adapters, i, key, &keylen, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) { if(ret != ERROR_SUCCESS)
continue; {
} continue;
}
/* Check its values */
len = sizeof data; /* Append it to NETWORK_ADAPTERS and open it */
ret = RegQueryValueEx(adapter, "ComponentId", NULL, NULL, (LPBYTE)data, &len); snprintf(new_key, sizeof new_key, "%s\\%s", key_name, key);
if (ret != ERROR_SUCCESS) { ret =
/* This value doesn't exist in this adaptater tree */ RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(new_key), 0, KEY_READ, &adapter);
goto clean; if(ret != ERROR_SUCCESS)
} {
/* If its a tap adapter, its all good */ continue;
if (strncmp(data, "tap", 3) == 0) { }
DWORD type;
/* Check its values */
len = sizeof data; len = sizeof data;
ret = RegQueryValueEx(adapter, "NetCfgInstanceId", NULL, &type, (LPBYTE)data, &len); ret =
if (ret != ERROR_SUCCESS) { RegQueryValueEx(adapter, "ComponentId", NULL, NULL, (LPBYTE)data, &len);
tuntap_log(TUNTAP_LOG_INFO, (const char *)formated_error(L"%1", ret)); if(ret != ERROR_SUCCESS)
goto clean; {
} /* This value doesn't exist in this adaptater tree */
deviceid = strdup(data); goto clean;
break; }
} /* If its a tap adapter, its all good */
clean: if(strncmp(data, "tap", 3) == 0)
RegCloseKey(adapter); {
} DWORD type;
RegCloseKey(adapters);
return deviceid; len = sizeof data;
ret = RegQueryValueEx(adapter, "NetCfgInstanceId", NULL, &type,
(LPBYTE)data, &len);
if(ret != ERROR_SUCCESS)
{
tuntap_log(TUNTAP_LOG_INFO, (const char *)formated_error(L"%1", ret));
goto clean;
}
deviceid = strdup(data);
break;
}
clean:
RegCloseKey(adapter);
}
RegCloseKey(adapters);
return deviceid;
} }
void void
tuntap_sys_destroy(struct device *dev) { tuntap_sys_destroy(struct device *dev)
(void)dev; {
return; (void)dev;
return;
} }
int int
tuntap_start(struct device *dev, int mode, int tun) { tuntap_start(struct device *dev, int mode, int tun)
HANDLE tun_fd; {
char *deviceid; HANDLE tun_fd;
char buf[60]; char *deviceid;
char buf[60];
/* Don't re-initialise a previously started device */
if (dev->tun_fd != TUNFD_INVALID_VALUE) { /* Don't re-initialise a previously started device */
return -1; if(dev->tun_fd != TUNFD_INVALID_VALUE)
} {
return -1;
/* Shift the persistence bit */ }
if (mode & TUNTAP_MODE_PERSIST) {
mode &= ~TUNTAP_MODE_PERSIST; /* Shift the persistence bit */
} if(mode & TUNTAP_MODE_PERSIST)
{
if (mode == TUNTAP_MODE_TUNNEL) { mode &= ~TUNTAP_MODE_PERSIST;
tuntap_log(TUNTAP_LOG_NOTICE, "Layer 3 tunneling is not implemented"); }
return -1;
} if(mode == TUNTAP_MODE_TUNNEL)
else if (mode != TUNTAP_MODE_ETHERNET) { {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'"); tuntap_log(TUNTAP_LOG_NOTICE, "Layer 3 tunneling is not implemented");
return -1; return -1;
} }
else if(mode != TUNTAP_MODE_ETHERNET)
deviceid = reg_query(NETWORK_ADAPTERS); {
snprintf(buf, sizeof buf, "\\\\.\\Global\\%s.tap", deviceid); tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
tun_fd = CreateFile(buf, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED, 0); return -1;
if (tun_fd == TUNFD_INVALID_VALUE) { }
int errcode = GetLastError();
deviceid = reg_query(NETWORK_ADAPTERS);
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); snprintf(buf, sizeof buf, "\\\\.\\Global\\%s.tap", deviceid);
return -1; tun_fd = CreateFile(buf, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING,
} FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
if(tun_fd == TUNFD_INVALID_VALUE)
dev->tun_fd = tun_fd; {
return 0; int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
dev->tun_fd = tun_fd;
return 0;
} }
void void
tuntap_release(struct device *dev) { tuntap_release(struct device *dev)
(void)CloseHandle(dev->tun_fd); {
free(dev); (void)CloseHandle(dev->tun_fd);
free(dev);
} }
char * char *
tuntap_get_hwaddr(struct device *dev) { tuntap_get_hwaddr(struct device *dev)
static unsigned char hwaddr[ETHER_ADDR_LEN]; {
DWORD len; static unsigned char hwaddr[ETHER_ADDR_LEN];
DWORD len;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MAC, &hwaddr, sizeof(hwaddr), &hwaddr, sizeof(hwaddr), &len, NULL) == 0) {
int errcode = GetLastError(); if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MAC, &hwaddr, sizeof(hwaddr),
&hwaddr, sizeof(hwaddr), &len, NULL)
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); == 0)
return NULL; {
} else { int errcode = GetLastError();
char buf[128];
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
(void)_snprintf_s(buf, sizeof buf, sizeof buf, "MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", return NULL;
hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]); }
tuntap_log(TUNTAP_LOG_DEBUG, buf); else
} {
return (char *)hwaddr; char buf[128];
(void)_snprintf(buf, sizeof buf,
"MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", hwaddr[0],
hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
tuntap_log(TUNTAP_LOG_DEBUG, buf);
}
return (char *)hwaddr;
} }
int int
tuntap_set_hwaddr(struct device *dev, const char *hwaddr) { tuntap_set_hwaddr(struct device *dev, const char *hwaddr)
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_hwaddr()"); {
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_hwaddr()");
return -1;
} }
static int static int
tuntap_sys_set_updown(struct device *dev, ULONG flag) { tuntap_sys_set_updown(struct device *dev, ULONG flag)
DWORD len; {
DWORD len;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_SET_MEDIA_STATUS, &flag, sizeof(flag), &flag, sizeof(flag), &len, NULL) == 0) {
int errcode = GetLastError(); if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_SET_MEDIA_STATUS, &flag,
sizeof(flag), &flag, sizeof(flag), &len, NULL)
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); == 0)
return -1; {
} else { int errcode = GetLastError();
char buf[32];
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
(void)_snprintf_s(buf, sizeof buf, sizeof buf, "Status: %s", flag ? "Up" : "Down"); return -1;
tuntap_log(TUNTAP_LOG_DEBUG, buf); }
return 0; else
} {
char buf[32];
(void)_snprintf(buf, sizeof buf, "Status: %s",
flag ? "Up" : "Down");
tuntap_log(TUNTAP_LOG_DEBUG, buf);
return 0;
}
} }
int int
tuntap_up(struct device *dev) { tuntap_up(struct device *dev)
ULONG flag; {
ULONG flag;
flag = 1; flag = 1;
return tuntap_sys_set_updown(dev, flag); return tuntap_sys_set_updown(dev, flag);
} }
int int
tuntap_down(struct device *dev) { tuntap_down(struct device *dev)
ULONG flag; {
ULONG flag;
flag = 0; flag = 0;
return tuntap_sys_set_updown(dev, flag); return tuntap_sys_set_updown(dev, flag);
} }
int int
tuntap_get_mtu(struct device *dev) { tuntap_get_mtu(struct device *dev)
ULONG mtu; {
DWORD len; ULONG mtu;
DWORD len;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MTU, &mtu, sizeof(mtu), &mtu, sizeof(mtu), &len, NULL) == 0) {
int errcode = GetLastError(); if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MTU, &mtu, sizeof(mtu), &mtu,
sizeof(mtu), &len, NULL)
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); == 0)
return -1; {
} int errcode = GetLastError();
return 0;
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
return 0;
} }
int int
tuntap_set_mtu(struct device *dev, int mtu) { tuntap_set_mtu(struct device *dev, int mtu)
(void)dev; {
(void)mtu; (void)dev;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_mtu()"); (void)mtu;
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_mtu()");
return -1;
} }
int int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask) { tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask)
IPADDR psock[4]; {
DWORD len; IPADDR psock[4];
DWORD len;
/* Address + Netmask */
psock[0] = s->S_un.S_addr; /* Address + Netmask */
psock[1] = mask; psock[0] = s->S_un.S_addr;
/* DHCP server address (We don't want it) */ psock[1] = mask;
psock[2] = 0; /* DHCP server address (We don't want it) */
/* DHCP lease time */ psock[2] = 0;
psock[3] = 0; /* DHCP lease time */
psock[3] = 0;
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, &psock, sizeof(psock), &psock, sizeof(psock), &len, NULL) == 0) {
int errcode = GetLastError(); if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, &psock,
sizeof(psock), &psock, sizeof(psock), &len, NULL)
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); == 0)
return -1; {
} int errcode = GetLastError();
return 0;
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
return 0;
} }
int int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s, uint32_t mask) { tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s, uint32_t mask)
(void)dev; {
(void)s; (void)dev;
(void)mask; (void)s;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_sys_set_ipv6()"); (void)mask;
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_sys_set_ipv6()");
return -1;
} }
int int
tuntap_read(struct device *dev, void *buf, size_t size) { tuntap_read(struct device *dev, void *buf, size_t size)
DWORD len; {
DWORD len;
if (ReadFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0) { if(ReadFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0)
int errcode = GetLastError(); {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1; return -1;
} }
return 0; return 0;
} }
int int
tuntap_write(struct device *dev, void *buf, size_t size) { tuntap_write(struct device *dev, void *buf, size_t size)
DWORD len; {
DWORD len;
if (WriteFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0) { if(WriteFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0)
int errcode = GetLastError(); {
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1; return -1;
} }
return 0; return 0;
} }
int int
tuntap_get_readable(struct device *dev) { tuntap_get_readable(struct device *dev)
(void)dev; {
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_get_readable()"); (void)dev;
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_get_readable()");
return -1;
} }
int int
tuntap_set_nonblocking(struct device *dev, int set) { tuntap_set_nonblocking(struct device *dev, int set)
(void)dev; {
(void)set; (void)dev;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_nonblocking()"); (void)set;
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_nonblocking()");
return -1;
} }
int int
tuntap_set_debug(struct device *dev, int set) { tuntap_set_debug(struct device *dev, int set)
(void)dev; {
(void)set; (void)dev;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_debug()"); (void)set;
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_debug()");
return -1;
} }
int int
tuntap_set_descr(struct device *dev, const char *descr) { tuntap_set_descr(struct device *dev, const char *descr)
(void)dev; {
(void)descr; (void)dev;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_descr()"); (void)descr;
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_descr()");
return -1;
} }
int int
tuntap_set_ifname(struct device *dev, const char *name) { tuntap_set_ifname(struct device *dev, const char *name)
/* TODO: Check Windows API to know how to rename an interface */ {
(void)dev; /* TODO: Check Windows API to know how to rename an interface */
(void)name; (void)dev;
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_ifname()"); (void)name;
return -1; tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_ifname()");
return -1;
} }

@ -31,6 +31,12 @@
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <wspiapi.h> #include <wspiapi.h>
#ifndef _MSC_VER
extern "C" int
inet_pton(int af, const char *src, void *dst);
extern "C" const char *
inet_ntop(int af, const void *src, char *dst, size_t size);
#endif
#else #else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>

Loading…
Cancel
Save