liudf0716 / xfrpc

The xfrpc project is a lightweight implementation of the FRP client written in C language for OpenWRT and IoT systems. It is designed to provide an efficient solution for resource-constrained devices such as OpenWRT routers and IoT devices, which often have limited ROM and RAM space.
GNU General Public License v3.0
721 stars 92 forks source link

在编译成so动态库后,调用.so的启动方法无法登录到frps #56

Closed jackylany closed 3 months ago

jackylany commented 5 months ago

平台:aarch64 GNU/Linux

run.c

#include "xfrpc.h"
#include "login.h"
#include "config.h"

void run();
void run()
{
    char *server_addr = "serverIp";
    int port = 10000;

    make_config(server_addr, port);
    init_login();
    xfrpc_loop();
}

config.c 增加

void make_config(char *server_addr, int port)
{
    c_conf = (struct common_conf *)calloc(sizeof(struct common_conf), 1);
    assert(c_conf);

    init_common_conf(c_conf);

    c_conf->server_addr         = strdup(server_addr);
    assert(c_conf->server_addr);
    c_conf->server_port         = port;

    dump_common_conf();

    struct proxy_service *ps = NULL;
    ps = new_proxy_service(strdup("socks5"));
    if (! ps) {
        debug(LOG_ERR, "cannot create proxy service, it should not happenned!");
        exit(0);
    }

    HASH_ADD_KEYPTR(hh, all_ps, ps->proxy_name, strlen(ps->proxy_name), ps);
    ps->proxy_type = strdup("tcp");
    ps->remote_port = 11000;
    ps->plugin = strdup("socks5");
    ps->local_ip = strdup("127.0.0.1");
    ps->local_port = 10801;

    dump_all_ps();
}

CMakeLists.txt 修改为

cmake_minimum_required(VERSION 2.8.12)

project(xfrp C)

if (THIRDPARTY_STATIC_BUILD STREQUAL "ON" OR  THIRDPARTY_STATIC_BUILD STREQUAL "mips" OR THIRDPARTY_STATIC_BUILD STREQUAL "arm")
    add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/)
    include_directories(${PROJECT_SOURCE_DIR}/thirdparty/include/libevent)
    include_directories(${PROJECT_SOURCE_DIR}/thirdparty/include/)
    link_directories(${PROJECT_SOURCE_DIR}/thirdparty/libs/)
    set(static_libs dl pthread)
else()
    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

    find_package(LibEvent)
    if(NOT LibEvent_FOUND)
      message(FATAL_ERROR "LibEvent not found!")
    endif(NOT LibEvent_FOUND)

    find_package(OpenSSL)
    if(NOT OPENSSL_FOUND)
      message(FATAL_ERROR "OpenSSL not found!")
    endif(NOT OPENSSL_FOUND)

    find_package(JSON-C REQUIRED)
    include_directories(${JSON-C_INCLUDE_DIR})
endif(THIRDPARTY_STATIC_BUILD)

macro(check_asan _RESULT)
    include(CheckCSourceRuns)
    set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
    check_c_source_runs(
            [====[
int main()
{
  return 0;
}
]====]
            ${_RESULT}
    )
    unset(CMAKE_REQUIRED_FLAGS)
endmacro()

# Enable address sanitizer
option(ENABLE_SANITIZER "Enable sanitizer(Debug+Gcc/Clang/AppleClang)" ON)
if(ENABLE_SANITIZER AND NOT MSVC)
    if(CMAKE_BUILD_TYPE STREQUAL "Debug")
        check_asan(HAS_ASAN)
        if(HAS_ASAN)
        message(WARNING "add sanitizer")
        set(asan_c_flags "-fsanitize=address -fsanitize=leak")
        set(asan_c_libs "asan")
        else()
            message(WARNING "sanitizer is no supported with current tool-chains")
        endif()
    else()
        message(WARNING "Sanitizer supported only for debug type")
    endif()
endif()

