tun code refactor (#1495)
* partial tun code refactor * take out the trash * move vpn platform code into llarp/vpn/platform.cpp * fix hive build * fix win32 * fix memory leak on win32 * reduce cpu use * make macos compile * win32 patches: * use wepoll for zmq * use all cores on windows iocp read loop * fix zmq patch for windows * clean up cmake for win32 * add uninstall before reinstall option to win32 installer * more ipv6 stuff * make it compile * fix up route poker * remove an unneeded code block in macos wtf * always use call to system * fix route poker behavior on macos * disable ipv6 on windows for now * cpu perf improvement: * colease calls to Router::PumpLL to 1 per event loop wakeup * set up THEN add addresses * emulate proactor event loop on win32 * remove excessively verbose error message * fix issue #1499 * exclude uv_poll from win32 so that it can start up * update logtag to include directory * create minidump on windows if there was a crash * make windows happy * use dmp suffix on minidump files * typo fix * address feedback from jason * use PROJECT_SOURCE_DIR instead of CMAKE_SOURCE_DIR * quote $@ in apply-patches in case path has spaces in it * address feedback from tom * remove llarp/ev/pipe * add comments for clairification * make event loop queue size constant namedstable
parent
029b6db364
commit
49b9ad7197
|
@ -23,7 +23,7 @@ set(RELEASE_MOTTO "Proof of soon" CACHE STRING "Release motto")
|
|||
add_definitions(-DLLARP_VERSION_MAJOR=${lokinet_VERSION_MAJOR})
|
||||
add_definitions(-DLLARP_VERSION_MINOR=${lokinet_VERSION_MINOR})
|
||||
add_definitions(-DLLARP_VERSION_PATCH=${lokinet_VERSION_PATCH})
|
||||
if(RELEASE_MOTTO)
|
||||
if(RELEASE_MOTTO AND CMAKE_BUILD_TYPE MATCHES "[Rr][Ee][Ll][Ee][Aa][Ss][Ee]")
|
||||
add_definitions(-DLLARP_RELEASE_MOTTO="${RELEASE_MOTTO}")
|
||||
endif()
|
||||
|
||||
|
@ -329,8 +329,6 @@ add_subdirectory(external/date EXCLUDE_FROM_ALL)
|
|||
|
||||
include_directories(SYSTEM external/sqlite_orm/include)
|
||||
|
||||
add_subdirectory(vendor)
|
||||
|
||||
if(ANDROID)
|
||||
target_link_libraries(base_libs INTERFACE log)
|
||||
target_compile_definitions(base_libs INTERFACE ANDROID)
|
||||
|
|
|
@ -259,9 +259,16 @@ build_external(sqlite3)
|
|||
add_static_target(sqlite3 sqlite3_external libsqlite3.a)
|
||||
|
||||
|
||||
if(ZMQ_VERSION VERSION_LESS 4.3.4 AND CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw)
|
||||
if(ARCH_TRIPLET MATCHES mingw)
|
||||
set(zmq_extra --with-poller=wepoll)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw)
|
||||
set(zmq_patch
|
||||
PATCH_COMMAND patch -p1 -i ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-closesocket.patch)
|
||||
PATCH_COMMAND ${PROJECT_SOURCE_DIR}/contrib/apply-patches.sh ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-wepoll.patch)
|
||||
if(ZMQ_VERSION VERSION_LESS 4.3.4)
|
||||
set(zmq_patch ${zmq_patch} ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-closesocket.patch)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
build_external(zmq
|
||||
|
@ -269,7 +276,7 @@ build_external(zmq
|
|||
${zmq_patch}
|
||||
CONFIGURE_COMMAND ./configure ${cross_host} --prefix=${DEPS_DESTDIR} --enable-static --disable-shared
|
||||
--disable-curve-keygen --enable-curve --disable-drafts --disable-libunwind --with-libsodium
|
||||
--without-pgm --without-norm --without-vmci --without-docs --with-pic --disable-Werror
|
||||
--without-pgm --without-norm --without-vmci --without-docs --with-pic --disable-Werror ${zmq_extra}
|
||||
"CC=${deps_cc}" "CXX=${deps_cxx}" "CFLAGS=${deps_CFLAGS} -fstack-protector" "CXXFLAGS=${deps_CXXFLAGS} -fstack-protector"
|
||||
"sodium_CFLAGS=-I${DEPS_DESTDIR}/include" "sodium_LIBS=-L${DEPS_DESTDIR}/lib -lsodium"
|
||||
)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
function(add_log_tag target)
|
||||
get_target_property(TARGET_SRCS ${target} SOURCES)
|
||||
foreach(F ${TARGET_SRCS})
|
||||
set_property(SOURCE ${F} APPEND PROPERTY COMPILE_DEFINITIONS LOG_TAG=\"${F}\")
|
||||
get_filename_component(fpath "${F}" ABSOLUTE)
|
||||
string(REPLACE "${PROJECT_SOURCE_DIR}/" "" logtag "${fpath}")
|
||||
set_property(SOURCE ${F} APPEND PROPERTY COMPILE_DEFINITIONS LOG_TAG=\"${logtag}\")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
set(GUI_ZIP_URL "https://oxen.rocks/loki-project/loki-network-control-panel/master/lokinet-gui-windows-32bit-v0.3.5.zip")
|
||||
set(GUI_ZIP_HASH SHA256=fcb1d78f7d6eecb440d05a034dd7e60ae506275af5b0f600b416bb1a896f32aa)
|
||||
if(NOT GUI_ZIP_URL)
|
||||
set(GUI_ZIP_URL "https://oxen.rocks/loki-project/loki-network-control-panel/master/lokinet-gui-windows-32bit-v0.3.5.zip")
|
||||
set(GUI_ZIP_HASH_OPTS EXPECTED_HASH SHA256=fcb1d78f7d6eecb440d05a034dd7e60ae506275af5b0f600b416bb1a896f32aa)
|
||||
endif()
|
||||
|
||||
set(TUNTAP_URL "https://build.openvpn.net/downloads/releases/latest/tap-windows-latest-stable.exe")
|
||||
set(TUNTAP_EXE "${CMAKE_BINARY_DIR}/tuntap-install.exe")
|
||||
set(BOOTSTRAP_URL "https://seed.lokinet.org/lokinet.signed")
|
||||
|
@ -16,7 +19,7 @@ file(DOWNLOAD
|
|||
file(DOWNLOAD
|
||||
${GUI_ZIP_URL}
|
||||
${CMAKE_BINARY_DIR}/lokinet-gui.zip
|
||||
EXPECTED_HASH ${GUI_ZIP_HASH})
|
||||
${GUI_ZIP_HASH_OPTS})
|
||||
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf ${CMAKE_BINARY_DIR}/lokinet-gui.zip
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
@ -28,6 +31,7 @@ install(FILES ${BOOTSTRAP_FILE} DESTINATION share)
|
|||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Lokinet")
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/win32-setup/lokinet.ico")
|
||||
set(CPACK_NSIS_DEFINES "RequestExecutionLevel admin")
|
||||
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
|
||||
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '$INSTDIR\\\\bin\\\\tuntap-install.exe /S'\\nExecWait '$INSTDIR\\\\bin\\\\lokinet.exe --install'\\nExecWait '$INSTDIR\\\\bin\\\\lokinet.exe -g C:\\\\ProgramData\\\\lokinet\\\\lokinet.ini'\\nCopyFiles '$INSTDIR\\\\share\\\\bootstrap.signed' C:\\\\ProgramData\\\\lokinet\\\\bootstrap.signed")
|
||||
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "ExecWait 'net stop lokinet'\\nExecWait 'taskkill /f /t /im lokinet-gui.exe'\\nExecWait '$INSTDIR\\\\bin\\\\lokinet.exe --remove'\\nRMDir /r /REBOOTOK C:\\\\ProgramData\\\\lokinet")
|
||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
for f in "$@" ; do
|
||||
patch -p1 -i "$f"
|
||||
done
|
|
@ -0,0 +1,16 @@
|
|||
diff --git a/external/wepoll/wepoll.c b/external/wepoll/wepoll.c
|
||||
--- a/external/wepoll/wepoll.c
|
||||
+++ b/external/wepoll/wepoll.c
|
||||
@@ -140,9 +140,9 @@
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
-#include <WS2tcpip.h>
|
||||
-#include <WinSock2.h>
|
||||
-#include <Windows.h>
|
||||
+#include <ws2tcpip.h>
|
||||
+#include <winsock2.h>
|
||||
+#include <windows.h>
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(pop)
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/bash
|
||||
mkdir -p build-windows
|
||||
cd build-windows
|
||||
cmake -G Ninja -DCMAKE_CROSSCOMPILE=ON -DCMAKE_EXE_LINKER_FLAGS=-fstack-protector -DLIBUV_ROOT=$PWD/../external/libuv -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always -DCMAKE_TOOLCHAIN_FILE=../contrib/cross/mingw64.cmake -DBUILD_STATIC_DEPS=ON -DBUILD_PACKAGE=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF -DWITH_TESTS=OFF -DNATIVE_BUILD=OFF -DSTATIC_LINK=ON -DWITH_SYSTEMD=OFF -DFORCE_LOKIMQ_SUBMODULE=ON -DSUBMODULE_CHECK=OFF -DWITH_LTO=OFF ..
|
||||
cmake -G Ninja -DCMAKE_CROSSCOMPILE=ON -DCMAKE_EXE_LINKER_FLAGS=-fstack-protector -DLIBUV_ROOT=$PWD/../external/libuv -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always -DCMAKE_TOOLCHAIN_FILE=../contrib/cross/mingw64.cmake -DBUILD_STATIC_DEPS=ON -DBUILD_PACKAGE=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF -DWITH_TESTS=OFF -DNATIVE_BUILD=OFF -DSTATIC_LINK=ON -DWITH_SYSTEMD=OFF -DFORCE_LOKIMQ_SUBMODULE=ON -DSUBMODULE_CHECK=OFF -DWITH_LTO=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_CROSSCOMPLING=ON ..
|
||||
ninja package
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#include <util/str.hpp>
|
||||
#include <util/thread/logic.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <dbghelp.h>
|
||||
#endif
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <cxxopts.hpp>
|
||||
|
@ -329,6 +333,45 @@ class WindowsServiceStopped
|
|||
TellWindowsServiceStopped();
|
||||
}
|
||||
};
|
||||
|
||||
/// minidump generation for windows jizz
|
||||
/// will make a coredump when there is an unhandled exception
|
||||
LONG
|
||||
GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "C:\\ProgramData\\lokinet\\crash-" << llarp::time_now_ms().count() << ".dmp";
|
||||
const std::string fname = ss.str();
|
||||
HANDLE hDumpFile;
|
||||
SYSTEMTIME stLocalTime;
|
||||
GetLocalTime(&stLocalTime);
|
||||
MINIDUMP_EXCEPTION_INFORMATION ExpParam;
|
||||
|
||||
hDumpFile = CreateFile(
|
||||
fname.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
||||
0,
|
||||
CREATE_ALWAYS,
|
||||
0,
|
||||
0);
|
||||
|
||||
ExpParam.ThreadId = GetCurrentThreadId();
|
||||
ExpParam.ExceptionPointers = pExceptionPointers;
|
||||
ExpParam.ClientPointers = TRUE;
|
||||
|
||||
MiniDumpWriteDump(
|
||||
GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
hDumpFile,
|
||||
MiniDumpWithDataSegs,
|
||||
&ExpParam,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -521,6 +564,10 @@ lokinet_main(int argc, char* argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
SetUnhandledExceptionFilter(&GenerateDump);
|
||||
#endif
|
||||
|
||||
std::thread main_thread{std::bind(&run_main_context, configFile, opts)};
|
||||
auto ftr = exit_code.get_future();
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <util/fs.hpp>
|
||||
#include <util/types.hpp>
|
||||
#include <ev/ev.hpp>
|
||||
#include <ev/vpn.hpp>
|
||||
#include <nodedb.hpp>
|
||||
#include <crypto/crypto.hpp>
|
||||
#include <router/abstractrouter.hpp>
|
||||
|
@ -95,6 +96,10 @@ namespace llarp
|
|||
virtual std::unique_ptr<AbstractRouter>
|
||||
makeRouter(llarp_ev_loop_ptr __netloop, std::shared_ptr<Logic> logic);
|
||||
|
||||
/// create the vpn platform for use in creating network interfaces
|
||||
virtual std::unique_ptr<llarp::vpn::Platform>
|
||||
makeVPNPlatform();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Config> config = nullptr;
|
||||
|
||||
|
|
267
include/tuntap.h
267
include/tuntap.h
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Tristan Le Guern <leguern AT medu DOT se>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* Copyright (c) 2016 Mahdi Mokhtari <mokhi64@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined Windows
|
||||
#else /* Unix */
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#if !defined Windows /* Unix :) */
|
||||
#if !defined Linux
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#if defined(Linux)
|
||||
// Once we drop xenial support we can just include net/if.h on linux
|
||||
#include <linux/if.h>
|
||||
#else
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
#if defined Linux
|
||||
#include <netinet/in.h>
|
||||
#elif defined(iOS)
|
||||
#include <net/ethernet.h>
|
||||
#else
|
||||
#include <netinet/if_ether.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef LIBTUNTAP_H_
|
||||
#define LIBTUNTAP_H_
|
||||
|
||||
#if defined IFNAMSIZ && !defined IF_NAMESIZE
|
||||
#define IF_NAMESIZE IFNAMSIZ /* Historical BSD name */
|
||||
#elif !defined IF_NAMESIZE
|
||||
#define IF_NAMESIZE 16
|
||||
#endif
|
||||
|
||||
#define IF_DESCRSIZE 50 /* XXX: Tests needed on NetBSD and OpenBSD */
|
||||
|
||||
#if defined TUNSETDEBUG
|
||||
#define TUNSDEBUG TUNSETDEBUG
|
||||
#endif
|
||||
|
||||
#if defined Windows
|
||||
#define TUNFD_INVALID_VALUE INVALID_HANDLE_VALUE
|
||||
#else /* Unix */
|
||||
#define TUNFD_INVALID_VALUE -1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uniformize types
|
||||
* - t_tun: tun device file descriptor
|
||||
* - t_tun_in_addr: struct in_addr/IN_ADDR
|
||||
* - t_tun_in6_addr: struct in6_addr/IN6_ADDR
|
||||
*/
|
||||
#if defined Windows
|
||||
#include <windows.h>
|
||||
#include <in6addr.h>
|
||||
#include <winsock2.h>
|
||||
typedef HANDLE t_tun;
|
||||
typedef IN_ADDR t_tun_in_addr;
|
||||
typedef IN6_ADDR t_tun_in6_addr;
|
||||
#else /* Unix */
|
||||
typedef int t_tun;
|
||||
typedef struct in_addr t_tun_in_addr;
|
||||
typedef struct in6_addr t_tun_in6_addr;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Windows helpers
|
||||
*/
|
||||
#if defined Windows
|
||||
//#define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z));
|
||||
#define strdup(x) _strdup(x)
|
||||
#endif
|
||||
|
||||
#define TUNTAP_ID_MAX 256
|
||||
#define TUNTAP_ID_ANY 257
|
||||
|
||||
#define TUNTAP_MODE_ETHERNET 0x0001
|
||||
#define TUNTAP_MODE_TUNNEL 0x0002
|
||||
#define TUNTAP_MODE_PERSIST 0x0004
|
||||
|
||||
#define TUNTAP_LOG_NONE 0x0000
|
||||
#define TUNTAP_LOG_DEBUG 0x0001
|
||||
#define TUNTAP_LOG_INFO 0x0002
|
||||
#define TUNTAP_LOG_NOTICE 0x0004
|
||||
#define TUNTAP_LOG_WARN 0x0008
|
||||
#define TUNTAP_LOG_ERR 0x0016
|
||||
|
||||
/* Versioning: 0xMMmm, with 'M' for major and 'm' for minor */
|
||||
#define TUNTAP_VERSION_MAJOR 0
|
||||
#define TUNTAP_VERSION_MINOR 3
|
||||
#define TUNTAP_VERSION ((TUNTAP_VERSION_MAJOR << 8) | TUNTAP_VERSION_MINOR)
|
||||
|
||||
#define TUNTAP_GET_FD(x) (x)->tun_fd
|
||||
|
||||
/* Handle Windows symbols export */
|
||||
#if defined Windows
|
||||
#if defined(tuntap_EXPORTS) && defined(_USRDLL) /* CMake generated goo */
|
||||
#define TUNTAP_EXPORT __declspec(dllexport)
|
||||
#elif defined(tuntap_EXPORTS)
|
||||
#define TUNTAP_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define TUNTAP_EXPORT extern
|
||||
#endif
|
||||
#else /* Unix */
|
||||
#define TUNTAP_EXPORT extern
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct device
|
||||
{
|
||||
/** set me on ios and android to block on a promise for the fd */
|
||||
int (*obtain_fd)(struct device*);
|
||||
/** user data */
|
||||
void* user;
|
||||
t_tun tun_fd;
|
||||
int ctrl_sock;
|
||||
int flags; /* ifr.ifr_flags on Unix */
|
||||
char if_name[IF_NAMESIZE];
|
||||
#if defined(Windows)
|
||||
int idx; /* needed to set ipv6 address */
|
||||
DWORD bindaddr; /* set DNS client address */
|
||||
#endif
|
||||
#if defined(FreeBSD)
|
||||
int mode;
|
||||
#endif
|
||||
#if defined(__sun)
|
||||
int ip_fd;
|
||||
int reserved;
|
||||
char internal_name[IF_NAMESIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* User definable log callback */
|
||||
typedef void (*t_tuntap_log)(int, int, const char*, const char*);
|
||||
TUNTAP_EXPORT t_tuntap_log __tuntap_log;
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#define LOG_TAG "tuntap"
|
||||
#endif
|
||||
|
||||
#define tuntap_log(lvl, msg) __tuntap_log(lvl, __LINE__, LOG_TAG, msg)
|
||||
|
||||
/* Portable "public" functions */
|
||||
TUNTAP_EXPORT struct device*
|
||||
tuntap_init(void);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_version(void);
|
||||
TUNTAP_EXPORT void
|
||||
tuntap_destroy(struct device*);
|
||||
TUNTAP_EXPORT void
|
||||
tuntap_release(struct device*);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_start(struct device*, int, int);
|
||||
TUNTAP_EXPORT char*
|
||||
tuntap_get_ifname(struct device*);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_set_ifname(struct device*, const char*);
|
||||
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_set_descr(struct device*, const char*);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_up(struct device*);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_down(struct device*);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_get_mtu(struct device*);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_set_mtu(struct device*, int);
|
||||
|
||||
/** set ip address and netmask
|
||||
|
||||
*/
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_set_ip(struct device*, const char* srcaddr, const char* dstaddr, int netmask);
|
||||
// TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char
|
||||
// *, int);
|
||||
/*TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char
|
||||
* *, int);*/
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_read(struct device*, void*, size_t);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_write(struct device*, void*, size_t);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_get_readable(struct device*);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_set_nonblocking(struct device* dev, int);
|
||||
TUNTAP_EXPORT int
|
||||
tuntap_set_debug(struct device* dev, int);
|
||||
|
||||
/* Logging functions */
|
||||
TUNTAP_EXPORT void
|
||||
tuntap_log_set_cb(t_tuntap_log cb);
|
||||
void
|
||||
tuntap_log_default(int, int, const char*, const char*);
|
||||
void
|
||||
tuntap_log_hexdump(void*, size_t);
|
||||
void
|
||||
tuntap_log_chksum(void*, int);
|
||||
|
||||
/* OS specific functions */
|
||||
int
|
||||
tuntap_sys_start(struct device*, int, int);
|
||||
void
|
||||
tuntap_sys_destroy(struct device*);
|
||||
int
|
||||
tuntap_sys_set_ipv4(struct device*, t_tun_in_addr*, uint32_t);
|
||||
|
||||
#if defined(Windows)
|
||||
int
|
||||
tuntap_sys_set_dns(struct device* dev, t_tun_in_addr* s, uint32_t mask);
|
||||
#endif
|
||||
|
||||
#if defined(FreeBSD)
|
||||
int
|
||||
tuntap_sys_set_ipv4_tap(struct device*, t_tun_in_addr*, uint32_t);
|
||||
int
|
||||
tuntap_sys_set_ipv4_tun(
|
||||
struct device* dev, t_tun_in_addr* s4, t_tun_in_addr* s4dest, uint32_t bits, int netmask);
|
||||
#endif
|
||||
|
||||
int
|
||||
tuntap_sys_set_ipv6(struct device*, t_tun_in6_addr*, uint32_t);
|
||||
int
|
||||
tuntap_sys_set_ifname(struct device*, const char*, size_t);
|
||||
int
|
||||
tuntap_sys_set_descr(struct device*, const char*, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -52,7 +52,6 @@ add_library(lokinet-platform
|
|||
ev/ev.cpp
|
||||
ev/pipe.cpp
|
||||
ev/ev_libuv.cpp
|
||||
|
||||
net/ip.cpp
|
||||
net/ip_address.cpp
|
||||
net/ip_packet.cpp
|
||||
|
@ -61,7 +60,7 @@ add_library(lokinet-platform
|
|||
net/net_int.cpp
|
||||
net/route.cpp
|
||||
net/sock_addr.cpp
|
||||
$<TARGET_OBJECTS:tuntap>
|
||||
vpn/platform.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography lokinet-util Threads::Threads base_libs libuv)
|
||||
|
@ -83,7 +82,6 @@ endif()
|
|||
if (WIN32)
|
||||
target_sources(lokinet-platform PRIVATE
|
||||
ev/ev_libuv.cpp
|
||||
ev/ev_win32.cpp
|
||||
win32/win32_inet.c
|
||||
win32/win32_intrnl.c)
|
||||
|
||||
|
|
|
@ -98,7 +98,16 @@ namespace llarp
|
|||
std::unique_ptr<AbstractRouter>
|
||||
Context::makeRouter(llarp_ev_loop_ptr netloop, std::shared_ptr<Logic> logic)
|
||||
{
|
||||
return std::make_unique<Router>(netloop, logic);
|
||||
return std::make_unique<Router>(netloop, logic, makeVPNPlatform());
|
||||
}
|
||||
|
||||
std::unique_ptr<vpn::Platform>
|
||||
Context::makeVPNPlatform()
|
||||
{
|
||||
auto plat = vpn::MakeNativePlatform(this);
|
||||
if (plat == nullptr)
|
||||
throw std::runtime_error("vpn platform not supported");
|
||||
return plat;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -123,9 +132,9 @@ namespace llarp
|
|||
llarp_ev_loop_run_single_process(mainloop, logic);
|
||||
if (closeWaiter)
|
||||
{
|
||||
// inform promise if called by CloseAsync
|
||||
closeWaiter->set_value();
|
||||
}
|
||||
Close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -177,13 +186,6 @@ namespace llarp
|
|||
/// async stop router on sigint
|
||||
router->Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logic)
|
||||
logic->stop();
|
||||
llarp_ev_loop_stop(mainloop);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -47,14 +47,7 @@ namespace llarp
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const IpAddress any("0.0.0.0", 0);
|
||||
auto self = shared_from_this();
|
||||
LogicCall(m_ClientLogic, [=]() {
|
||||
llarp_ev_add_udp(self->m_ClientLoop.get(), &self->m_Client, any.createSockAddr());
|
||||
});
|
||||
return (
|
||||
llarp_ev_add_udp(self->m_ServerLoop.get(), &self->m_Server, addr.createSockAddr()) == 0);
|
||||
return (llarp_ev_add_udp(m_ServerLoop, &m_Server, addr.createSockAddr()) == 0);
|
||||
}
|
||||
|
||||
static Proxy::Buffer_t
|
||||
|
|
134
llarp/ev/ev.cpp
134
llarp/ev/ev.cpp
|
@ -9,10 +9,6 @@
|
|||
|
||||
// We libuv now
|
||||
#include <ev/ev_libuv.hpp>
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#include <ev/ev_win32.hpp>
|
||||
#endif
|
||||
|
||||
llarp_ev_loop_ptr
|
||||
llarp_make_ev_loop(size_t queueLength)
|
||||
|
@ -34,14 +30,14 @@ llarp_ev_loop_run_single_process(llarp_ev_loop_ptr ev, std::shared_ptr<llarp::Lo
|
|||
}
|
||||
|
||||
int
|
||||
llarp_ev_add_udp(struct llarp_ev_loop* ev, struct llarp_udp_io* udp, const llarp::SockAddr& src)
|
||||
llarp_ev_add_udp(const llarp_ev_loop_ptr& ev, struct llarp_udp_io* udp, const llarp::SockAddr& src)
|
||||
{
|
||||
if (ev == nullptr or udp == nullptr)
|
||||
{
|
||||
llarp::LogError("Attempting llarp_ev_add_udp() with null event loop or udp io struct.");
|
||||
return -1;
|
||||
}
|
||||
udp->parent = ev;
|
||||
udp->parent = ev.get();
|
||||
if (ev->udp_listen(udp, src))
|
||||
return 0;
|
||||
llarp::LogError("llarp_ev_add_udp() call to udp_listen failed.");
|
||||
|
@ -75,129 +71,3 @@ llarp_ev_udp_sendto(struct llarp_udp_io* udp, const llarp::SockAddr& to, const l
|
|||
{
|
||||
return udp->sendto(udp, to, buf.base, buf.sz);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_ev_add_tun(struct llarp_ev_loop* loop, struct llarp_tun_io* tun)
|
||||
{
|
||||
if (tun->ifaddr[0] == 0 || strcmp(tun->ifaddr, "auto") == 0)
|
||||
{
|
||||
LogError("invalid ifaddr on tun: ", tun->ifaddr);
|
||||
return false;
|
||||
}
|
||||
if (tun->ifname[0] == 0 || strcmp(tun->ifname, "auto") == 0)
|
||||
{
|
||||
LogError("invalid ifname on tun: ", tun->ifname);
|
||||
return false;
|
||||
}
|
||||
#if !defined(_WIN32)
|
||||
return loop->tun_listen(tun);
|
||||
#else
|
||||
UNREFERENCED_PARAMETER(loop);
|
||||
auto dev = new win32_tun_io(tun);
|
||||
tun->impl = dev;
|
||||
// We're not even going to add this to the socket event loop
|
||||
if (dev)
|
||||
{
|
||||
dev->setup();
|
||||
return dev->add_ev(loop); // start up tun and add to event queue
|
||||
}
|
||||
llarp::LogWarn("Loop could not create tun");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_ev_tun_async_write(struct llarp_tun_io* tun, const llarp_buffer_t& buf)
|
||||
{
|
||||
if (buf.sz > EV_WRITE_BUF_SZ)
|
||||
{
|
||||
llarp::LogWarn("packet too big, ", buf.sz, " > ", EV_WRITE_BUF_SZ);
|
||||
return false;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
return tun->writepkt(tun, buf.base, buf.sz);
|
||||
#else
|
||||
return static_cast<win32_tun_io*>(tun->impl)->queue_write(buf.base, buf.sz);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_tcp_conn_async_write(struct llarp_tcp_conn* conn, const llarp_buffer_t& b)
|
||||
{
|
||||
ManagedBuffer buf{b};
|
||||
|
||||
size_t sz = buf.underlying.sz;
|
||||
buf.underlying.cur = buf.underlying.base;
|
||||
while (sz > EV_WRITE_BUF_SZ)
|
||||
{
|
||||
ssize_t amount = conn->write(conn, buf.underlying.cur, EV_WRITE_BUF_SZ);
|
||||
if (amount <= 0)
|
||||
{
|
||||
llarp::LogError("write underrun");
|
||||
llarp_tcp_conn_close(conn);
|
||||
return false;
|
||||
}
|
||||
buf.underlying.cur += amount;
|
||||
sz -= amount;
|
||||
}
|
||||
return conn->write(conn, buf.underlying.cur, sz) > 0;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_tcp_async_try_connect(struct llarp_ev_loop* loop, struct llarp_tcp_connecter* tcp)
|
||||
{
|
||||
tcp->loop = loop;
|
||||
|
||||
llarp::IpAddress address(tcp->remote);
|
||||
|
||||
if (not address.getPort())
|
||||
throw std::runtime_error(llarp::stringify("Address with no port: ", address));
|
||||
|
||||
llarp::SockAddr addr = address.createSockAddr();
|
||||
|
||||
if (!loop->tcp_connect(tcp, addr))
|
||||
{
|
||||
llarp::LogError("async connect failed");
|
||||
if (tcp->error)
|
||||
tcp->error(tcp);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_tcp_serve(
|
||||
struct llarp_ev_loop* loop, struct llarp_tcp_acceptor* tcp, const llarp::SockAddr& bindaddr)
|
||||
{
|
||||
tcp->loop = loop;
|
||||
return loop->tcp_listen(tcp, bindaddr);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_tcp_acceptor_close(struct llarp_tcp_acceptor* tcp)
|
||||
{
|
||||
tcp->close(tcp);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_tcp_conn_close(struct llarp_tcp_conn* conn)
|
||||
{
|
||||
conn->close(conn);
|
||||
}
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
bool
|
||||
tcp_conn::tick()
|
||||
{
|
||||
if (_shouldClose)
|
||||
{
|
||||
if (tcp.closed)
|
||||
tcp.closed(&tcp);
|
||||
::shutdown(fd, SHUT_RDWR);
|
||||
return false;
|
||||
}
|
||||
if (tcp.tick)
|
||||
tcp.tick(&tcp);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
|
150
llarp/ev/ev.h
150
llarp/ev/ev.h
|
@ -4,7 +4,6 @@
|
|||
#include <net/ip_address.hpp>
|
||||
#include <util/buffer.hpp>
|
||||
#include <util/time.hpp>
|
||||
#include <tuntap.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
@ -31,17 +30,13 @@
|
|||
|
||||
#define EV_TICK_INTERVAL 10
|
||||
|
||||
// forward declare
|
||||
struct llarp_threadpool;
|
||||
|
||||
struct llarp_ev_loop;
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
class Logic;
|
||||
}
|
||||
struct EventLoop;
|
||||
} // namespace llarp
|
||||
|
||||
using llarp_ev_loop_ptr = std::shared_ptr<llarp_ev_loop>;
|
||||
using llarp_ev_loop_ptr = std::shared_ptr<llarp::EventLoop>;
|
||||
|
||||
/// make an event loop using our baked in event loop on Windows
|
||||
/// make an event loop using libuv otherwise.
|
||||
|
@ -68,7 +63,7 @@ struct llarp_udp_io
|
|||
int fd;
|
||||
void* user;
|
||||
void* impl;
|
||||
struct llarp_ev_loop* parent;
|
||||
llarp::EventLoop* parent;
|
||||
|
||||
/// called every event loop tick after reads
|
||||
void (*tick)(struct llarp_udp_io*);
|
||||
|
@ -80,7 +75,7 @@ struct llarp_udp_io
|
|||
|
||||
/// add UDP handler
|
||||
int
|
||||
llarp_ev_add_udp(struct llarp_ev_loop* ev, struct llarp_udp_io* udp, const llarp::SockAddr& src);
|
||||
llarp_ev_add_udp(const llarp_ev_loop_ptr& ev, struct llarp_udp_io* udp, const llarp::SockAddr& src);
|
||||
|
||||
/// send a UDP packet
|
||||
int
|
||||
|
@ -90,139 +85,4 @@ llarp_ev_udp_sendto(struct llarp_udp_io* udp, const llarp::SockAddr& to, const l
|
|||
int
|
||||
llarp_ev_close_udp(struct llarp_udp_io* udp);
|
||||
|
||||
// forward declare
|
||||
struct llarp_tcp_acceptor;
|
||||
|
||||
/// a single tcp connection
|
||||
struct llarp_tcp_conn
|
||||
{
|
||||
/// user data
|
||||
void* user;
|
||||
/// private implementation
|
||||
void* impl;
|
||||
/// parent loop (dont set me)
|
||||
struct llarp_ev_loop* loop;
|
||||
/// handle read event
|
||||
void (*read)(struct llarp_tcp_conn*, const llarp_buffer_t&);
|
||||
//// set by parent
|
||||
ssize_t (*write)(struct llarp_tcp_conn*, const byte_t*, size_t sz);
|
||||
/// set by parent
|
||||
bool (*is_open)(struct llarp_tcp_conn*);
|
||||
/// handle close event (free-ing is handled by event loop)
|
||||
void (*closed)(struct llarp_tcp_conn*);
|
||||
/// explict close by user (set by parent)
|
||||
void (*close)(struct llarp_tcp_conn*);
|
||||
/// handle event loop tick
|
||||
void (*tick)(struct llarp_tcp_conn*);
|
||||
};
|
||||
|
||||
/// queue async write a buffer in full
|
||||
/// return if we queued it or not
|
||||
bool
|
||||
llarp_tcp_conn_async_write(struct llarp_tcp_conn*, const llarp_buffer_t&);
|
||||
|
||||
/// close a tcp connection
|
||||
void
|
||||
llarp_tcp_conn_close(struct llarp_tcp_conn*);
|
||||
|
||||
/// handles outbound connections to 1 endpoint
|
||||
struct llarp_tcp_connecter
|
||||
{
|
||||
/// remote address family
|
||||
int af;
|
||||
/// remote address string
|
||||
llarp::IpAddress remote;
|
||||
/// userdata pointer
|
||||
void* user;
|
||||
/// private implementation (dont set me)
|
||||
void* impl;
|
||||
/// parent event loop (dont set me)
|
||||
struct llarp_ev_loop* loop;
|
||||
/// handle outbound connection made
|
||||
void (*connected)(struct llarp_tcp_connecter*, struct llarp_tcp_conn*);
|
||||
/// handle outbound connection error
|
||||
void (*error)(struct llarp_tcp_connecter*);
|
||||
};
|
||||
|
||||
/// async try connecting to a remote connection 1 time
|
||||
void
|
||||
llarp_tcp_async_try_connect(struct llarp_ev_loop* l, struct llarp_tcp_connecter* tcp);
|
||||
|
||||
/// handles inbound connections
|
||||
struct llarp_tcp_acceptor
|
||||
{
|
||||
/// userdata pointer
|
||||
void* user;
|
||||
/// internal implementation
|
||||
void* impl;
|
||||
/// parent event loop (dont set me)
|
||||
struct llarp_ev_loop* loop;
|
||||
/// handle event loop tick
|
||||
void (*tick)(struct llarp_tcp_acceptor*);
|
||||
/// handle inbound connection
|
||||
void (*accepted)(struct llarp_tcp_acceptor*, struct llarp_tcp_conn*);
|
||||
/// handle after server socket closed (free-ing is handled by event loop)
|
||||
void (*closed)(struct llarp_tcp_acceptor*);
|
||||
/// set by impl
|
||||
void (*close)(struct llarp_tcp_acceptor*);
|
||||
};
|
||||
|
||||
/// bind to an address and start serving async
|
||||
/// return false if failed to bind
|
||||
/// return true on success
|
||||
bool
|
||||
llarp_tcp_serve(
|
||||
struct llarp_ev_loop* loop, struct llarp_tcp_acceptor* t, const llarp::SockAddr& bindaddr);
|
||||
|
||||
/// close and stop accepting connections
|
||||
void
|
||||
llarp_tcp_acceptor_close(struct llarp_tcp_acceptor*);
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IFNAMSIZ (16)
|
||||
#endif
|
||||
|
||||
struct llarp_fd_promise;
|
||||
|
||||
/// wait until the fd promise is set
|
||||
int
|
||||
llarp_fd_promise_wait_for_value(struct llarp_fd_promise* promise);
|
||||
|
||||
struct llarp_tun_io
|
||||
{
|
||||
// TODO: more info?
|
||||
char ifaddr[128];
|
||||
// windows only
|
||||
uint32_t dnsaddr;
|
||||
int netmask;
|
||||
char ifname[IFNAMSIZ + 1];
|
||||
|
||||
void* user;
|
||||
void* impl;
|
||||
|
||||
/// functor for getting a promise that returns the vpn fd
|
||||
/// dont set me if you don't know how to use this
|
||||
struct llarp_fd_promise* (*get_fd_promise)(struct llarp_tun_io*);
|
||||
|
||||
struct llarp_ev_loop* parent;
|
||||
/// called when we are able to write right before we write
|
||||
/// this happens after reading packets
|
||||
void (*before_write)(struct llarp_tun_io*);
|
||||
/// called every event loop tick after reads
|
||||
void (*tick)(struct llarp_tun_io*);
|
||||
void (*recvpkt)(struct llarp_tun_io*, const llarp_buffer_t&);
|
||||
/// set by parent
|
||||
bool (*writepkt)(struct llarp_tun_io*, const byte_t*, size_t);
|
||||
};
|
||||
|
||||
/// create tun interface with network interface name ifname
|
||||
/// returns true on success otherwise returns false
|
||||
bool
|
||||
llarp_ev_add_tun(struct llarp_ev_loop* ev, struct llarp_tun_io* tun);
|
||||
|
||||
/// async write a packet on tun interface
|
||||
/// returns true if queued, returns false on drop
|
||||
bool
|
||||
llarp_ev_tun_async_write(struct llarp_tun_io* tun, const llarp_buffer_t&);
|
||||
|
||||
#endif
|
||||
|
|
795
llarp/ev/ev.hpp
795
llarp/ev/ev.hpp
|
@ -2,6 +2,7 @@
|
|||
#define LLARP_EV_HPP
|
||||
|
||||
#include <net/ip_address.hpp>
|
||||
#include <net/ip_packet.hpp>
|
||||
#include <ev/ev.h>
|
||||
#include <util/buffer.hpp>
|
||||
#include <util/codel.hpp>
|
||||
|
@ -51,759 +52,81 @@ struct llarp_ev_pkt_pipe;
|
|||
#define EV_WRITE_BUF_SZ (4 * 1024UL)
|
||||
#endif
|
||||
|
||||
/// do io and reset errno after
|
||||
static ssize_t
|
||||
IO(std::function<ssize_t(void)> iofunc)
|
||||
{
|
||||
ssize_t ret = iofunc();
|
||||
#ifndef _WIN32
|
||||
errno = 0;
|
||||
#else
|
||||
WSASetLastError(0);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct win32_ev_io
|
||||
namespace vpn
|
||||
{
|
||||
struct WriteBuffer
|
||||
{
|
||||
llarp_time_t timestamp = 0s;
|
||||
size_t bufsz;
|
||||
byte_t buf[EV_WRITE_BUF_SZ] = {0};
|
||||
class NetworkInterface;
|
||||
}
|
||||
|
||||
WriteBuffer() = default;
|
||||
// this (nearly!) abstract base class
|
||||
// is overriden for each platform
|
||||
struct EventLoop
|
||||
{
|
||||
byte_t readbuf[EV_READ_BUF_SZ] = {0};
|
||||
|
||||
WriteBuffer(const byte_t* ptr, size_t sz)
|
||||
{
|
||||
if (sz <= sizeof(buf))
|
||||
{
|
||||
bufsz = sz;
|
||||
memcpy(buf, ptr, bufsz);
|
||||
}
|
||||
else
|
||||
bufsz = 0;
|
||||
}
|
||||
|
||||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const WriteBuffer& buf) const
|
||||
{
|
||||
return buf.timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetNow
|
||||
{
|
||||
llarp_ev_loop_ptr loop;
|
||||
GetNow(llarp_ev_loop_ptr l) : loop(l)
|
||||
{}
|
||||
|
||||
llarp_time_t
|
||||
operator()() const
|
||||
{
|
||||
return llarp_ev_loop_time_now_ms(loop);
|
||||
}
|
||||
};
|
||||
|
||||
struct PutTime
|
||||
{
|
||||
llarp_ev_loop_ptr loop;
|
||||
PutTime(llarp_ev_loop_ptr l) : loop(l)
|
||||
{}
|
||||
void
|
||||
operator()(WriteBuffer& buf)
|
||||
{
|
||||
buf.timestamp = llarp_ev_loop_time_now_ms(loop);
|
||||
}
|
||||
};
|
||||
|
||||
struct Compare
|
||||
{
|
||||
bool
|
||||
operator()(const WriteBuffer& left, const WriteBuffer& right) const
|
||||
{
|
||||
return left.timestamp < right.timestamp;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
using LosslessWriteQueue_t = std::deque<WriteBuffer>;
|
||||
|
||||
intptr_t fd; // Sockets only, fuck UNIX-style reactive IO with a rusty knife
|
||||
|
||||
int flags = 0;
|
||||
win32_ev_io(intptr_t f) : fd(f){};
|
||||
|
||||
/// for tcp
|
||||
win32_ev_io(intptr_t f, LosslessWriteQueue_t* q) : fd(f), m_BlockingWriteQueue(q)
|
||||
{}
|
||||
|
||||
virtual void
|
||||
error()
|
||||
{
|
||||
char ebuf[1024];
|
||||
int err = WSAGetLastError();
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_NEUTRAL, ebuf, 1024, nullptr);
|
||||
llarp::LogError(ebuf);
|
||||
}
|
||||
|
||||
virtual int
|
||||
read(byte_t* buf, size_t sz) = 0;
|
||||
|
||||
virtual int
|
||||
sendto(const SockAddr& dst, const void* data, size_t sz)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dst);
|
||||
UNREFERENCED_PARAMETER(data);
|
||||
UNREFERENCED_PARAMETER(sz);
|
||||
return -1;
|
||||
};
|
||||
|
||||
/// return false if we want to deregister and remove ourselves
|
||||
virtual bool
|
||||
tick()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
/// used for tun interface and tcp conn
|
||||
virtual ssize_t
|
||||
do_write(void* data, size_t sz)
|
||||
{
|
||||
return send(fd, (char*)data, sz, 0);
|
||||
}
|
||||
|
||||
bool
|
||||
queue_write(const byte_t* buf, size_t sz)
|
||||
{
|
||||
if (m_BlockingWriteQueue)
|
||||
{
|
||||
m_BlockingWriteQueue->emplace_back(buf, sz);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void
|
||||
flush_write()
|
||||
{
|
||||
flush_write_buffers(0);
|
||||
}
|
||||
|
||||
/// 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_buffers(size_t amount)
|
||||
{
|
||||
if (m_BlockingWriteQueue)
|
||||
{
|
||||
if (amount)
|
||||
{
|
||||
while (amount && m_BlockingWriteQueue->size())
|
||||
{
|
||||
auto& itr = m_BlockingWriteQueue->front();
|
||||
ssize_t result = do_write(itr.buf, std::min(amount, itr.bufsz));
|
||||
if (result == -1)
|
||||
return;
|
||||
ssize_t dlt = itr.bufsz - result;
|
||||
if (dlt > 0)
|
||||
{
|
||||
// queue remaining to front of queue
|
||||
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
m_BlockingWriteQueue->push_front(buff);
|
||||
// TODO: errno?
|
||||
return;
|
||||
}
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
amount -= result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write buffers
|
||||
while (m_BlockingWriteQueue->size())
|
||||
{
|
||||
auto& itr = m_BlockingWriteQueue->front();
|
||||
ssize_t result = do_write(itr.buf, itr.bufsz);
|
||||
if (result == -1)
|
||||
return;
|
||||
ssize_t dlt = itr.bufsz - result;
|
||||
if (dlt > 0)
|
||||
{
|
||||
// queue remaining to front of queue
|
||||
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
m_BlockingWriteQueue->push_front(buff);
|
||||
// TODO: errno?
|
||||
return;
|
||||
}
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
int wsaerr = WSAGetLastError();
|
||||
if (wsaerr == WSA_IO_PENDING || wsaerr == WSAEWOULDBLOCK)
|
||||
{
|
||||
WSASetLastError(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// reset errno
|
||||
WSASetLastError(0);
|
||||
}
|
||||
|
||||
std::unique_ptr<LosslessWriteQueue_t> m_BlockingWriteQueue;
|
||||
|
||||
virtual ~win32_ev_io()
|
||||
{
|
||||
closesocket(fd);
|
||||
};
|
||||
};
|
||||
#else
|
||||
struct posix_ev_io
|
||||
{
|
||||
struct WriteBuffer
|
||||
{
|
||||
llarp_time_t timestamp = 0s;
|
||||
size_t bufsz;
|
||||
byte_t buf[EV_WRITE_BUF_SZ];
|
||||
|
||||
WriteBuffer() = default;
|
||||
|
||||
WriteBuffer(const byte_t* ptr, size_t sz)
|
||||
{
|
||||
if (sz <= sizeof(buf))
|
||||
{
|
||||
bufsz = sz;
|
||||
memcpy(buf, ptr, bufsz);
|
||||
}
|
||||
else
|
||||
bufsz = 0;
|
||||
}
|
||||
|
||||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const WriteBuffer& writebuf) const
|
||||
{
|
||||
return writebuf.timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetNow
|
||||
{
|
||||
llarp_ev_loop_ptr loop;
|
||||
GetNow(llarp_ev_loop_ptr l) : loop(std::move(l))
|
||||
{}
|
||||
|
||||
llarp_time_t
|
||||
operator()() const
|
||||
{
|
||||
return llarp_ev_loop_time_now_ms(loop);
|
||||
}
|
||||
};
|
||||
|
||||
struct PutTime
|
||||
{
|
||||
llarp_ev_loop_ptr loop;
|
||||
PutTime(llarp_ev_loop_ptr l) : loop(std::move(l))
|
||||
{}
|
||||
void
|
||||
operator()(WriteBuffer& writebuf)
|
||||
{
|
||||
writebuf.timestamp = llarp_ev_loop_time_now_ms(loop);
|
||||
}
|
||||
};
|
||||
|
||||
struct Compare
|
||||
{
|
||||
bool
|
||||
operator()(const WriteBuffer& left, const WriteBuffer& right) const
|
||||
{
|
||||
return left.timestamp < right.timestamp;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
using LossyWriteQueue_t = llarp::util::CoDelQueue<
|
||||
WriteBuffer,
|
||||
WriteBuffer::GetTime,
|
||||
WriteBuffer::PutTime,
|
||||
WriteBuffer::Compare,
|
||||
WriteBuffer::GetNow,
|
||||
llarp::util::NullMutex,
|
||||
llarp::util::NullLock>;
|
||||
|
||||
using LosslessWriteQueue_t = std::deque<WriteBuffer>;
|
||||
|
||||
int fd;
|
||||
int flags = 0;
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
|
||||
struct kevent change;
|
||||
#endif
|
||||
|
||||
posix_ev_io(int f) : fd(f)
|
||||
{}
|
||||
|
||||
/// for tun
|
||||
posix_ev_io(int f, LossyWriteQueue_t* q) : fd(f), m_LossyWriteQueue(q)
|
||||
{}
|
||||
|
||||
/// for tcp
|
||||
posix_ev_io(int f, LosslessWriteQueue_t* q) : fd(f), m_BlockingWriteQueue(q)
|
||||
{}
|
||||
|
||||
virtual void
|
||||
error()
|
||||
{
|
||||
llarp::LogError(strerror(errno));
|
||||
}
|
||||
init() = 0;
|
||||
|
||||
virtual int
|
||||
read(byte_t* buf, size_t sz) = 0;
|
||||
run() = 0;
|
||||
|
||||
virtual int
|
||||
sendto(
|
||||
__attribute__((unused)) const SockAddr& dst,
|
||||
__attribute__((unused)) const void* data,
|
||||
__attribute__((unused)) size_t sz)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// return false if we want to deregister and remove ourselves
|
||||
virtual bool
|
||||
tick()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// used for tun interface and tcp conn
|
||||
virtual ssize_t
|
||||
do_write(void* data, size_t sz)
|
||||
{
|
||||
return write(fd, data, sz);
|
||||
}
|
||||
|
||||
bool
|
||||
queue_write(const byte_t* buf, size_t sz)
|
||||
{
|
||||
if (m_LossyWriteQueue)
|
||||
{
|
||||
m_LossyWriteQueue->Emplace(buf, sz);
|
||||
return true;
|
||||
}
|
||||
if (m_BlockingWriteQueue)
|
||||
{
|
||||
m_BlockingWriteQueue->emplace_back(buf, sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
running() const = 0;
|
||||
|
||||
virtual void
|
||||
flush_write()
|
||||
{
|
||||
flush_write_buffers(0);
|
||||
}
|
||||
|
||||
virtual void
|
||||
before_flush_write()
|
||||
update_time()
|
||||
{}
|
||||
|
||||
/// called in event loop when fd is ready for writing
|
||||
/// requeues anything not written
|
||||
/// this assumes fd is set to non blocking
|
||||
virtual llarp_time_t
|
||||
time_now() const
|
||||
{
|
||||
return llarp::time_now_ms();
|
||||
}
|
||||
|
||||
virtual void
|
||||
flush_write_buffers(size_t amount)
|
||||
{
|
||||
before_flush_write();
|
||||
if (m_LossyWriteQueue)
|
||||
{
|
||||
m_LossyWriteQueue->Process([&](WriteBuffer& buffer) {
|
||||
do_write(buffer.buf, buffer.bufsz);
|
||||
// if we would block we save the entries for later
|
||||
// discard entry
|
||||
});
|
||||
}
|
||||
else if (m_BlockingWriteQueue)
|
||||
{
|
||||
if (amount)
|
||||
{
|
||||
while (amount && m_BlockingWriteQueue->size())
|
||||
{
|
||||
auto& itr = m_BlockingWriteQueue->front();
|
||||
ssize_t result = do_write(itr.buf, std::min(amount, itr.bufsz));
|
||||
if (result <= 0)
|
||||
return;
|
||||
ssize_t dlt = itr.bufsz - result;
|
||||
if (dlt > 0)
|
||||
{
|
||||
// queue remaining to front of queue
|
||||
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
m_BlockingWriteQueue->push_front(buff);
|
||||
// TODO: errno?
|
||||
return;
|
||||
}
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
amount -= result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write buffers
|
||||
while (m_BlockingWriteQueue->size())
|
||||
{
|
||||
auto& itr = m_BlockingWriteQueue->front();
|
||||
ssize_t result = do_write(itr.buf, itr.bufsz);
|
||||
if (result <= 0)
|
||||
{
|
||||
errno = 0;
|
||||
return;
|
||||
}
|
||||
ssize_t dlt = itr.bufsz - result;
|
||||
if (dlt > 0)
|
||||
{
|
||||
// queue remaining to front of queue
|
||||
WriteBuffer buff(itr.buf + dlt, itr.bufsz - dlt);
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
m_BlockingWriteQueue->push_front(buff);
|
||||
// TODO: errno?
|
||||
return;
|
||||
}
|
||||
m_BlockingWriteQueue->pop_front();
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
{
|
||||
errno = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// reset errno
|
||||
errno = 0;
|
||||
}
|
||||
stopped(){};
|
||||
|
||||
std::unique_ptr<LossyWriteQueue_t> m_LossyWriteQueue;
|
||||
std::unique_ptr<LosslessWriteQueue_t> m_BlockingWriteQueue;
|
||||
virtual uint32_t
|
||||
call_after_delay(llarp_time_t delay_ms, std::function<void(void)> callback) = 0;
|
||||
|
||||
virtual ~posix_ev_io()
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
virtual void
|
||||
cancel_delayed_call(uint32_t call_id) = 0;
|
||||
|
||||
virtual bool
|
||||
add_network_interface(
|
||||
std::shared_ptr<vpn::NetworkInterface> netif,
|
||||
std::function<void(net::IPPacket)> packetHandler) = 0;
|
||||