diff --git a/package/lienol/trojan-go/Makefile b/package/lienol/trojan-go/Makefile new file mode 100644 index 0000000000..f0e7434166 --- /dev/null +++ b/package/lienol/trojan-go/Makefile @@ -0,0 +1,85 @@ +# Copyright (C) 2020 Lienol +# +# This is free software, licensed under the GNU General Public License v3. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=trojan-go +PKG_VERSION:=0.7.8 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/p4gefau1t/trojan-go.git +PKG_SOURCE_VERSION:=9866c030058870bf18d60f1d3677c6d4ed9de35d +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) + +PKG_CONFIG_DEPENDS := \ + CONFIG_TROJAN_GO_COMPRESS_GOPROXY \ + CONFIG_TROJAN_GO_COMPRESS_UPX + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/p4gefau1t/trojan-go +GO_PKG_LDFLAGS:=-s -w +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG)/constant.Version=$(PKG_VERSION) \ + $(GO_PKG)/constant.Commit=$(PKG_SOURCE_VERSION) +GO_PKG_TAG:=-tags full + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/$(PKG_NAME) + SECTION:=net + CATEGORY:=Network + DEPENDS:=$$(GO_ARCH_DEPENDS) + TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features. + URL:=https://github.com/p4gefau1t/trojan-go +endef + +define Package/$(PKG_NAME)/config + +menu "Configuration" + depends on PACKAGE_$(PKG_NAME) + +config TROJAN_GO_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config TROJAN_GO_COMPRESS_UPX + bool "Compress executable files with UPX" + default y + +endmenu + +endef + +ifeq ($(CONFIG_TROJAN_GO_COMPRESS_GOPROXY),y) +export GO111MODULE=on +export GOPROXY=https://goproxy.cn +endif + +define Build/Prepare + tar -zxvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1 +endef + +define Build/Compile + $(call GoPackage/Build/Configure) + $(call GoPackage/Build/Compile) +ifeq ($(CONFIG_TROJAN_GO_COMPRESS_UPX),y) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) +endif +endef + +define Package/$(PKG_NAME)/install + $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) $(1)/usr/bin/$(PKG_NAME) +endef + +$(eval $(call GoBinPackage,$(PKG_NAME))) +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lienol/trojan-plus/Makefile b/package/lienol/trojan-plus/Makefile new file mode 100644 index 0000000000..76f9d6fb2f --- /dev/null +++ b/package/lienol/trojan-plus/Makefile @@ -0,0 +1,69 @@ +# +# Copyright (C) 2018-2019 wongsyrone +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +PKG_NAME:=trojan +PKG_VERSION:=10.0.1 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/Trojan-Plus-Group/trojan-plus.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=4af7ff4dd48c7257c354d4e6dafafcdf5f12379c +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz + +CMAKE_INSTALL:=1 +PKG_BUILD_PARALLEL:=0 +PKG_BUILD_DEPENDS:=openssl + +PKG_LICENSE:=GPL-3.0 +PKG_MAINTAINER:=Trojan-Plus-Group + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +TARGET_CXXFLAGS += -Wall -Wextra +TARGET_CXXFLAGS += $(FPIC) + +# LTO +TARGET_CXXFLAGS += -flto +TARGET_LDFLAGS += -flto + +# CXX standard +TARGET_CXXFLAGS += -std=c++11 +TARGET_CXXFLAGS := $(filter-out -O%,$(TARGET_CXXFLAGS)) -O3 +TARGET_CXXFLAGS += -ffunction-sections -fdata-sections +TARGET_LDFLAGS += -Wl,--gc-sections + +CMAKE_OPTIONS += \ + -DENABLE_MYSQL=OFF \ + -DENABLE_NAT=ON \ + -DENABLE_REUSE_PORT=ON \ + -DENABLE_SSL_KEYLOG=ON \ + -DENABLE_TLS13_CIPHERSUITES=ON \ + -DFORCE_TCP_FASTOPEN=OFF \ + -DSYSTEMD_SERVICE=OFF \ + -DOPENSSL_USE_STATIC_LIBS=FALSE \ + -DBoost_DEBUG=ON \ + -DBoost_NO_BOOST_CMAKE=ON + +define Package/trojan + SECTION:=net + CATEGORY:=Network + TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features. + URL:=https://github.com/Trojan-Plus-Group/trojan-plus + DEPENDS:=+libpthread +libstdcpp +libopenssl \ + +boost +boost-system +boost-program_options +endef + +define Package/trojan/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/trojan +endef + +$(eval $(call BuildPackage,trojan)) + diff --git a/package/lienol/trojan-plus/patches/0001-C-S-Binary-Mods.patch b/package/lienol/trojan-plus/patches/0001-C-S-Binary-Mods.patch new file mode 100644 index 0000000000..8b19c83480 --- /dev/null +++ b/package/lienol/trojan-plus/patches/0001-C-S-Binary-Mods.patch @@ -0,0 +1,3339 @@ +From 2a15d2c886cb23f4d5a8ff975fa3c87819046390 Mon Sep 17 00:00:00 2001 +From: peter-tank <30540412+peter-tank@users.noreply.github.com> +Date: Sat, 4 Jul 2020 16:00:00 +0000 +Subject: [PATCH] C/S Binary Mods - no dns settings + +Signed-off-by: peter-tank <30540412+peter-tank@users.noreply.github.com> +--- + .gitmodules | 9 - + CMakeLists.txt | 114 ++---- + GSL | 1 - + badvpn | 1 - + src/core/pipeline.cpp | 1 - + src/core/service.cpp | 41 --- + src/core/service.h | 4 - + src/tun/dnsserver.cpp | 278 -------------- + src/tun/dnsserver.h | 107 ------ + src/tun/lwip_custom/arch/cc.h | 79 ---- + src/tun/lwip_custom/lwipopts.h | 84 ----- + src/tun/lwip_custom/sys.c | 29 -- + src/tun/lwip_tcp_client.cpp | 273 -------------- + src/tun/lwip_tcp_client.h | 81 ----- + src/tun/tundev.cpp | 644 --------------------------------- + src/tun/tundev.h | 146 -------- + src/tun/tunlocalsession.cpp | 215 ----------- + src/tun/tunlocalsession.h | 55 --- + src/tun/tunproxysession.cpp | 409 --------------------- + src/tun/tunproxysession.h | 59 --- + src/tun/tunsession.cpp | 40 -- + src/tun/tunsession.h | 108 ------ + src/tun/udplocalforwarder.cpp | 156 -------- + src/tun/udplocalforwarder.h | 63 ---- + trojan-plus-android-libs | 1 - + 25 files changed, 26 insertions(+), 2972 deletions(-) + delete mode 160000 GSL + delete mode 160000 badvpn + delete mode 100644 src/tun/dnsserver.cpp + delete mode 100644 src/tun/dnsserver.h + delete mode 100644 src/tun/lwip_custom/arch/cc.h + delete mode 100644 src/tun/lwip_custom/lwipopts.h + delete mode 100644 src/tun/lwip_custom/sys.c + delete mode 100644 src/tun/lwip_tcp_client.cpp + delete mode 100644 src/tun/lwip_tcp_client.h + delete mode 100644 src/tun/tundev.cpp + delete mode 100644 src/tun/tundev.h + delete mode 100644 src/tun/tunlocalsession.cpp + delete mode 100644 src/tun/tunlocalsession.h + delete mode 100644 src/tun/tunproxysession.cpp + delete mode 100644 src/tun/tunproxysession.h + delete mode 100644 src/tun/tunsession.cpp + delete mode 100644 src/tun/tunsession.h + delete mode 100644 src/tun/udplocalforwarder.cpp + delete mode 100644 src/tun/udplocalforwarder.h + delete mode 160000 trojan-plus-android-libs + +diff --git a/.gitmodules b/.gitmodules +index 68e3712..e69de29 100644 +--- a/.gitmodules ++++ b/.gitmodules +@@ -1,9 +0,0 @@ +-[submodule "badvpn"] +- path = badvpn +- url = https://github.com/Trojan-Plus-Group/badvpn +-[submodule "trojan-plus-android-libs"] +- path = trojan-plus-android-libs +- url = https://github.com/Trojan-Plus-Group/trojan-plus-android-libs.git +-[submodule "GSL"] +- path = GSL +- url = https://github.com/microsoft/GSL.git +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3fc087d..e3e1171 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -47,7 +47,7 @@ if(CMAKE_BUILD_TYPE STREQUAL Release AND NOT MSVC AND NOT APPLE) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s") + +- if( ANDROID ) ++ if(ANDROID) + # I don't know why andorid's clang++ compiler will report "clang++: warning: argument unused during compilation: '-s' [-Wunused-command-line-argument]" + # so I add this to surpass warning + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Qunused-arguments") +@@ -68,73 +68,15 @@ else() + add_definitions(-Wall -Wextra) + endif() + +-if(ANDROID) +- option(ENABLE_ANDROID_LOG "Build with LogCat output" ON) +- if(ENABLE_ANDROID_LOG) +- add_definitions(-DENABLE_ANDROID_LOG=1) +- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -llog") +- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -llog") +- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -llog") +- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -llog") +- endif() +-endif() +- + # force 1.73 boost compiling warning note + add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS=1) + +-# badvpn definitions for tun2socks +-if(NOT MSVC) +- if(APPLE) +- add_definitions(-DBADVPN_FREEBSD=1) +- else() +- add_definitions(-DBADVPN_LINUX=1) +- endif() +-endif() +- +-add_definitions(-DBADVPN_THREADWORK_USE_PTHREAD=1 -DBADVPN_BREACTOR_BADVPN=1) +-add_definitions(-D_GNU_SOURCE=1 -DBADVPN_USE_SIGNALFD=1 -DBADVPN_USE_EPOLL=1) +-add_definitions(-DBADVPN_LITTLE_ENDIAN=1 -DBADVPN_THREAD_SAFE=1) +- + include_directories( + src +- src/tun/lwip_custom +- badvpn/lwip/src/include +- badvpn + ) + + set(TROJAN_SOURCE_FILES +- src/tun/lwip_custom/sys.c + +- badvpn/lwip/src/core/udp.c +- badvpn/lwip/src/core/memp.c +- badvpn/lwip/src/core/init.c +- badvpn/lwip/src/core/pbuf.c +- badvpn/lwip/src/core/tcp.c +- badvpn/lwip/src/core/tcp_out.c +- badvpn/lwip/src/core/netif.c +- badvpn/lwip/src/core/def.c +- badvpn/lwip/src/core/ip.c +- badvpn/lwip/src/core/mem.c +- badvpn/lwip/src/core/tcp_in.c +- badvpn/lwip/src/core/stats.c +- badvpn/lwip/src/core/inet_chksum.c +- badvpn/lwip/src/core/timeouts.c +- badvpn/lwip/src/core/ipv4/icmp.c +- badvpn/lwip/src/core/ipv4/igmp.c +- badvpn/lwip/src/core/ipv4/ip4_addr.c +- badvpn/lwip/src/core/ipv4/ip4_frag.c +- badvpn/lwip/src/core/ipv4/ip4.c +- badvpn/lwip/src/core/ipv4/autoip.c +- badvpn/lwip/src/core/ipv6/ethip6.c +- badvpn/lwip/src/core/ipv6/inet6.c +- badvpn/lwip/src/core/ipv6/ip6_addr.c +- badvpn/lwip/src/core/ipv6/mld6.c +- badvpn/lwip/src/core/ipv6/dhcp6.c +- badvpn/lwip/src/core/ipv6/icmp6.c +- badvpn/lwip/src/core/ipv6/ip6.c +- badvpn/lwip/src/core/ipv6/ip6_frag.c +- badvpn/lwip/src/core/ipv6/nd6.c +- + src/core/authenticator.cpp + src/core/config.cpp + src/core/log.cpp +@@ -161,45 +103,43 @@ set(TROJAN_SOURCE_FILES + src/ssl/ssldefaults.cpp + src/ssl/sslsession.cpp + +- src/tun/lwip_tcp_client.cpp +- src/tun/tundev.cpp +- src/tun/tunsession.cpp +- src/tun/tunproxysession.cpp +- src/tun/tunlocalsession.cpp +- src/tun/dnsserver.cpp +- src/tun/udplocalforwarder.cpp + ) + +-if(ANDROID) +- add_library(trojan SHARED ${TROJAN_SOURCE_FILES}) +-else() ++ + add_executable(trojan ${TROJAN_SOURCE_FILES}) +-endif() + + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) + target_link_libraries(trojan ${CMAKE_THREAD_LIBS_INIT}) + + # https://github.com/microsoft/GSL supported +-include_directories(${PROJECT_SOURCE_DIR}/GSL/include) +- ++#find_package(Microsoft.GSL CONFIG REQUIRED) ++if(${Microsoft.GSL_FOUND}) ++ message(STATUS "Found the Guidelines Support Library: ${Microsoft.GSL_DIR}") ++ target_link_libraries(trojan INTERFACE Microsoft.GSL::GSL) ++else() ++ set(GSL_URL https://github.com/Microsoft/GSL) ++ set(GSL_VERSION 0f6dbc9) ++ message(STATUS "Using and shipping ${GSL_URL} version ${GCL_VERSION}") ++ set(GSL_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/GSL) ++ if(NOT EXISTS ${GSL_DIR}) ++ execute_process(COMMAND git clone ${GSL_URL} ${GSL_DIR}) ++ endif() ++ execute_process(COMMAND git checkout ${GSL_VERSION} WORKING_DIRECTORY ${GSL_DIR}) ++ #install(DIRECTORY ${GSL_DIR}/gsl DESTINATION include) ++ #install(FILES ${GSL_DIR}/LICENSE DESTINATION include/gsl/LICENSE) ++ set(GSL_INCLUDE_DIR NAMES ${GSL_DIR}) ++ if(GSL_INCLUDE_DIR) ++ set(GSL_INCLUDE_DIRS ${GSL_INCLUDE_DIR}/include) ++ include_directories(${GSL_INCLUDE_DIRS}) ++ set(GSL_FOUND TRUE) ++ endif() ++endif() ++ + # for cland-tidy compiling database by default the file is small, generation is cheap + # as developer, I am always add this option... + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +-if (ANDROID) +- set(ANDROID_MY_LIBS ${PROJECT_SOURCE_DIR}/trojan-plus-android-libs) +- set(ANDROID_MY_LIBS_LIBRARIES +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libssl.a +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libcrypto.a +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libboost_system.a +- ${ANDROID_MY_LIBS}/lib/${ANDROID_ABI}/libboost_program_options.a) +- +- set(OPENSSL_VERSION 1.1.1) +- +- include_directories(${ANDROID_MY_LIBS}/include) +- target_link_libraries(trojan ${ANDROID_MY_LIBS_LIBRARIES}) +-else() + find_package(Boost 1.66.0 REQUIRED COMPONENTS system program_options) + include_directories(${Boost_INCLUDE_DIR}) + target_link_libraries(trojan ${Boost_LIBRARIES}) +@@ -210,7 +150,6 @@ else() + find_package(OpenSSL 1.1.0 REQUIRED) + include_directories(${OPENSSL_INCLUDE_DIR}) + target_link_libraries(trojan ${OPENSSL_LIBRARIES}) +-endif() + + if(OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1.1) + option(ENABLE_SSL_KEYLOG "Build with SSL KeyLog support" ON) +@@ -229,7 +168,7 @@ if(FORCE_TCP_FASTOPEN) + add_definitions(-DTCP_FASTOPEN=23 -DTCP_FASTOPEN_CONNECT=30) + endif() + +-if(NOT ANDROID) ++if(NOT ANDROID) + option(ENABLE_MYSQL "Build with MySQL support" ON) + if(ENABLE_MYSQL) + find_package(MySQL REQUIRED) +@@ -301,4 +240,3 @@ if(NOT ANDROID) + endif() + endif() + +- +diff --git a/GSL b/GSL +deleted file mode 160000 +index 98002ab..0000000 +--- a/GSL ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit 98002ab60135fe70f4acd7e5b8a34f9ad1427807 +diff --git a/badvpn b/badvpn +deleted file mode 160000 +index 01feab8..0000000 +--- a/badvpn ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit 01feab854625d1cc0e0391db394dd305b6dd1815 +diff --git a/src/core/pipeline.cpp b/src/core/pipeline.cpp +index 4dd0cbf..8fa5bce 100644 +--- a/src/core/pipeline.cpp ++++ b/src/core/pipeline.cpp +@@ -23,7 +23,6 @@ + #include "core/utils.h" + #include "proto/pipelinerequest.h" + #include "session/clientsession.h" +-#include "tun/tunsession.h" + + using namespace std; + using namespace boost::asio::ip; +diff --git a/src/core/service.cpp b/src/core/service.cpp +index e439e8c..e597c6e 100644 +--- a/src/core/service.cpp ++++ b/src/core/service.cpp +@@ -36,9 +36,6 @@ + #include "session/serversession.h" + #include "utils.h" + +-#include "tun/dnsserver.h" +-#include "tun/tundev.h" +- + using namespace std; + using namespace boost::asio::ip; + using namespace boost::asio::ssl; +@@ -58,12 +55,6 @@ Service::Service(Config& config, bool test) + #endif // ENABLE_NAT + + if (!test) { +- if (config.get_run_type() == Config::CLIENT_TUN || config.get_run_type() == Config::SERVERT_TUN) { +- m_tundev = make_shared(this, config.get_tun().tun_name, config.get_tun().net_ip, +- config.get_tun().net_mask, config.get_tun().mtu, config.get_tun().tun_fd); +- } +- +- if (config.get_run_type() != Config::CLIENT_TUN) { + tcp::resolver resolver(io_context); + tcp::endpoint listen_endpoint = + *resolver.resolve(config.get_local_addr(), to_string(config.get_local_port())).begin(); +@@ -119,7 +110,6 @@ Service::Service(Config& config, bool test) + _log_with_date_time("TCP_FASTOPEN_CONNECT is not supported", Log::WARN); + #endif // TCP_FASTOPEN_CONNECT + } +- } + } + + config.prepare_ssl_context(ssl_context, plain_http_response); +@@ -134,25 +124,6 @@ Service::Service(Config& config, bool test) + } + } + +- if (!test && config.get_dns().enabled) { +- if (config.get_run_type() == Config::SERVER || config.get_run_type() == Config::FORWARD) { +- _log_with_date_time("[dns] dns server cannot run in type 'server' or 'forward'", Log::ERROR); +- } else { +- if (DNSServer::get_dns_lock()) { +- m_dns_server = make_shared(this); +- if (m_dns_server->start()) { +- _log_with_date_time( +- "[dns] start local dns server at 0.0.0.0:" + to_string(config.get_dns().port), Log::WARN); +- +- if (m_tundev != nullptr) { +- m_tundev->set_dns_server(m_dns_server); +- } +- } +- } else { +- _log_with_date_time("[dns] dns server has been created in other process.", Log::WARN); +- } +- } +- } + } + + void Service::prepare_icmpd(Config& config, bool is_ipv4) { +@@ -175,10 +146,6 @@ void Service::run() { + rt = "nat"; + } else if (config.get_run_type() == Config::CLIENT) { + rt = "client"; +- } else if (config.get_run_type() == Config::CLIENT_TUN) { +- rt = "client tun"; +- } else if (config.get_run_type() == Config::SERVERT_TUN) { +- rt = "server tun"; + } else { + throw logic_error("unknow run type error"); + } +@@ -187,7 +154,6 @@ void Service::run() { + rt += " in pipeline mode"; + } + +- if (config.get_run_type() != Config::CLIENT_TUN) { + async_accept(); + if (config.get_run_type() == Config::FORWARD || config.get_run_type() == Config::NAT) { + udp_async_read(); +@@ -197,18 +163,11 @@ void Service::run() { + _log_with_date_time(string("trojan plus service (") + rt + ") started at " + + local_endpoint.address().to_string() + ':' + to_string(local_endpoint.port()), + Log::FATAL); +- } else { +- _log_with_date_time(string("trojan plus service (") + rt + ") started at [" + config.get_tun().tun_name + "] " + +- config.get_tun().net_ip + "/" + config.get_tun().net_mask, +- Log::FATAL); +- } + io_context.run(); + _log_with_date_time("trojan service stopped", Log::WARN); + } + + void Service::stop() { +- m_tundev = nullptr; +- m_dns_server = nullptr; + boost::system::error_code ec; + socket_acceptor.cancel(ec); + if (udp_socket.is_open()) { +diff --git a/src/core/service.h b/src/core/service.h +index 07e6e0f..5361e5d 100644 +--- a/src/core/service.h ++++ b/src/core/service.h +@@ -38,8 +38,6 @@ + #include "session/session.h" + #include "session/udpforwardsession.h" + +-class TUNDev; +-class DNSServer; + class Pipeline; + class icmpd; + class Service { +@@ -66,8 +64,6 @@ class Service { + std::shared_ptr icmp_processor; + void prepare_icmpd(Config& config, bool is_ipv4); + +- std::shared_ptr m_dns_server; +- std::shared_ptr m_tundev; + SendingDataAllocator m_sending_data_allocator; + + const Config& config; +diff --git a/src/tun/dnsserver.cpp b/src/tun/dnsserver.cpp +deleted file mode 100644 +index d19aa33..0000000 +--- a/src/tun/dnsserver.cpp ++++ /dev/null +@@ -1,278 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "dnsserver.h" +-#include "core/service.h" +-#include "proto/dns_header.h" +-#include "tun/udplocalforwarder.h" +-#include +-#include +- +-using namespace std; +-using namespace boost::asio::ip; +-using namespace trojan; +- +-FILE_LOCK_HANDLE DNSServer::s_dns_file_lock = INVALID_LOCK_HANDLE; +-bool DNSServer::get_dns_lock() { +- s_dns_file_lock = get_file_lock("./trojan_dns_lock.output"); +- return s_dns_file_lock != INVALID_LOCK_HANDLE; +-} +- +-DNSServer::DNSServer(Service* _service) : m_service(_service), m_serv_udp_socket(_service->get_io_context()) {} +- +-DNSServer::~DNSServer() { close_file_lock(s_dns_file_lock); } +- +-bool DNSServer::start() { +- boost::system::error_code ec; +- +- auto udp_bind_endpoint = udp::endpoint(make_address_v4("0.0.0.0"), m_service->get_config().get_dns().port); +- auto udp_protocol = udp_bind_endpoint.protocol(); +- +- m_serv_udp_socket.open(udp_protocol, ec); +- if (ec) { +- output_debug_info_ec(ec); +- return false; +- } +- m_serv_udp_socket.bind(udp_bind_endpoint, ec); +- if (ec) { +- output_debug_info_ec(ec); +- return false; +- } +- +- async_read_udp(); +- return true; +-} +- +-bool DNSServer::is_proxy_dns_msg(const dns_header& dns_hdr) { +- return dns_hdr.QR() == 0 && dns_hdr.RCODE() == 0 && dns_hdr.ANCOUNT() == 0 && dns_hdr.NSCOUNT() == 0 && +- dns_hdr.QDCOUNT() > 0; +-} +- +-bool DNSServer::is_proxy_dns_msg(const trojan::dns_question& qt) { +- return qt.get_QCLASS() == dns_header::QCLASS_INTERNET && +- (qt.get_QTYPE() == dns_header::QTYPE_A_RECORD || qt.get_QTYPE() == dns_header::QTYPE_AAAA_RECORD); +-} +- +-bool DNSServer::is_in_gfwlist(const string& domain) const { +- const auto& gfwlist = m_service->get_config().get_dns()._gfwlist; +- for (size_t start_size = domain.size(); start_size > 0; start_size--) { +- const auto& it = gfwlist.find(start_size); +- if (it != gfwlist.end()) { +- for (const auto& d : it->second) { +- int i = int(d.size() - 1); +- int j = int(domain.size() - 1); +- for (; i >= 0 && j >= 0; i--, j--) { +- if (d[i] != domain[j]) { +- break; +- } +- } +- +- if (i < 0) { +- return true; +- } +- } +- } +- } +- +- return false; +-} +- +-bool DNSServer::try_to_find_existed(const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data) { +- clear_weak_ptr_list(m_proxy_forwarders); +- clear_weak_ptr_list(m_forwarders); +- +- for (const auto& f : m_proxy_forwarders) { +- if (f.lock()->process(local_src, data)) { +- return true; +- } +- } +- +- for (const auto& f : m_forwarders) { +- if (f.lock()->process(local_src, data)) { +- return true; +- } +- } +- +- return false; +-} +-bool DNSServer::find_in_dns_cache( +- const udp::endpoint& local_src, const dns_header& header, const dns_question& question) { +- if (m_service->get_config().get_dns().enable_cached) { +- auto curr_time = time(nullptr); +- +- auto it = m_dns_cache.begin(); +- while (it != m_dns_cache.end()) { +- if (it->expired(curr_time)) { +- it = m_dns_cache.erase(it); +- } else { +- it++; +- } +- } +- +- for (auto& c : m_dns_cache) { +- if (c.get_domain() == question.get_QNAME()) { +- _log_with_endpoint_ALL(local_src, "[dns] find " + question.get_QNAME() + " in cache ttl: " + +- to_string(c.get_ttl() - (curr_time - c.get_cached_time()))); +- +- std::string& raw_data = c.get_answer_data(); +- raw_data[0] = header.ID() >> one_byte_shift_8_bits; +- raw_data[1] = header.ID() & one_byte_mask_0xFF; +- +- send_to_local(local_src, raw_data); +- return true; +- } +- } +- } +- +- return false; +-} +- +-void DNSServer::store_in_dns_cache(const string_view& data, bool proxyed) { +- if (m_service->get_config().get_dns().enable_cached) { +- string read_data(data); +- istringstream is(read_data); +- +- dns_answer answer; +- if (is >> answer) { +- if (!answer.get_questions().empty() && is_proxy_dns_msg(answer.get_questions()[0])) { +- +- const auto& domain = answer.get_questions()[0].get_QNAME(); +- uint32_t ttl = numeric_limits::max(); +- vector A_list; +- for (const auto& an : answer.get_answers()) { +- if (an.A != 0) { +- if (ttl > an.TTL) { // find min +- ttl = an.TTL; +- } +- +- A_list.emplace_back(an.A); +- } +- } +- +- if (ttl != numeric_limits::max()) { +- sort(A_list.begin(), A_list.end()); +- m_dns_cache.emplace_back(DNSCache(domain, ttl, A_list, proxyed, data)); +- _log_with_date_time_ALL("[dns] cache " + domain + " in ttl: " + to_string(ttl)); +- } +- } +- } +- } +-} +- +-void DNSServer::send_to_local(const udp::endpoint& local_src, const string_view& data) { +- _log_with_endpoint_ALL(local_src, "[dns] <-- " + to_string(data.length())); +- +- boost::system::error_code ec; +- m_serv_udp_socket.send_to(boost::asio::buffer(data), local_src, 0, ec); +-} +- +-void DNSServer::recv_up_stream_data(const udp::endpoint& local_src, const string_view& data, bool proxyed) { +- send_to_local(local_src, data); +- store_in_dns_cache(data, proxyed); +-} +- +-void DNSServer::in_recved(istream& is, const dns_header& header, const string_view& former_data) { +- bool proxy = false; +- dns_question qt; +- is >> qt; +- if (is) { +- if (is_proxy_dns_msg(qt)) { +- if (find_in_dns_cache(m_udp_recv_endpoint, header, qt)) { +- return; +- } +- proxy = is_in_gfwlist(qt.get_QNAME()); +- } +- } +- +- if (try_to_find_existed(m_udp_recv_endpoint, m_udp_read_buf)) { +- return; +- } +- +- if (proxy) { +- auto up_stream_ns_svr = m_service->get_config().get_dns().up_gfw_dns_server.at(0); +- auto dst = make_pair(up_stream_ns_svr, DEFAULT_UP_STREAM_NS_SVR_PORT); +- auto forwarder = make_shared( +- m_service, m_service->get_config(), m_service->get_ssl_context(), m_udp_recv_endpoint, dst, +- [this](const udp::endpoint& endpoint, const string_view& data) { recv_up_stream_data(endpoint, data, true); }, +- false, true); +- +- auto data = m_service->get_sending_data_allocator().allocate(former_data); +- m_service->start_session(forwarder, [this, forwarder, data](boost::system::error_code ec) { +- if (!ec) { +- m_proxy_forwarders.emplace_back(forwarder); +- forwarder->start_udp(streambuf_to_string_view(*data)); +- } +- m_service->get_sending_data_allocator().free(data); +- }); +- +- } else { +- auto up_stream_ns_svr = m_service->get_config().get_dns().up_dns_server.at(0); +- auto dst = udp::endpoint(make_address(up_stream_ns_svr), DEFAULT_UP_STREAM_NS_SVR_PORT); +- auto forwarder = make_shared( +- m_service, m_udp_recv_endpoint, dst, +- [this]( +- const udp::endpoint& endpoint, const string_view& data) { recv_up_stream_data(endpoint, data, false); }, +- true); +- +- forwarder->start(); +- +- if (forwarder->process(m_udp_recv_endpoint, former_data)) { +- m_forwarders.emplace_back(forwarder); +- } +- } +-} +-void DNSServer::async_read_udp() { +- auto self = shared_from_this(); +- auto prepare_size = m_service->get_config().get_udp_recv_buf(); +- m_udp_read_buf.begin_read(__FILE__, __LINE__); +- m_udp_read_buf.consume_all(); +- m_serv_udp_socket.async_receive_from(m_udp_read_buf.prepare(prepare_size), m_udp_recv_endpoint, +- [self, this](const boost::system::error_code error, size_t length) { +- m_udp_read_buf.end_read(); +- if (error) { +- async_read_udp(); +- return; +- } +- +- m_udp_read_buf.commit(length); +- const string_view& former_data = m_udp_read_buf; +- std::istream is(&(boost::asio::streambuf&)m_udp_read_buf); +- +- dns_header dns_hdr; +- is >> dns_hdr; +- +- if (is && is_proxy_dns_msg(dns_hdr)) { +- in_recved(is, dns_hdr, former_data); +- } +- +- async_read_udp(); +- }); +-} +- +-bool DNSServer::is_ip_in_gfwlist(uint32_t ip) const { +- for (const auto& dns : m_dns_cache) { +- if (dns.is_proxyed() && binary_search(dns.get_ips().cbegin(), dns.get_ips().cend(), ip)) { +- return true; +- } +- } +- +- return false; +-} +diff --git a/src/tun/dnsserver.h b/src/tun/dnsserver.h +deleted file mode 100644 +index f46d53d..0000000 +--- a/src/tun/dnsserver.h ++++ /dev/null +@@ -1,107 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_DNS_SERVER_HPP +-#define _TROJAN_DNS_SERVER_HPP +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "core/utils.h" +-#include "proto/dns_header.h" +- +-class UDPForwardSession; +-class UDPLocalForwarder; +-class Service; +-class DNSServer : public std::enable_shared_from_this { +- +- enum { DEFAULT_UP_STREAM_NS_SVR_PORT = 53 }; +- +- class DNSCache { +- std::string domain; +- int ttl; +- std::vector ips; +- bool proxyed; +- time_t cached_time{time(nullptr)}; +- std::string answer_data; +- +- public: +- DNSCache( +- std::string _domain, int _ttl, std::vector& _ips, bool _proxyed, const std::string_view& data) +- : domain(std::move(_domain)), ttl(_ttl), ips(move(_ips)), proxyed(_proxyed), answer_data(data) {} +- +- [[nodiscard]] inline bool expired(time_t curr) const { return int(curr - cached_time) >= ttl; } +- +- _define_getter_const(const std::string&, domain); +- _define_getter_const(int, ttl); +- _define_getter_const(const std::vector&, ips); +- _define_getter_const(time_t, cached_time); +- _define_is_const(proxyed); +- +- _define_getter(std::string&, answer_data); +- }; +- +- Service* m_service; +- +- std::vector m_dns_cache; +- boost::asio::ip::udp::socket m_serv_udp_socket; +- ReadBufWithGuard m_udp_read_buf; +- boost::asio::ip::udp::endpoint m_udp_recv_endpoint; +- +- std::list> m_proxy_forwarders; +- std::list> m_forwarders; +- +- void in_recved(std::istream& is, const trojan::dns_header& header, const std::string_view& former_data); +- void async_read_udp(); +- void recv_up_stream_data( +- const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data, bool proxyed); +- void send_to_local(const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data); +- bool find_in_dns_cache(const boost::asio::ip::udp::endpoint& local_src, const trojan::dns_header& header, +- const trojan::dns_question& question); +- void store_in_dns_cache(const std::string_view& data, bool proxyed); +- +- [[nodiscard]] bool is_in_gfwlist(const std::string& domain) const; +- +- [[nodiscard]] bool try_to_find_existed( +- const boost::asio::ip::udp::endpoint& local_src, const std::string_view& data); +- +- [[nodiscard]] static bool is_proxy_dns_msg(const trojan::dns_header& hdr); +- +- [[nodiscard]] static bool is_proxy_dns_msg(const trojan::dns_question& question); +- +- static FILE_LOCK_HANDLE s_dns_file_lock; +- +- public: +- DNSServer(Service* _service); +- ~DNSServer(); +- +- [[nodiscard]] bool start(); +- [[nodiscard]] bool is_ip_in_gfwlist(uint32_t ip) const; +- +- [[nodiscard]] static bool get_dns_lock(); +-}; +- +-#endif //_TROJAN_DNS_SERVER_HPP +diff --git a/src/tun/lwip_custom/arch/cc.h b/src/tun/lwip_custom/arch/cc.h +deleted file mode 100644 +index 6554989..0000000 +--- a/src/tun/lwip_custom/arch/cc.h ++++ /dev/null +@@ -1,79 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef LWIP_CUSTOM_CC_H +-#define LWIP_CUSTOM_CC_H +- +-#include +-#include +-#include +-#include +- +-#include +- +-#ifndef _WIN32 +- #define PACK_STRUCT_BEGIN +- #define PACK_STRUCT_END +- #if defined(__GNUC__) && defined(__MINGW32__) +- // Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 +- #define PACK_STRUCT_STRUCT __attribute__((packed)) __attribute__((gcc_struct)) +- #else +- #define PACK_STRUCT_STRUCT __attribute__((packed)) +- #endif +-#else +- #define PACK_STRUCT_BEGIN +- #define PACK_STRUCT_END +- #define PACK_STRUCT_STRUCT +-#endif //_WIN32 +- +- +-#define LWIP_PLATFORM_DIAG(x) { fprintf(stdout, "%s: lwip diag failure: %s\n", __FUNCTION__, (x)); } +-#define LWIP_PLATFORM_ASSERT(x) { fprintf(stderr, "%s: lwip assertion failure: %s\n", __FUNCTION__, (x)); abort(); } +- +-#define lwip_htons(x) hton16(x) +-#define lwip_htonl(x) hton32(x) +- +-#define LWIP_RAND() ( \ +- (((uint32_t)(rand() & 0xFF)) << 24) | \ +- (((uint32_t)(rand() & 0xFF)) << 16) | \ +- (((uint32_t)(rand() & 0xFF)) << 8) | \ +- (((uint32_t)(rand() & 0xFF)) << 0) \ +-) +- +-// for BYTE_ORDER +-#if defined(BADVPN_USE_WINAPI) && !defined(_MSC_VER) +- #include +-#elif defined(BADVPN_LINUX) +- #include +-#elif defined(BADVPN_FREEBSD) +- #include +-#else +- #define LITTLE_ENDIAN 1234 +- #define BIG_ENDIAN 4321 +- #if defined(BADVPN_LITTLE_ENDIAN) +- #define BYTE_ORDER LITTLE_ENDIAN +- #else +- #define BYTE_ORDER BIG_ENDIAN +- #endif +-#endif +- +- +-#endif +diff --git a/src/tun/lwip_custom/lwipopts.h b/src/tun/lwip_custom/lwipopts.h +deleted file mode 100644 +index dd83db7..0000000 +--- a/src/tun/lwip_custom/lwipopts.h ++++ /dev/null +@@ -1,84 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef LWIP_CUSTOM_LWIPOPTS_H +-#define LWIP_CUSTOM_LWIPOPTS_H +- +-#define NO_SYS 1 +-#define LWIP_TIMERS 0 +-#define MEM_ALIGNMENT 4 +- +-#define LWIP_ARP 0 +-#define ARP_QUEUEING 0 +-#define IP_FORWARD 0 +-#define LWIP_ICMP 1 +-#define LWIP_RAW 0 +-#define LWIP_DHCP 0 +-#define LWIP_AUTOIP 0 +-#define LWIP_SNMP 0 +-#define LWIP_IGMP 0 +-#define LWIP_DNS 0 +-#define LWIP_UDP 0 +-#define LWIP_UDPLITE 0 +-#define LWIP_TCP 1 +-#define LWIP_CALLBACK_API 1 +-#define LWIP_NETIF_API 0 +-#define LWIP_NETIF_LOOPBACK 0 +-#define LWIP_HAVE_LOOPIF 0 +-#define LWIP_HAVE_SLIPIF 0 +-#define LWIP_NETCONN 0 +-#define LWIP_SOCKET 0 +-#define PPP_SUPPORT 0 +-#define LWIP_IPV6 1 +-#define LWIP_IPV6_MLD 0 +-#define LWIP_IPV6_AUTOCONFIG 0 +-#define LWIP_WND_SCALE 1 +-#define TCP_RCV_SCALE 5 +- +-#define MEMP_NUM_TCP_PCB_LISTEN 16 +-#define MEMP_NUM_TCP_PCB 1024 +-#ifndef TCP_MSS +-#define TCP_MSS 1460 +-#endif //TCP_MSS +-#define TCP_SND_BUF 16384 +-#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS)) +- +-#define MEM_LIBC_MALLOC 1 +-#define MEMP_MEM_MALLOC 1 +- +-#define LWIP_PERF 0 +-#define SYS_LIGHTWEIGHT_PROT 0 +-#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +- +-// needed on 64-bit systems, enable it always so that the same configuration +-// is used regardless of the platform +-#define IPV6_FRAG_COPYHEADER 1 +- +-/* +-#define LWIP_DEBUG 1 +-#define IP_DEBUG LWIP_DBG_ON +-#define NETIF_DEBUG LWIP_DBG_ON +-#define TCP_DEBUG LWIP_DBG_ON +-#define TCP_INPUT_DEBUG LWIP_DBG_ON +-#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +-*/ +- +-#endif +diff --git a/src/tun/lwip_custom/sys.c b/src/tun/lwip_custom/sys.c +deleted file mode 100644 +index d32febd..0000000 +--- a/src/tun/lwip_custom/sys.c ++++ /dev/null +@@ -1,29 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2017-2020 The Trojan Authors. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include +-#include +- +-u32_t sys_now (void) +-{ +- return (u32_t)time(NULL); +-} +diff --git a/src/tun/lwip_tcp_client.cpp b/src/tun/lwip_tcp_client.cpp +deleted file mode 100644 +index b63a46d..0000000 +--- a/src/tun/lwip_tcp_client.cpp ++++ /dev/null +@@ -1,273 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2017-2020 The Trojan Authors. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "lwip_tcp_client.h" +- +-#include +-#include +-#include +- +-#include "core/log.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-lwip_tcp_client::lwip_tcp_client(struct tcp_pcb* _pcb, shared_ptr _session, CloseCallback&& _close_cb) +- : m_pcb(_pcb), m_closed(false), m_aborted(false), m_tun_session(move(_session)), m_close_cb(move(_close_cb)) { +- +- // special for reverse local to remote +- m_remote_addr = +- tcp::endpoint(make_address_v4((address_v4::uint_type)ntoh32(_pcb->local_ip.u_addr.ip4.addr)), _pcb->local_port); +- m_local_addr = +- tcp::endpoint(make_address_v4((address_v4::uint_type)ntoh32(_pcb->remote_ip.u_addr.ip4.addr)), _pcb->remote_port); +- +- m_tun_session->set_tcp_connect(m_local_addr, m_remote_addr); +- m_tun_session->set_write_to_lwip( +- [this](const TUNSession*, const std::string_view*) { return client_socks_recv_send_out(); }); +- +- m_tun_session->set_close_callback([this](TUNSession* session) { +- if (session->recv_buf_ack_length() == 0) { // need to wait send remain buff +- output_debug_info(); +- close_client(false); +- } +- }); +- +- tcp_arg(m_pcb, this); +- +- // setup handlers +- tcp_err(m_pcb, static_client_err_func); +- tcp_recv(m_pcb, static_client_recv_func); +- tcp_sent(m_pcb, static_client_sent_func); +- +- client_log("accepted"); +-} +- +-void lwip_tcp_client::client_log(const char* fmt, ...) { +- const auto logout_level = Log::INFO; +- +- if (Log::level <= logout_level) { +- const int buf_size = 256; +- char buf[buf_size]; +- int n = snprintf((char*)buf, buf_size, "[lwip] [%s:%d->%s:%d] [pcb:0x%llx session_id: %d] ", +- m_local_addr.address().to_string().c_str(), m_local_addr.port(), m_remote_addr.address().to_string().c_str(), +- m_remote_addr.port(), (unsigned long long)m_pcb, (int)m_tun_session->get_session_id()); +- +- va_list vl; +- va_start(vl, fmt); +- vsnprintf(buf + n, buf_size - n, fmt, vl); +- va_end(vl); +- +- _log_with_date_time(buf, logout_level); +- } +-} +- +-void lwip_tcp_client::client_err_func(err_t err) { +- client_log("client_err_func (%d)", (int)err); +- +- // do NOT call close_client with tcp_close/tcp_abort, otherwise it will assert to free double +- // this client_err_func will be called by lwip and then lwip system will be free pcb +- close_session(); +- release_client(false); +-} +- +-err_t lwip_tcp_client::client_recv_func(struct tcp_pcb*, struct pbuf* p, err_t err) { +- +- if (m_aborted) { +- return ERR_ABRT; +- } +- +- if (p == nullptr || err != ERR_OK) { +- client_log("client_recv_func closed (%d)", (int)err); +- close_client(false); +- } else { +- +- if (m_tun_session->is_destroyed()) { +- client_log("m_tun_session->is_destroyed closed"); +- output_debug_info(); +- close_client(true); +- return ERR_ABRT; +- } +- +- assert(p->tot_len > 0); +- if (p->tot_len > sizeof(send_buf)) { +- return ERR_MEM; +- } +- +- // copy data to buffer +- auto length = pbuf_copy_partial(p, (void*)send_buf, p->tot_len, 0); +- assert(length == p->tot_len); +- pbuf_free(p); +- m_sending_len += length; +- m_tun_session->out_async_send((const uint8_t*)send_buf, length, [this, length](boost::system::error_code ec) { +- if (ec) { +- output_debug_info_ec(ec); +- close_client(true); +- } else { +- if (!m_closed) { +- tcp_recved(m_pcb, length); +- m_sent_len += length; +- } +- } +- }); +- } +- +- return ERR_OK; +-} +- +-err_t lwip_tcp_client::client_sent_func(struct tcp_pcb*, u16_t len) { +- +- if (m_aborted) { +- return ERR_ABRT; +- } +- +- m_recved_len += len; +- m_tun_session->recv_buf_ack_sent(len); +- +- if (m_tun_session->is_destroyed()) { +- if (m_tun_session->recv_buf_ack_length() > 0) { +- if (client_socks_recv_send_out() < 0) { +- return ERR_ABRT; +- } +- +- return ERR_OK; +- } +- output_debug_info(); +- close_client(false); +- return ERR_OK; +- } +- +- if (client_socks_recv_send_out() < 0) { +- return ERR_ABRT; +- } +- +- return ERR_OK; +-} +- +-int lwip_tcp_client::client_socks_recv_send_out() { +- if (m_aborted) { +- return -1; +- } +- +- if (m_closed) { +- return 0; +- } +- +- auto recv_size = m_tun_session->recv_buf_size(); +- if (recv_size == 0) { +- return 0; +- } +- +- const auto* recv_data = m_tun_session->recv_buf(); +- size_t wrote_size = 0; +- do { +- +- auto to_write = min(recv_size, (size_t)tcp_sndbuf(m_pcb)); +- if (to_write == 0) { +- break; +- } +- +- err_t err = tcp_write(m_pcb, (const void*)(recv_data + wrote_size), (uint16_t)to_write, TCP_WRITE_FLAG_COPY); +- if (err != ERR_OK) { +- if (err == ERR_MEM) { +- break; +- } +- +- client_log("tcp_write failed (%d)", (int)err); +- close_client(true); +- return -1; +- } +- +- recv_size -= to_write; +- wrote_size += to_write; +- } while (recv_size > 0); +- +- // start sending now +- err_t err = tcp_output(m_pcb); +- if (err != ERR_OK) { +- client_log("tcp_output failed (%d)", (int)err); +- close_client(true); +- return -1; +- } +- +- m_output_len += wrote_size; +- m_tun_session->recv_buf_consume((uint16_t)wrote_size); +- return 0; +-} +- +-void lwip_tcp_client::close_session() { +- if (m_closed || m_aborted) { +- return; +- } +- +- m_closed = true; +- +- // remove callbacks +- tcp_err(m_pcb, nullptr); +- tcp_recv(m_pcb, nullptr); +- tcp_sent(m_pcb, nullptr); +- +- if (!m_tun_session->is_destroyed()) { +- output_debug_info(); +- m_tun_session->destroy(true); +- } +- +- client_log("close_session (output: %u, recved: %u), (sending: %u, sent: %u)", m_output_len, m_recved_len, +- m_sending_len, m_sent_len); +-} +- +-void lwip_tcp_client::close_client(bool _abort, bool _owner_call /*= false*/) { +- if (m_closed || m_aborted) { +- return; +- } +- +- close_session(); +- +- if (_abort) { +- client_log("close_client abort"); +- m_aborted = true; +- tcp_abort(m_pcb); +- } else { +- // free m_pcb +- err_t err = tcp_close(m_pcb); +- client_log("close_client"); +- if (err != ERR_OK) { +- client_log("tcp_close failed (%d)", err); +- m_aborted = true; +- // abort the PCB +- tcp_abort(m_pcb); +- } +- } +- +- release_client(_owner_call); +-} +- +-void lwip_tcp_client::release_client(bool _owner_call /*=false*/) { +- if (m_pcb != nullptr) { +- tcp_arg(m_pcb, nullptr); +- m_pcb = nullptr; +- +- if (!_owner_call && m_close_cb) { +- // this callback will trigger decontructor +- m_close_cb(this); +- } +- } +-} +diff --git a/src/tun/lwip_tcp_client.h b/src/tun/lwip_tcp_client.h +deleted file mode 100644 +index f10c32f..0000000 +--- a/src/tun/lwip_tcp_client.h ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_LWIP_TCP_CLIENT_HPP +-#define _TROJAN_LWIP_TCP_CLIENT_HPP +- +-#include +- +-#include +-#include +-#include +-#include +- +-#include "core/service.h" +-#include "tun/tunsession.h" +- +-class lwip_tcp_client : public std::enable_shared_from_this { +- +- static void static_client_err_func(void* arg, err_t err) { ((lwip_tcp_client*)arg)->client_err_func(err); } +- +- static err_t static_client_recv_func(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err) { +- return ((lwip_tcp_client*)arg)->client_recv_func(tpcb, p, err); +- } +- +- static err_t static_client_sent_func(void* arg, struct tcp_pcb* tpcb, uint16_t len) { +- return ((lwip_tcp_client*)arg)->client_sent_func(tpcb, len); +- } +- +- public: +- typedef std::function CloseCallback; +- +- private: +- boost::asio::ip::tcp::endpoint m_local_addr; +- boost::asio::ip::tcp::endpoint m_remote_addr; +- +- struct tcp_pcb* m_pcb; +- bool m_closed; +- bool m_aborted; +- +- size_t m_recved_len{}; +- size_t m_output_len{}; +- +- size_t m_sending_len{}; +- size_t m_sent_len{}; +- +- uint8_t send_buf[TCP_WND]{}; +- std::shared_ptr m_tun_session; +- CloseCallback m_close_cb; +- +- void close_session(); +- void release_client(bool _owner_call = false); +- void client_log(const char* fmt, ...); +- int client_socks_recv_send_out(); +- +- void client_err_func(err_t err); +- err_t client_recv_func(struct tcp_pcb* tpcb, struct pbuf* p, err_t err); +- err_t client_sent_func(struct tcp_pcb* tpcb, u16_t len); +- +- public: +- lwip_tcp_client(struct tcp_pcb* _pcb, std::shared_ptr _session, CloseCallback&& _close_cb); +- void close_client(bool _abort, bool _owner_call = false); +-}; +-#endif //_TROJAN_LWIP_TCP_CLIENT_HPP +\ No newline at end of file +diff --git a/src/tun/tundev.cpp b/src/tun/tundev.cpp +deleted file mode 100644 +index 116f0b8..0000000 +--- a/src/tun/tundev.cpp ++++ /dev/null +@@ -1,644 +0,0 @@ +- +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tundev.h" +- +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include "proto/ipv4_header.h" +-#include "proto/ipv6_header.h" +- +-#include "core/log.h" +-#include "core/service.h" +-#include "tun/dnsserver.h" +-#include "tun/lwip_tcp_client.h" +-#include "tun/tunlocalsession.h" +-#include "tun/tunproxysession.h" +-#include "tun/tunsession.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-// clang-format off +-static const uint32_t mask_values[] = { +- 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, +- 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, +- 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, +- 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, +- 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, +- 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, +- 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, +- 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF, +-}; +-// clang-format on +- +-static void tcp_remove(struct tcp_pcb* pcb_list) { +- struct tcp_pcb* pcb = pcb_list; +- struct tcp_pcb* pcb2 = nullptr; +- +- while (pcb != nullptr) { +- pcb2 = pcb; +- pcb = pcb->next; +- tcp_abort(pcb2); +- } +-} +- +-TUNDev* TUNDev::sm_tundev = nullptr; +- +-TUNDev::TUNDev(Service* _service, const std::string& _tun_name, const std::string& _ipaddr, const std::string& _netmask, +- uint16_t _mtu, int _outside_tun_fd) +- : m_netif_configured(false), +- m_tcp_listener(nullptr), +- m_service(_service), +- m_tun_fd(_outside_tun_fd), +- m_is_outside_tun_fd(_outside_tun_fd != -1), +- m_mtu(_mtu), +- m_quitting(false), +- m_boost_sd(_service->get_io_context()) { +- +- assert(sm_tundev == nullptr); +- sm_tundev = this; +- +- if (m_tun_fd == -1) { +-#ifdef __linux__ +- // open TUN device, check detail information: +- // https://www.kernel.org/doc/Documentation/networking/tuntap.txt +- if ((m_tun_fd = open("/dev/net/tun", O_RDWR)) < 0) { +- throw runtime_error("[tun] error opening device"); +- } +- +- struct ifreq ifr {}; +- ifr.ifr_flags = IFF_NO_PI | IFF_TUN; +- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", _tun_name.c_str()); +- +- if (ioctl(m_tun_fd, TUNSETIFF, (void*)&ifr) < 0) { +- throw runtime_error("[tun] error configuring device"); +- } +- +- _log_with_date_time("[tun] /dev/net/tun ifr.ifr_mtu: " + to_string(ifr.ifr_mtu), Log::WARN); +-#else +- throw logic_error("[tun] cannot enable tun run type in NON-linux system ! " + _tun_name); +-#endif //__linux__ +- } +- +- m_boost_sd.assign(m_tun_fd); +- +- // init lwip +- lwip_init(); +- +- // make addresses for netif +- ip4_addr_t addr; +- addr.addr = make_address_v4(_ipaddr).to_uint(); +- +- ip4_addr_t netmask; +- netmask.addr = make_address_v4(_netmask).to_uint(); +- +- ip4_addr_t gw; +- ip4_addr_set_any(&gw); +- +- // init netif +- if (netif_add(&m_netif, &addr, &netmask, &gw, nullptr, (netif_init_fn)static_netif_init_func, +- (netif_input_fn)static_netif_input_func) == nullptr) { +- throw runtime_error("[tun] netif_add failed"); +- } +- +- // set netif up +- netif_set_up(&m_netif); +- +- // set netif link up, otherwise ip route will refuse to route +- netif_set_link_up(&m_netif); +- +- // set netif pretend TCP +- netif_set_pretend_tcp(&m_netif, 1); +- +- // set netif default +- netif_set_default(&m_netif); +- +- m_netif_configured = true; +- +- // init listener +- struct tcp_pcb* l = tcp_new_ip_type(IPADDR_TYPE_V4); +- if (l == nullptr) { +- throw runtime_error("[tun] tcp_new_ip_type failed"); +- } +- +- // bind listener +- if (tcp_bind_to_netif(l, "ho0") != ERR_OK) { +- tcp_close(l); +- throw runtime_error("[tun] tcp_bind_to_netif failed"); +- } +- +- tcp_bind_netif(l, &m_netif); +- +- // listen listener +- m_tcp_listener = tcp_listen(l); +- if (m_tcp_listener == nullptr) { +- tcp_close(l); +- throw runtime_error("[tun] tcp_listen failed"); +- } +- +- tcp_arg(m_tcp_listener, this); +- +- // setup listener accept handler +- tcp_accept(m_tcp_listener, static_listener_accept_func); +- +- async_read(); +-} +- +-TUNDev::~TUNDev() { +- if (m_quitting) { +- return; +- } +- +- m_quitting = true; +- +- _log_with_date_time("[tun] destoryed, clear all tcp_clients: " + to_string(m_tcp_clients.size()) + +- " udp_clients: " + to_string(m_udp_clients.size()), +- Log::INFO); +- +- for (auto& it : m_tcp_clients) { +- it->close_client(true, true); +- } +- m_tcp_clients.clear(); +- +- for (auto& it : m_udp_clients) { +- it->set_close_from_tundev_flag(); +- it->destroy(); +- } +- m_udp_clients.clear(); +- +- // free listener +- if (m_tcp_listener != nullptr) { +- tcp_close(m_tcp_listener); +- } +- +- // free netif +- if (m_netif_configured) { +- netif_remove(&m_netif); +- m_netif_configured = false; +- } +- +- tcp_remove(tcp_bound_pcbs); +- tcp_remove(tcp_active_pcbs); +- tcp_remove(tcp_tw_pcbs); +- +- if (m_tun_fd != -1 && !m_is_outside_tun_fd) { +- m_boost_sd.close(); +- } else { +- m_boost_sd.release(); +- } +- +- sm_tundev = nullptr; +-} +- +-err_t TUNDev::netif_init_func(struct netif* netif) const { +- netif->name[0] = 'h'; +- netif->name[1] = 'o'; +- netif->mtu = m_mtu; +- netif->output = static_netif_output_func; +- return ERR_OK; +-} +- +-err_t TUNDev::netif_input_func(struct pbuf* p, struct netif* inp) { +- uint8_t ip_version = 0; +- if (p->len > 0) { +- ip_version = (((uint8_t*)p->payload)[0] >> half_byte_shift_4_bits); +- } +- +- switch (ip_version) { +- case IPV4: { +- return ip_input(p, inp); +- } break; +- case IPV6: { +- // throw runtime_error("haven't supported ipv6"); +- } break; +- } +- +- pbuf_free(p); +- return ERR_OK; +-} +- +-err_t TUNDev::netif_output_func(struct netif*, struct pbuf* p, const ip4_addr_t*) { +- if (m_quitting) { +- return ERR_OK; +- } +- +- if (p != nullptr) { +- if (p->next == nullptr && p->len <= m_mtu) { +- boost::system::error_code ec; +- m_boost_sd.write_some(boost::asio::buffer(p->payload, p->len), ec); +- if (ec) { +- output_debug_info_ec(ec); +- } +- } else { +- do { +- if (p->len > 0) { +- auto* write_buff = boost::asio::buffer_cast(m_write_fill_buf.prepare(p->len)); +- memcpy(write_buff, (uint8_t*)p->payload, p->len); +- m_write_fill_buf.commit(p->len); +- } +- } while ((p = p->next) != nullptr); +- +- write_to_tun(); +- } +- } +- +- return ERR_OK; +-} +- +-bool TUNDev::is_in_ips(uint32_t ip, const Config::IPList& ips, const Config::IPSubnetList& subnet) { +- if (!ips.empty() && binary_search(ips.cbegin(), ips.cend(), ip)) { +- return true; +- } +- +- for (const auto& sub : subnet) { +- uint32_t net = ip & gsl::at(mask_values, sub.first); +- if (binary_search(sub.second.cbegin(), sub.second.cend(), net)) { +- return true; +- } +- } +- +- return false; +-} +- +-bool TUNDev::proxy_by_route(uint32_t ip) const { +- auto route = m_service->get_config().get_route(); +- if (is_in_ips(ip, route._proxy_ips, route._proxy_ips_subnet)) { +- return true; +- } +- +- if (is_in_ips(ip, route._white_ips, route._white_ips_subnet)) { +- return false; +- } +- +- switch (route.proxy_type) { +- case Config::route_all: // Controlled by route tables +- case Config::route_bypass_local: // Controlled by route tables +- return true; +- case Config::route_bypass_cn_mainland: +- case Config::route_bypass_local_and_cn_mainland: // Local ips Controlled by route tables +- return !is_in_ips(ip, route._cn_mainland_ips, route._cn_mainland_ips_subnet); +- case Config::route_gfwlist: +- return m_dns_server != nullptr && m_dns_server->is_ip_in_gfwlist(ip); +- case Config::route_cn_mainland: +- return is_in_ips(ip, route._cn_mainland_ips, route._cn_mainland_ips_subnet); +- default: +- throw logic_error("[dns] error proxy type: " + to_string((int)route.proxy_type)); +- } +-} +- +-err_t TUNDev::listener_accept_func(struct tcp_pcb* newpcb, err_t err) { +- +- if (err != ERR_OK) { +- return err; +- } +- +- shared_ptr session = nullptr; +- if (proxy_by_route(ntoh32(newpcb->local_ip.u_addr.ip4.addr))) { +- session = make_shared(m_service, false); +- } else { +- session = make_shared(m_service, false); +- } +- auto tcp_client = make_shared(newpcb, session, [this](lwip_tcp_client* client) { +- for (auto it = m_tcp_clients.begin(); it != m_tcp_clients.end(); it++) { +- if (it->get() == client) { +- m_tcp_clients.erase(it); +- break; +- } +- } +- }); +- +- m_service->start_session(session, [this, session, tcp_client](boost::system::error_code ec) { +- if (!ec) { +- session->start(); +- m_tcp_clients.emplace_back(tcp_client); +- } else { +- session->destroy(); +- tcp_client->close_client(true); +- } +- }); +- +- // start_session callback immediately and destory the session +- return session->is_destroyed() ? ERR_ABRT : ERR_OK; +-} +- +-void TUNDev::input_netif_packet(const uint8_t* data, uint16_t packet_len) { +- struct pbuf* p = pbuf_alloc(PBUF_RAW, packet_len, PBUF_POOL); +- if (p == nullptr) { +- _log_with_date_time("[tun] device read: pbuf_alloc failed", Log::ERROR); +- return; +- } +- +- // write packet to pbuf +- if (pbuf_take(p, (void*)data, packet_len) != ERR_OK) { +- _log_with_date_time("[tun] device read: pbuf_take failed", Log::ERROR); +- pbuf_free(p); +- return; +- } +- +- // pass pbuf to input +- if (m_netif.input(p, &m_netif) != ERR_OK) { +- _log_with_date_time("[tun] device read: input failed", Log::ERROR); +- pbuf_free(p); +- return; +- } +-} +- +-void TUNDev::parse_packet() { +- if (m_packet_parse_buff.empty()) { +- // need more byte for version +- return; +- } +- +- auto* data = (uint8_t*)m_packet_parse_buff.c_str(); +- auto data_len = m_packet_parse_buff.length(); +- auto ip_version = (data[0] >> half_byte_shift_4_bits) & half_byte_mask_0xF; +- +- if (ip_version == IPV4 || ip_version == IPV6) { +- +- uint16_t total_length = 0; +- +- if (ip_version == IPV4) { +- if (data_len < sizeof(struct ipv4_header)) { +- return; +- } +- struct ipv4_header ipv4_hdr; +- memcpy(&ipv4_hdr, data, sizeof(ipv4_hdr)); +- total_length = ntoh16(ipv4_hdr.total_length); +- +- //_log_with_date_time("parse_packet length:" + to_string(data_len) + " ipv4 protocol: " +- //+ +- // to_string((int)ipv4_hdr.protocol) + " total_length: " + to_string(total_length)); +- +- } else { +- if (data_len < sizeof(struct ipv6_header)) { +- return; +- } +- struct ipv6_header ipv6_hdr; +- memcpy(&ipv6_hdr, data, sizeof(ipv6_hdr)); +- total_length = ntoh16(ipv6_hdr.payload_length) + sizeof(ipv6_hdr); +- +- //_log_with_date_time("parse_packet length:" + to_string(data_len) + " ipv6 next header: +- //" + +- // to_string((int)ipv6_hdr.next_header) + " total_length: " + to_string(total_length)); +- } +- +- if (total_length <= data_len) { +- auto result = try_to_process_udp_packet(data, (int)total_length); +- if (result == 0) { +- input_netif_packet(data, total_length); +- } +- +- if (data_len == total_length) { +- //_log_with_date_time("full packet process"); +- m_packet_parse_buff.clear(); +- } else { +- //_log_with_date_time("split packet process--------------"); +- m_packet_parse_buff = m_packet_parse_buff.substr(total_length); +- parse_packet(); +- } +- } +- +- } else { +- m_packet_parse_buff.clear(); +- } +-} +- +-int TUNDev::handle_write_upd_data(const TUNSession* _session, string_view& data_str) { +- assert(_session->is_udp_forward_session()); +- +- auto data_len = data_str.length(); +- if (data_len == 0) { +- return 0; +- } +- const auto* data = (const uint8_t*)data_str.data(); +- auto header_length = (uint16_t)(sizeof(struct ipv4_header) + sizeof(struct udp_header)); +- auto max_len = min(numeric_limits::max(), m_mtu); +- max_len = max_len - header_length; +- if (data_len > max_len) { +- data_len = max_len; +- } +- +- auto local_endpoint = _session->get_udp_local_endpoint(); +- auto remote_endpoint = _session->get_udp_remote_endpoint(); +- +- auto* local_addr = (struct sockaddr_in*)local_endpoint.data(); +- auto* remote_addr = (struct sockaddr_in*)remote_endpoint.data(); +- +- // build IP header +- struct ipv4_header ipv4_hdr; +- ipv4_hdr.version4_ihl4 = IPV4_MAKE_VERSION_IHL(sizeof(ipv4_hdr)); +- ipv4_hdr.ds = hton8(0); +- ipv4_hdr.total_length = hton16(uint16_t(sizeof(ipv4_hdr) + sizeof(struct udp_header) + data_len)); +- ipv4_hdr.identification = hton16(0); +- ipv4_hdr.flags3_fragmentoffset13 = hton16(0); +- ipv4_hdr.ttl = hton8(Default_UDP_TTL); +- ipv4_hdr.protocol = hton8(IPV4_PROTOCOL_UDP); +- ipv4_hdr.checksum = hton16(0); +- ipv4_hdr.source_address = (remote_addr->sin_addr.s_addr); +- ipv4_hdr.destination_address = (local_addr->sin_addr.s_addr); +- ipv4_hdr.checksum = ipv4_checksum(&ipv4_hdr, nullptr, 0); +- +- // build UDP header +- struct udp_header udp_hdr; +- udp_hdr.source_port = hton16(remote_endpoint.port()); +- udp_hdr.dest_port = hton16(local_endpoint.port()); +- udp_hdr.length = hton16(uint16_t(sizeof(udp_hdr) + data_len)); +- udp_hdr.checksum = hton16(0); +- udp_hdr.checksum = +- udp_checksum(&udp_hdr, data, (uint16_t)data_len, ipv4_hdr.source_address, ipv4_hdr.destination_address); +- +- // compose packet +- auto packat_length = header_length + data_len; +- auto* write_buf = boost::asio::buffer_cast(m_write_fill_buf.prepare(packat_length)); +- +- memcpy(write_buf, &ipv4_hdr, sizeof(ipv4_hdr)); +- memcpy(write_buf + sizeof(ipv4_hdr), &udp_hdr, sizeof(udp_hdr)); +- memcpy(write_buf + sizeof(ipv4_hdr) + sizeof(udp_hdr), data, data_len); +- +- m_write_fill_buf.commit(packat_length); +- +- _log_with_endpoint_ALL(local_endpoint, "<- " + remote_endpoint.address().to_string() + ":" + +- to_string(remote_endpoint.port()) + " length:" + to_string(data_len)); +- +- write_to_tun(); +- +- data_str = data_str.substr(data_len); +- if (data_str.length() > 0) { +- handle_write_upd_data(_session, data_str); +- } +- +- return 0; +-} +- +-int TUNDev::try_to_process_udp_packet(uint8_t* data, int data_len) { +- uint8_t ip_version = 0; +- if (data_len > 0) { +- ip_version = (data[0] >> half_byte_shift_4_bits) & half_byte_mask_0xF; +- } +- +- if (ip_version == IPV4) { +- // ignore non-UDP packets +- if (data_len < (int)sizeof(struct ipv4_header) || +- data[offsetof(struct ipv4_header, protocol)] != IPV4_PROTOCOL_UDP) { +- return 0; +- } +- +- // parse IPv4 header +- struct ipv4_header ipv4_hdr; +- if (ipv4_check(data, data_len, &ipv4_hdr, &data, &data_len) == 0) { +- return 1; +- } +- +- // parse UDP +- struct udp_header udp_hdr; +- if (udp_check(data, data_len, &udp_hdr, &data, &data_len) == 0) { +- return 1; +- } +- +- // verify UDP checksum +- uint16_t checksum_in_packet = udp_hdr.checksum; +- udp_hdr.checksum = 0; +- uint16_t checksum_computed = +- udp_checksum(&udp_hdr, data, data_len, ipv4_hdr.source_address, ipv4_hdr.destination_address); +- if (checksum_in_packet != checksum_computed) { +- return 1; +- } +- +- auto local_endpoint = udp::endpoint( +- make_address_v4((address_v4::uint_type)ntoh32(ipv4_hdr.source_address)), ntoh16(udp_hdr.source_port)); +- +- auto remote_endpoint = udp::endpoint( +- make_address_v4((address_v4::uint_type)ntoh32(ipv4_hdr.destination_address)), ntoh16(udp_hdr.dest_port)); +- +- _log_with_endpoint_ALL(local_endpoint, " -> " + remote_endpoint.address().to_string() + ":" + +- to_string(remote_endpoint.port()) + +- " [tun] length:" + to_string(data_len)); +- +- for (auto& it : m_udp_clients) { +- if (it->try_to_process_udp(local_endpoint, remote_endpoint, data, data_len)) { +- return 1; +- } +- } +- +- shared_ptr session = nullptr; +- if (proxy_by_route(ntoh32(ipv4_hdr.destination_address))) { +- session = make_shared(m_service, true); +- } else { +- session = make_shared(m_service, true); +- } +- session->set_udp_connect(local_endpoint, remote_endpoint); +- session->set_write_to_lwip([this](const TUNSession* _se, string_view* _data) { +- assert(_data != nullptr); +- return handle_write_upd_data(_se, *_data); +- }); +- +- session->set_close_callback([this](TUNSession* _session) { +- for (auto it = m_udp_clients.begin(); it != m_udp_clients.end(); it++) { +- if (it->get() == _session) { +- m_udp_clients.erase(it); +- break; +- } +- } +- }); +- +- session->out_async_send(data, data_len, [](boost::system::error_code) {}); // send as buf +- m_udp_clients.emplace_back(session); +- +- _log_with_endpoint(local_endpoint, +- "TUNDev start to connected " + remote_endpoint.address().to_string() + ":" + +- to_string(remote_endpoint.port()), +- Log::INFO); +- +- m_service->start_session(session, [session, local_endpoint, remote_endpoint](boost::system::error_code ec) { +- if (!ec) { +- session->start(); +- } else { +- output_debug_info_ec(ec); +- session->destroy(); +- } +- }); +- +- return 1; +- } +- +- if (ip_version == IPV6) { +- // TODO +- } +- +- return 0; +-} +- +-void TUNDev::write_to_tun() { +- if (m_quitting) { +- return; +- } +- +- while (m_write_fill_buf.size() > 0) { +- boost::system::error_code ec; +- size_t wrote = 0; +- if (m_write_fill_buf.size() > m_mtu) { +- auto copied = boost::asio::buffer_copy(m_writing_buf.prepare(m_mtu), m_write_fill_buf.data(), m_mtu); +- m_writing_buf.commit(copied); +- +- wrote = m_boost_sd.write_some(m_writing_buf.data(), ec); +- m_writing_buf.consume(m_writing_buf.size()); +- } else { +- wrote = m_boost_sd.write_some(m_write_fill_buf.data(), ec); +- } +- +- if (!ec && wrote > 0) { +- m_write_fill_buf.consume(wrote); +- } else { +- m_write_fill_buf.consume(m_write_fill_buf.size()); +- } +- } +-} +- +-void TUNDev::async_read() { +- m_sd_read_buffer.consume(m_sd_read_buffer.size()); +- m_boost_sd.async_read_some(m_sd_read_buffer.prepare(m_mtu), [this](boost::system::error_code ec, size_t data_len) { +- if (m_quitting) { +- return; +- } +- +- if (!ec) { +- m_sd_read_buffer.commit(data_len); +- +- const auto* data = boost::asio::buffer_cast(m_sd_read_buffer.data()); +- m_packet_parse_buff.append(data, data_len); +- +- parse_packet(); +- } +- +- async_read(); +- }); +- +- // sleep for test +- //::sleep(1); +-} +\ No newline at end of file +diff --git a/src/tun/tundev.h b/src/tun/tundev.h +deleted file mode 100644 +index 83ca4ec..0000000 +--- a/src/tun/tundev.h ++++ /dev/null +@@ -1,146 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_TUNDEV_HPP +-#define _TROJAN_TUNDEV_HPP +- +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifdef __linux__ +-#include +-#include +-#endif +- +-#include +-#include +-#include +- +-#include "core/config.h" +- +-#ifndef _WIN32 +-using BoostStreamDescriptor = boost::asio::posix::stream_descriptor; +-#else +-class BoostStreamDescriptor { +- public: +- BoostStreamDescriptor(boost::asio::io_context&) {} +- void assign(int) {} +- +- template +- std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec) { +- return 0; +- } +- +- template +- void async_read_some(const ConstBufferSequence&, Handler&&) {} +- +- void close() {} +- void release() {} +-}; +-#endif +- +-class Service; +-class lwip_tcp_client; +-class TUNSession; +-class DNSServer; +-// this class canot support ipv6 +-class TUNDev { +- +- enum IPVersion { IPV4 = 4, IPV6 = 6 }; +- enum DefaultVar { Default_UDP_TTL = 60 }; +- +- static TUNDev* sm_tundev; +- static err_t static_netif_init_func(struct netif* netif) { return sm_tundev->netif_init_func(netif); } +- +- static err_t static_netif_input_func(struct pbuf* p, struct netif* inp) { +- return sm_tundev->netif_input_func(p, inp); +- } +- +- static err_t static_netif_output_func(struct netif* netif, struct pbuf* p, const ip4_addr_t* ipaddr) { +- return sm_tundev->netif_output_func(netif, p, ipaddr); +- } +- +- static err_t static_listener_accept_func(void* arg, struct tcp_pcb* newpcb, err_t err) { +- return ((TUNDev*)arg)->listener_accept_func(newpcb, err); +- } +- +- // lwip TUN netif device handler +- struct netif m_netif {}; +- bool m_netif_configured; +- +- // lwip TCP listener +- struct tcp_pcb* m_tcp_listener; +- +- err_t netif_init_func(struct netif* netif) const; +- err_t netif_input_func(struct pbuf* p, struct netif* inp); +- err_t netif_output_func(struct netif* netif, struct pbuf* p, const ip4_addr_t* ipaddr); +- +- err_t listener_accept_func(struct tcp_pcb* newpcb, err_t err); +- +- private: +- std::list> m_tcp_clients; +- std::list> m_udp_clients; +- +- Service* m_service; +- std::shared_ptr m_dns_server; +- int m_tun_fd; +- const bool m_is_outside_tun_fd; +- uint16_t m_mtu; +- +- bool m_quitting; +- boost::asio::streambuf m_write_fill_buf; +- boost::asio::streambuf m_writing_buf; +- +- boost::asio::streambuf m_sd_read_buffer; +- BoostStreamDescriptor m_boost_sd; +- +- std::string m_packet_parse_buff; +- +- void async_read(); +- void write_to_tun(); +- +- int try_to_process_udp_packet(uint8_t* data, int data_len); +- void parse_packet(); +- void input_netif_packet(const uint8_t* data, uint16_t packet_len); +- int handle_write_upd_data(const TUNSession* _session, std::string_view& data); +- +- [[nodiscard]] static bool is_in_ips(uint32_t ip, const Config::IPList& ips, const Config::IPSubnetList& subnet); +- [[nodiscard]] bool proxy_by_route(uint32_t ip) const; +- +- public: +- TUNDev(Service* _service, const std::string& _tun_name, const std::string& _ipaddr, const std::string& _netmask, +- uint16_t _mtu, int _outside_tun_fd = -1); +- ~TUNDev(); +- +- void set_dns_server(std::shared_ptr dns) { m_dns_server = std::move(dns); } +- [[nodiscard]] int get_tun_fd() const { return m_tun_fd; } +-}; +-#endif //_TROJAN_TUNDEV_HPP +diff --git a/src/tun/tunlocalsession.cpp b/src/tun/tunlocalsession.cpp +deleted file mode 100644 +index 04a2f02..0000000 +--- a/src/tun/tunlocalsession.cpp ++++ /dev/null +@@ -1,215 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tun/tunlocalsession.h" +-#include "core/service.h" +-#include "core/utils.h" +-#include "tun/udplocalforwarder.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-TUNLocalSession::TUNLocalSession(Service* _service, bool is_udp) +- : TUNSession(_service, is_udp), m_resolver(_service->get_io_context()), m_tcp_socket(_service->get_io_context()) { +- if (!is_udp) { +- m_sending_data_cache.set_is_connected_func([this]() { return !m_destroyed && m_connected; }); +- m_sending_data_cache.set_async_writer([this](const boost::asio::streambuf& data, SentHandler&& handler) { +- auto self = shared_from_this(); +- boost::asio::async_write( +- m_tcp_socket, data.data(), [this, self, handler](const boost::system::error_code error, size_t length) { +- udp_timer_async_wait(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- } +- +- get_stat().inc_sent_len(length); +- handler(error); +- }); +- }); +- } +-} +- +-void TUNLocalSession::start() { +- if (is_udp_forward_session()) { +- auto remote_addr = get_config().get_tun().redirect_local ? get_redirect_local_remote_addr() : m_remote_addr_udp; +- m_udp_forwarder = make_shared( +- get_service(), m_local_addr_udp, remote_addr, +- [this](const udp::endpoint&, const string_view& data) { +- if (m_write_to_lwip(this, (string_view*)&data) < 0) { +- output_debug_info(); +- destroy(); +- } +- }, +- false); +- +- m_udp_forwarder->set_destroy_callback([this]() { +- output_debug_info(); +- destroy(); +- }); +- +- m_udp_forwarder->start(); +- +- if (m_send_buf.size() != 0) { +- if (m_udp_forwarder->process(m_local_addr_udp, streambuf_to_string_view(m_send_buf))) { +- m_connected = true; +- } +- } else if (!m_udp_forwarder->is_destroyed()) { +- m_connected = true; +- } +- +- } else { +- auto remote_addr = +- get_config().get_tun().redirect_local ? LOCALHOST_IP_ADDRESS : m_remote_addr.address().to_string(); +- auto self = shared_from_this(); +- connect_out_socket(this, remote_addr, to_string(m_remote_addr.port()), m_resolver, m_tcp_socket, +- m_local_addr_udp, [this, self]() { +- m_connected = true; +- +- if (m_send_buf.size() != 0) { +- out_async_send_impl(streambuf_to_string_view(m_send_buf), [this, self](boost::system::error_code ec) { +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- if (!m_wait_connected_handler.empty()) { +- for (auto& h : m_wait_connected_handler) { +- h(boost::system::error_code()); +- } +- m_wait_connected_handler.clear(); +- } +- out_async_read(); +- }); +- } else { +- out_async_read(); +- } +- }); +- } +-} +- +-void TUNLocalSession::recv_buf_consume(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf.consume(_length); +- +- if (m_recv_buf.size() == 0) { +- out_async_read(); +- } +-} +- +-void TUNLocalSession::recv_buf_ack_sent(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf_ack_length -= _length; +-} +- +-void TUNLocalSession::out_async_read() { +- if (!is_udp_forward_session()) { +- m_recv_buf.begin_read(__FILE__, __LINE__); +- auto self = shared_from_this(); +- m_tcp_socket.async_read_some(m_recv_buf.prepare(Session::MAX_BUF_LENGTH), +- [this, self](const boost::system::error_code error, size_t length) { +- m_recv_buf.end_read(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- return; +- } +- m_recv_buf.commit(length); +- get_stat().inc_recv_len(length); +- +- m_recv_buf_ack_length += length; +- +- if (m_write_to_lwip(this, nullptr) < 0) { +- output_debug_info(); +- destroy(); +- } +- }); +- } +-} +- +-void TUNLocalSession::out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler) { +- if (is_udp_forward_session()) { +- if (m_udp_forwarder->process(m_local_addr_udp, data_to_send)) { +- _handler(boost::system::error_code()); +- } else { +- _handler(boost::asio::error::broken_pipe); +- } +- } else { +- m_sending_data_cache.push_data( +- [&](boost::asio::streambuf& buf) { streambuf_append(buf, data_to_send); }, move(_handler)); +- } +-} +- +-void TUNLocalSession::out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) { +- if (!m_connected) { +- if (m_send_buf.size() < numeric_limits::max()) { +- streambuf_append(m_send_buf, _data, _length); +- m_wait_connected_handler.emplace_back(_handler); +- } else { +- output_debug_info(); +- destroy(); +- } +- } else { +- out_async_send_impl(string_view((const char*)_data, _length), move(_handler)); +- } +-} +- +-void TUNLocalSession::destroy(bool /*= false*/) { +- if (m_destroyed) { +- return; +- } +- m_destroyed = true; +- +- auto note_str = "TUNLocalSession disconnected, " + get_stat().to_string(); +- if (is_udp_forward_session()) { +- _log_with_endpoint(m_local_addr_udp, note_str, Log::INFO); +- } else { +- _log_with_endpoint(m_local_addr, note_str, Log::INFO); +- } +- +- m_wait_ack_handler.clear(); +- +- if (m_udp_forwarder && !m_udp_forwarder->is_destroyed()) { +- m_udp_forwarder->destroy(); +- } +- +- if (m_tcp_socket.is_open()) { +- boost::system::error_code ec; +- m_tcp_socket.cancel(ec); +- m_tcp_socket.shutdown(tcp::socket::shutdown_both, ec); +- m_tcp_socket.close(ec); +- } +- +- if (!m_close_from_tundev_flag) { +- m_close_cb(this); +- } +-} +- +-bool TUNLocalSession::try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, +- const boost::asio::ip::udp::endpoint& _remote, const uint8_t* payload, size_t payload_length) { +- if (is_udp_forward_session()) { +- if (_local == m_local_addr_udp && _remote == m_remote_addr_udp) { +- return m_udp_forwarder->process(_local, string_view((const char*)payload, payload_length)); +- } +- } +- +- return false; +-} +\ No newline at end of file +diff --git a/src/tun/tunlocalsession.h b/src/tun/tunlocalsession.h +deleted file mode 100644 +index 4555ca1..0000000 +--- a/src/tun/tunlocalsession.h ++++ /dev/null +@@ -1,55 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TUN_LOCAL_SESSION_H_ +-#define _TUN_LOCAL_SESSION_H_ +- +-#include "tun/tunsession.h" +-#include "tun/udplocalforwarder.h" +- +-class TUNLocalSession : public TUNSession { +- +- std::shared_ptr m_udp_forwarder; +- +- boost::asio::ip::tcp::resolver m_resolver; +- boost::asio::ip::tcp::socket m_tcp_socket; +- +- void out_async_read(); +- void out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler); +- +- public: +- TUNLocalSession(Service* service, bool udp); +- +- // common interfaces +- void start() override; +- void destroy(bool pipeline_call = false) override; +- void out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) override; +- +- // interfaces for TCP +- void recv_buf_consume(uint16_t _length) override; +- void recv_buf_ack_sent(uint16_t _length) override; +- +- // interfaces for UDP +- bool try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, const boost::asio::ip::udp::endpoint& _remote, +- const uint8_t* payload, size_t payload_length) override; +-}; +- +-#endif //_TUN_LOCAL_SESSION_H_ +diff --git a/src/tun/tunproxysession.cpp b/src/tun/tunproxysession.cpp +deleted file mode 100644 +index 6f8d4a5..0000000 +--- a/src/tun/tunproxysession.cpp ++++ /dev/null +@@ -1,409 +0,0 @@ +- +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tun/tunproxysession.h" +- +-#include +-#include +-#include +- +-#include "core/service.h" +-#include "core/utils.h" +-#include "proto/trojanrequest.h" +-#include "proto/udppacket.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-TUNProxySession::TUNProxySession(Service* _service, bool _is_udp) +- : TUNSession(_service, _is_udp), +- m_out_socket(_service->get_io_context(), _service->get_ssl_context()), +- m_out_resolver(_service->get_io_context()) { +- +- get_pipeline_component().allocate_session_id(); +- +- m_sending_data_cache.set_is_connected_func([this]() { return !is_destroyed() && m_connected; }); +- m_sending_data_cache.set_async_writer([this](const boost::asio::streambuf& data, SentHandler&& handler) { +- auto self = shared_from_this(); +- boost::asio::async_write( +- m_out_socket, data.data(), [this, self, handler](const boost::system::error_code error, size_t length) { +- udp_timer_async_wait(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- } +- +- get_stat().inc_sent_len(length); +- +- handler(error); +- }); +- }); +-} +- +-TUNProxySession::~TUNProxySession() { get_pipeline_component().free_session_id(); } +- +-void TUNProxySession::start() { +- udp_timer_async_wait(); +- auto self = shared_from_this(); +- auto cb = [this, self]() { +- m_connected = true; +- +- if (!get_service()->is_use_pipeline()) { +- boost::system::error_code ec; +- auto endpoint = m_out_socket.next_layer().local_endpoint(ec); +- _log_with_endpoint( +- endpoint, "TUNProxySession session_id: " + to_string(get_session_id()) + " started", Log::INFO); +- } else { +- auto note_str = "TUNProxySession session_id: " + to_string(get_session_id()) + " started in pipeline"; +- if (is_udp_forward_session()) { +- _log_with_endpoint(m_local_addr_udp, note_str, Log::INFO); +- } else { +- _log_with_endpoint(m_local_addr, note_str, Log::INFO); +- } +- } +- auto insert_pwd = [this]() { +- if (is_udp_forward_session()) { +- streambuf_append( +- m_send_buf, TrojanRequest::generate(get_config().get_password().cbegin()->first, +- get_config().get_tun().redirect_local ? LOCALHOST_IP_ADDRESS +- : m_remote_addr_udp.address().to_string().c_str(), +- m_remote_addr_udp.port(), false)); +- } else { +- auto remote_addr = m_remote_addr.address().to_string(); +- if (get_config().get_tun().redirect_local) { +- _log_with_date_time(remote_addr + " redirect to local for test"); +- remote_addr = LOCALHOST_IP_ADDRESS; +- } +- streambuf_append(m_send_buf, TrojanRequest::generate(get_config().get_password().cbegin()->first, +- remote_addr, m_remote_addr.port(), true)); +- } +- }; +- +- if (m_send_buf.size() > 0) { +- boost::asio::streambuf tmp_buf; +- streambuf_append(tmp_buf, m_send_buf); +- m_send_buf.consume(m_send_buf.size()); +- insert_pwd(); +- streambuf_append(m_send_buf, tmp_buf); +- } else { +- insert_pwd(); +- } +- +- out_async_send_impl(streambuf_to_string_view(m_send_buf), [this](boost::system::error_code ec) { +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- if (!m_wait_connected_handler.empty()) { +- for (auto& h : m_wait_connected_handler) { +- h(boost::system::error_code()); +- } +- m_wait_connected_handler.clear(); +- } +- out_async_read(); +- }); +- m_send_buf.consume(m_send_buf.size()); +- }; +- +- if (get_service()->is_use_pipeline()) { +- cb(); +- } else { +- get_service()->get_config().prepare_ssl_reuse(m_out_socket); +- if (is_udp_forward_session()) { +- connect_remote_server_ssl(this, get_service()->get_config().get_remote_addr(), +- to_string(get_service()->get_config().get_remote_port()), m_out_resolver, m_out_socket, m_local_addr_udp, +- cb); +- } else { +- connect_remote_server_ssl(this, get_service()->get_config().get_remote_addr(), +- to_string(get_service()->get_config().get_remote_port()), m_out_resolver, m_out_socket, m_local_addr, cb); +- } +- } +-} +- +-void TUNProxySession::destroy(bool pipeline_call) { +- if (m_destroyed) { +- return; +- } +- m_destroyed = true; +- +- auto note_str = +- "TUNProxySession session_id: " + to_string(get_session_id()) + " disconnected, " + get_stat().to_string(); +- +- if (is_udp_forward_session()) { +- _log_with_endpoint(m_local_addr_udp, note_str, Log::INFO); +- } else { +- _log_with_endpoint(m_local_addr, note_str, Log::INFO); +- } +- +- m_wait_ack_handler.clear(); +- m_out_resolver.cancel(); +- udp_timer_cancel(); +- shutdown_ssl_socket(this, m_out_socket); +- +- if (!pipeline_call && get_service()->is_use_pipeline()) { +- get_service()->session_destroy_in_pipeline(*this); +- } +- +- if (!m_close_from_tundev_flag && m_close_cb) { +- m_close_cb(this); +- } +-} +- +-void TUNProxySession::recv_ack_cmd(size_t ack_count) { +- Session::recv_ack_cmd(ack_count); +- +- while (ack_count-- > 0) { +- if (!m_wait_ack_handler.empty()) { +- m_wait_ack_handler.front()(boost::system::error_code()); +- m_wait_ack_handler.pop_front(); +- } else { +- break; +- } +- } +-} +- +-void TUNProxySession::out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler) { +- if (get_service()->is_use_pipeline()) { +- auto data_sending_len = data_to_send.length(); +- auto self = shared_from_this(); +- get_service()->session_async_send_to_pipeline(*this, PipelineRequest::DATA, data_to_send, +- [this, self, _handler, data_sending_len](const boost::system::error_code error) { +- udp_timer_async_wait(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- } else { +- get_stat().inc_sent_len(data_sending_len); +- +- if (!is_udp_forward_session()) { +- if (!get_pipeline_component().pre_call_ack_func()) { +- m_wait_ack_handler.emplace_back(_handler); +- _log_with_endpoint_DEBUG( +- m_local_addr, "session_id: " + to_string(get_session_id()) + +- " cannot TUNProxySession::out_async_send ! Is waiting for ack"); +- return; +- } +- _log_with_endpoint_DEBUG( +- m_local_addr, "session_id: " + to_string(get_session_id()) + +- " permit to TUNProxySession::out_async_send ! ack:" + +- to_string(get_pipeline_component().pipeline_ack_counter)); +- } +- } +- _handler(error); +- }); +- } else { +- m_sending_data_cache.push_data( +- [&](boost::asio::streambuf& buf) { streambuf_append(buf, data_to_send); }, move(_handler)); +- } +-} +-void TUNProxySession::out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) { +- +- if (!m_connected) { +- if (m_send_buf.size() < numeric_limits::max()) { +- if (is_udp_forward_session()) { +- UDPPacket::generate(m_send_buf, +- get_config().get_tun().redirect_local ? get_redirect_local_remote_addr() : m_remote_addr_udp, +- string_view((const char*)_data, _length)); +- } else { +- streambuf_append(m_send_buf, _data, _length); +- } +- m_wait_connected_handler.emplace_back(_handler); +- } else { +- output_debug_info(); +- destroy(); +- } +- } else { +- if (is_udp_forward_session()) { +- m_send_buf.consume(m_send_buf.size()); +- UDPPacket::generate(m_send_buf, +- get_config().get_tun().redirect_local ? get_redirect_local_remote_addr() : m_remote_addr_udp, +- string_view((const char*)_data, _length)); +- out_async_send_impl(streambuf_to_string_view(m_send_buf), move(_handler)); +- } else { +- out_async_send_impl(string_view((const char*)_data, _length), move(_handler)); +- } +- } +-} +- +-void TUNProxySession::try_out_async_read() { +- if (is_destroyed()) { +- return; +- } +- +- if (get_service()->is_use_pipeline() && !is_udp_forward_session()) { +- auto self = shared_from_this(); +- get_service()->session_async_send_to_pipeline( +- *this, PipelineRequest::ACK, "", +- [this, self](const boost::system::error_code error) { +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- return; +- } +- +- out_async_read(); +- }, +- m_read_ack_count); +- m_read_ack_count = 0; +- } else { +- out_async_read(); +- } +-} +-void TUNProxySession::recv_buf_ack_sent(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf_ack_length -= _length; +- +- if (get_service()->is_use_pipeline() && m_recv_buf_ack_length <= 0) { +- if (get_pipeline_component().is_write_close_future()) { +- output_debug_info(); +- destroy(); +- return; +- } +- +- get_pipeline_component().set_async_writing_data(false); +- } +-} +- +-void TUNProxySession::recv_buf_consume(uint16_t _length) { +- assert(!is_udp_forward_session()); +- m_recv_buf.consume(_length); +- if (m_recv_buf.size() == 0) { +- try_out_async_read(); +- } +-} +- +-size_t TUNProxySession::parse_udp_packet_data(const string_view& data) { +- +- string_view parse_data(data); +- size_t parsed_size = 0; +- for (;;) { +- if (parse_data.empty()) { +- break; +- } +- +- // parse trojan protocol +- UDPPacket packet; +- size_t packet_len = 0; +- if (!packet.parse(parse_data, packet_len)) { +- if (parse_data.length() > numeric_limits::max()) { +- _log_with_endpoint(get_udp_local_endpoint(), "[tun] error UDPPacket.parse! destroy it.", Log::ERROR); +- destroy(); +- break; +- } +- +- _log_with_endpoint( +- get_udp_local_endpoint(), "[tun] UDPPacket.parse failed! Might need to read more...", Log::WARN); +- break; +- } +- +- if (m_write_to_lwip(this, &packet.payload) < 0) { +- output_debug_info(); +- destroy(); +- break; +- } +- +- parsed_size += packet_len; +- parse_data = parse_data.substr(packet_len); +- } +- +- return parsed_size; +-} +- +-void TUNProxySession::out_async_read() { +- if (get_service()->is_use_pipeline()) { +- get_pipeline_component().get_pipeline_data_cache().async_read( +- [this](const string_view& data, size_t ack_count) { +- get_stat().inc_recv_len(data.length()); +- +- if (is_udp_forward_session()) { +- +- udp_timer_async_wait(); +- +- if (m_recv_buf.size() == 0) { +- auto parsed = parse_udp_packet_data(data); +- if (parsed < data.length()) { +- streambuf_append(m_recv_buf, data.substr(parsed)); +- } +- } else { +- streambuf_append(m_recv_buf, data); +- auto parsed = parse_udp_packet_data(m_recv_buf); +- m_recv_buf.consume(parsed); +- } +- +- try_out_async_read(); +- } else { +- m_read_ack_count += ack_count; +- streambuf_append(m_recv_buf, data); +- m_recv_buf_ack_length += data.length(); +- +- get_pipeline_component().set_async_writing_data(true); +- if (m_write_to_lwip(this, nullptr) < 0) { +- output_debug_info(); +- destroy(); +- } +- } +- }); +- } else { +- m_recv_buf.begin_read(__FILE__, __LINE__); +- auto self = shared_from_this(); +- m_out_socket.async_read_some(m_recv_buf.prepare(Session::MAX_BUF_LENGTH), +- [this, self](const boost::system::error_code error, size_t length) { +- m_recv_buf.end_read(); +- if (error) { +- output_debug_info_ec(error); +- destroy(); +- return; +- } +- m_recv_buf.commit(length); +- get_stat().inc_recv_len(length); +- +- if (is_udp_forward_session()) { +- udp_timer_async_wait(); +- auto parsed = parse_udp_packet_data(m_recv_buf); +- m_recv_buf.consume(parsed); +- +- try_out_async_read(); +- } else { +- m_recv_buf_ack_length += length; +- +- if (m_write_to_lwip(this, nullptr) < 0) { +- output_debug_info(); +- destroy(); +- } +- } +- }); +- } +-} +- +-bool TUNProxySession::try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, +- const boost::asio::ip::udp::endpoint& _remote, const uint8_t* payload, size_t payload_length) { +- +- if (is_udp_forward_session()) { +- if (_local == m_local_addr_udp && _remote == m_remote_addr_udp) { +- out_async_send(payload, payload_length, [](boost::system::error_code) {}); +- return true; +- } +- } +- +- return false; +-} +\ No newline at end of file +diff --git a/src/tun/tunproxysession.h b/src/tun/tunproxysession.h +deleted file mode 100644 +index 4390a69..0000000 +--- a/src/tun/tunproxysession.h ++++ /dev/null +@@ -1,59 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TUN_PROXY_SESSION_H_ +-#define _TUN_PROXY_SESSION_H_ +- +-#include "tun/tunsession.h" +- +-class TUNProxySession : public TUNSession { +- +- size_t m_read_ack_count{0}; +- +- boost::asio::ssl::stream m_out_socket; +- boost::asio::ip::tcp::resolver m_out_resolver; +- +- void out_async_read(); +- void try_out_async_read(); +- +- [[nodiscard]] size_t parse_udp_packet_data(const std::string_view& data); +- +- void out_async_send_impl(const std::string_view& data_to_send, SentHandler&& _handler); +- +- public: +- TUNProxySession(Service* service, bool udp); +- ~TUNProxySession(); +- +- void start() override; +- void destroy(bool pipeline_call = false) override; +- void out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) override; +- void recv_ack_cmd(size_t ack_count) override; +- +- // interfaces for TCP +- void recv_buf_consume(uint16_t _length) override; +- void recv_buf_ack_sent(uint16_t _length) override; +- +- // interfaces for UDP +- bool try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, const boost::asio::ip::udp::endpoint& _remote, +- const uint8_t* payload, size_t payload_length) override; +-}; +- +-#endif //_TUN_PROXY_SESSION_H_ +\ No newline at end of file +diff --git a/src/tun/tunsession.cpp b/src/tun/tunsession.cpp +deleted file mode 100644 +index 0c465d9..0000000 +--- a/src/tun/tunsession.cpp ++++ /dev/null +@@ -1,40 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tunsession.h" +-#include "core/service.h" +- +-using namespace boost::asio::ip; +-TUNSession::TUNSession(Service* _service, bool _is_udp) : Session(_service, _service->get_config()) { +- set_udp_forward_session(_is_udp); +-} +- +-TUNSession::~TUNSession() {} +- +-udp::endpoint TUNSession::get_redirect_local_remote_addr(bool output_log /*= false*/) const { +- auto remote_addr = m_remote_addr_udp; +- remote_addr.address(make_address_v4(LOCALHOST_IP_ADDRESS)); +- if (output_log) { +- _log_with_date_time(m_remote_addr_udp.address().to_string() + " redirect to local for test"); +- } +- +- return remote_addr; +-} +diff --git a/src/tun/tunsession.h b/src/tun/tunsession.h +deleted file mode 100644 +index ec7b8cb..0000000 +--- a/src/tun/tunsession.h ++++ /dev/null +@@ -1,108 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TUNSESSION_H_ +-#define _TUNSESSION_H_ +- +-#include +-#include +-#include +-#include +- +-#include "core/pipeline.h" +-#include "core/utils.h" +-#include "session/session.h" +- +-#define LOCALHOST_IP_ADDRESS ("127.0.0.1") +- +-class Service; +-class TUNSession : public Session { +- +- public: +- using CloseCallback = std::function; +- using WriteToLwipCallback = std::function; +- +- protected: +- SendDataCache m_sending_data_cache; +- +- boost::asio::ip::tcp::endpoint m_local_addr; +- boost::asio::ip::tcp::endpoint m_remote_addr; +- +- boost::asio::ip::udp::endpoint m_local_addr_udp; +- boost::asio::ip::udp::endpoint m_remote_addr_udp; +- +- ReadBufWithGuard m_recv_buf; +- size_t m_recv_buf_ack_length{0}; +- bool m_destroyed{false}; +- +- CloseCallback m_close_cb; +- bool m_close_from_tundev_flag{false}; +- bool m_connected{false}; +- +- boost::asio::streambuf m_send_buf; +- WriteToLwipCallback m_write_to_lwip; +- std::list m_wait_ack_handler; +- std::list m_wait_connected_handler; +- +- [[nodiscard]] boost::asio::ip::udp::endpoint get_redirect_local_remote_addr(bool output_log = false) const; +- +- public: +- TUNSession(Service* _service, bool _is_udp); +- ~TUNSession(); +- +- // common interfaces for UDP and TCP +- void set_tcp_connect(const boost::asio::ip::tcp::endpoint& _local, const boost::asio::ip::tcp::endpoint& _remote) { +- m_local_addr = _local; +- m_remote_addr = _remote; +- } +- +- void set_udp_connect(const boost::asio::ip::udp::endpoint& _local, const boost::asio::ip::udp::endpoint& _remote) { +- m_local_addr_udp = _local; +- m_remote_addr_udp = _remote; +- } +- +- [[nodiscard]] const boost::asio::ip::udp::endpoint& get_udp_local_endpoint() const { return m_local_addr_udp; } +- [[nodiscard]] const boost::asio::ip::udp::endpoint& get_udp_remote_endpoint() const { return m_remote_addr_udp; } +- +- [[nodiscard]] bool is_destroyed() const { return m_destroyed; } +- +- void set_write_to_lwip(WriteToLwipCallback&& _handler) { m_write_to_lwip = std::move(_handler); } +- void set_close_callback(CloseCallback&& _cb) { m_close_cb = std::move(_cb); } +- void set_close_from_tundev_flag() { m_close_from_tundev_flag = true; } +- +- virtual void out_async_send(const uint8_t* _data, size_t _length, SentHandler&& _handler) = 0; +- +- // interfaces for TCP +- [[nodiscard]] size_t recv_buf_ack_length() const { return m_recv_buf_ack_length; } +- [[nodiscard]] size_t recv_buf_size() const { return m_recv_buf.size(); } +- +- [[nodiscard]] const uint8_t* recv_buf() const { +- return boost::asio::buffer_cast(m_recv_buf.data()); +- } +- +- virtual void recv_buf_consume(uint16_t _length) = 0; +- virtual void recv_buf_ack_sent(uint16_t _length) = 0; +- +- // interface for UDP +- virtual bool try_to_process_udp(const boost::asio::ip::udp::endpoint& _local, +- const boost::asio::ip::udp::endpoint& _remote, const uint8_t* payload, size_t payload_length) = 0; +-}; +-#endif //_TUNSESSION_H_ +\ No newline at end of file +diff --git a/src/tun/udplocalforwarder.cpp b/src/tun/udplocalforwarder.cpp +deleted file mode 100644 +index 1eefbdd..0000000 +--- a/src/tun/udplocalforwarder.cpp ++++ /dev/null +@@ -1,156 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#include "tun/udplocalforwarder.h" +-#include "core/service.h" +-#include "session/session.h" +- +-using namespace std; +-using namespace boost::asio::ip; +- +-UDPLocalForwarder::UDPLocalForwarder(Service* service, udp::endpoint local_src, udp::endpoint remote_dst, +- UDPForwardSession::UDPWriter&& writer, bool is_dns) +- : Session(service, service->get_config()), +- m_service(service), +- m_writer(move(writer)), +- m_local_src(move(local_src)), +- m_remote_dst(move(remote_dst)), +- m_gc_timer(service->get_io_context()), +- m_udp_socket(service->get_io_context()), +- m_is_dns(is_dns) { +- +- set_udp_forward_session(true); +-} +- +-UDPLocalForwarder::~UDPLocalForwarder() {} +-void UDPLocalForwarder::start() { +- auto protocol = m_remote_dst.protocol(); +- boost::system::error_code ec; +- m_udp_socket.open(protocol, ec); +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- +- set_udp_send_recv_buf((int)m_udp_socket.native_handle(), +- m_is_dns ? m_service->get_config().get_dns().udp_socket_buf : m_service->get_config().get_udp_socket_buf()); +- +- android_protect_socket((int)m_udp_socket.native_handle()); +- +- m_udp_socket.bind(udp::endpoint(protocol, 0), ec); +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return; +- } +- +- udp_timer_async_wait(); +- +- _log_with_endpoint(m_local_src, +- "UDP local forwarder to [" + m_remote_dst.address().to_string() + ":" + to_string(m_remote_dst.port()) + +- "] started", +- Log::INFO); +- +- async_read(); +-} +- +-bool UDPLocalForwarder::process(const udp::endpoint& endpoint, const string_view& data) { +- if (endpoint != m_local_src) { +- return false; +- } +- +- return write_to(data); +-} +- +-bool UDPLocalForwarder::write_to(const std::string_view& data) { +- if (is_destroyed()) { +- return false; +- } +- +- if (m_is_dns) { +- _log_with_endpoint_ALL(m_local_src, "[dns] --> [" + m_remote_dst.address().to_string() + ":" + +- to_string(m_remote_dst.port()) + "] length: " + to_string(data.length())); +- } +- +- boost::system::error_code ec; +- m_udp_socket.send_to(boost::asio::buffer(data), m_remote_dst, 0, ec); +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- return false; +- } +- +- m_stat.inc_sent_len(data.length()); +- return true; +-} +- +-void UDPLocalForwarder::async_read() { +- udp_timer_async_wait(); +- +- const auto prepare_size = +- m_is_dns ? m_service->get_config().get_dns().udp_recv_buf : m_service->get_config().get_udp_recv_buf(); +- +- m_read_buf.begin_read(__FILE__, __LINE__); +- m_read_buf.consume_all(); +- +- auto self = shared_from_this(); +- m_udp_socket.async_receive_from( +- m_read_buf.prepare(prepare_size), m_remote_dst, [this, self](boost::system::error_code ec, size_t length) { +- m_read_buf.end_read(); +- +- if (ec) { +- output_debug_info_ec(ec); +- destroy(); +- } else { +- m_read_buf.commit(length); +- m_stat.inc_recv_len(length); +- m_writer(m_local_src, m_read_buf); +- +- async_read(); +- } +- }); +-} +- +-void UDPLocalForwarder::destroy(bool) { +- if (m_destroyed) { +- return; +- } +- m_destroyed = true; +- +- _log_with_endpoint(m_local_src, +- "UDP local forwarder to [" + m_remote_dst.address().to_string() + ":" + to_string(m_remote_dst.port()) + +- "] disconnected, " + m_stat.to_string(), +- Log::INFO); +- +- udp_timer_cancel(); +- +- if (m_udp_socket.is_open()) { +- boost::system::error_code ec; +- m_udp_socket.cancel(ec); +- m_udp_socket.close(); +- } +- +- if (m_destroy_cb) { +- m_destroy_cb(); +- m_destroy_cb = nullptr; +- } +-} +diff --git a/src/tun/udplocalforwarder.h b/src/tun/udplocalforwarder.h +deleted file mode 100644 +index a2707cc..0000000 +--- a/src/tun/udplocalforwarder.h ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* +- * This file is part of the Trojan Plus project. +- * Trojan is an unidentifiable mechanism that helps you bypass GFW. +- * Trojan Plus is derived from original trojan project and writing +- * for more experimental features. +- * Copyright (C) 2020 The Trojan Plus Group Authors. +- * +- * This program is free software: you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef _TROJAN_UDP_LOCAL_FORWARDER_HPP +-#define _TROJAN_UDP_LOCAL_FORWARDER_HPP +- +-#include "session/session.h" +-#include "session/udpforwardsession.h" +- +-class Service; +-class UDPLocalForwarder : public Session { +- +- Service* m_service; +- UDPForwardSession::UDPWriter m_writer; +- boost::asio::ip::udp::endpoint m_local_src; +- boost::asio::ip::udp::endpoint m_remote_dst; +- boost::asio::steady_timer m_gc_timer; +- time_t m_gc_timer_checker{}; +- boost::asio::ip::udp::socket m_udp_socket; +- +- ReadBufWithGuard m_read_buf; +- bytes_stat m_stat; +- bool m_is_dns; +- +- bool m_destroyed{false}; +- std::function m_destroy_cb; +- +- bool write_to(const std::string_view& data); +- void async_read(); +- +- public: +- UDPLocalForwarder(Service* service, boost::asio::ip::udp::endpoint local_recv, +- boost::asio::ip::udp::endpoint remote_dst, UDPForwardSession::UDPWriter&& writer, bool is_dns); +- +- ~UDPLocalForwarder() override; +- +- void start() override; +- void destroy(bool pipeline_call = false) override; +- bool process(const boost::asio::ip::udp::endpoint& endpoint, const std::string_view& data); +- +- [[nodiscard]] bool is_destroyed() const { return m_destroyed; } +- void set_destroy_callback(std::function&& destroy_cb) { m_destroy_cb = std::move(destroy_cb); } +-}; +- +-#endif //_TROJAN_UDP_LOCAL_FORWARDER_HPP +\ No newline at end of file +diff --git a/trojan-plus-android-libs b/trojan-plus-android-libs +deleted file mode 160000 +index 8f04901..0000000 +--- a/trojan-plus-android-libs ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit 8f04901af9d9ee7c7d51733f490f57ad12d25e90 +-- +2.20.1 +