set(src_xfrpc
    run.c
    client.c
    config.c
    control.c
    ini.c
    msg.c
    xfrpc.c
    debug.c
    zip.c
    commandline.c
    crypto.c
    fastpbkdf2.c
    utils.c
    common.c
    login.c
    proxy_tcp.c
    proxy_udp.c
    proxy_ftp.c
    proxy.c
    tcpmux.c
    tcp_redir.c
    mongoose.c
    )

set(src_xfrpc_plugins
    plugins/telnetd.c
    plugins/instaloader.c
    plugins/httpd.c
    plugins/youtubedl.c
    plugins/socksv5.c
    )

set(libs
    ssl
    crypto
    event
    z
    m
    json-c
    crypt
    pthread)

set(test_libs
    event
    )

ADD_DEFINITIONS(-Wall -g -Wno-deprecated-declarations --std=gnu99 -fPIC ${asan_c_flags})

if (STATIC_BUILD STREQUAL "ON")
  add_link_options(-static)
endif (STATIC_BUILD)

add_library(xfrpc SHARED ${src_xfrpc} ${src_xfrpc_plugins})
target_link_libraries(xfrpc ${libs} ${static_libs} ${asan_c_libs})

install(TARGETS xfrpc
        RUNTIME DESTINATION lib
)

执行: cmake .. make 生成了 libxfrpc.so

然后在另一段代码中调用编译出的so

#include <stdio.h>
#include <dlfcn.h>

// 定义一个辅助函数来隐藏复杂的类型转换
void* get_function(void* handle, const char* function_name) {
    if (!handle || !function_name) return NULL;
    void* func_ptr = dlsym(handle, function_name);
    char* error = dlerror();
    if (error) {
        fprintf(stderr, "Error fetching symbol %s: %s\n", function_name, error);
        return NULL;
    }
    return func_ptr;
}

int main(int argc, char *argv[])
{
    void *handle = NULL;
    void (*run)() = NULL;
    char *error = NULL;

    handle = dlopen("./libxfrpc.so", RTLD_LAZY);
    if (!handle) {
        error = dlerror();
        if (error) {
            fputs(error, stderr);
        }
        return 1;
    }

    // 清除之前的错误信息,避免干扰
    dlerror();

    // 使用辅助函数获取函数指针
    run = (void (*)()) get_function(handle, "run");
    if (!run) {
        fputs("Failed to get function 'run' from the library.\n", stderr);
        dlclose(handle);
        return 1;
    }

    // 执行函数
    run();

    // 在执行 dlclose 之前,确保 handle 不是 NULL
    // 实际上,在当前逻辑中,如果 dlopen 成功,handle 不会是 NULL,
    // 但添加这个检查可以增加代码的健壮性
    if (handle) {
        dlclose(handle);
    }

    return 0;
}

结果是卡在了 [6][Wed Jun 19 16:50:13 2024][45940](control.c:702) connect server [x.x.x.x:10000]...

如果是在run.c中直接用main函数去调用run,编译成可执行文件那就可以正常登录到 frps

我也尝试过在 cmake 的时候加上 -D THIRDPARTY_STATIC_BUILD=ON,结果编译的 libxfrpc.so 也是卡在了连接 frps 那里

请问是 CMakeLists.txt 文件出问题了吗?还是哪里有更大的问题?

希望能够得到解答,十分感谢🙏

jackylany commented 5 months ago

暂时的解决方式 把 control.c 里面的 login 方法改名就可以了,奇怪的问题

是因为导出的 login 有冲突吗?但是编译成可执行文件又是正常的运行,为什么呢?

liudf0716 commented 3 months ago

不好意思,xfrpc作为一个完整的开源项目,不支持这种将xfrpc作为其它项目的子项目的方式。您可以自己私下学习研究,谢谢!

jackylany commented 3 months ago

不好意思,xfrpc作为一个完整的开源项目,不支持这种将xfrpc作为其它项目的子项目的方式。您可以自己私下学习研究,谢谢!

感谢大佬的回答,期待大佬添加更多的功能