From 6d733bd3b6ad7f91ab390fa494bba4ef8f880053 Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Fri, 30 Jun 2023 19:24:51 +0800 Subject: [PATCH] integrate overtls --- .gitignore | 1 + depends/ssr-native | 2 +- readme.md | 4 +- src/overtls.c | 116 ++++++++++++++++++++++++++++++ src/overtls.h | 10 +++ src/run_ssr_client.c | 48 +++++++++++-- src/run_ssr_client.h | 15 +++- src/ssrWin/main.c | 38 ++++++++-- src/ssrWin/ssrWin.vcxproj | 2 + src/ssrWin/ssrWin.vcxproj.filters | 6 ++ 10 files changed, 231 insertions(+), 11 deletions(-) create mode 100644 src/overtls.c create mode 100644 src/overtls.h diff --git a/.gitignore b/.gitignore index 86713d6..90ace96 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.sdf *.opensdf *.aps +*.json ipch/ Debug/ Release/ diff --git a/depends/ssr-native b/depends/ssr-native index d94883d..24506ef 160000 --- a/depends/ssr-native +++ b/depends/ssr-native @@ -1 +1 @@ -Subproject commit d94883d427e608508834d7a9a1541a31567f75c1 +Subproject commit 24506ef107a93505274ea03a994367a2c9633d50 diff --git a/readme.md b/readme.md index abc9cc6..d434d94 100644 --- a/readme.md +++ b/readme.md @@ -1,9 +1,11 @@ # SSR client for Windows -This client integrates [SSRoT](https://github.com/ShadowsocksR-Live/shadowsocksr-native/wiki) functions and is simple to operate. +This client integrates [overtls](https://github.com/ShadowsocksR-Live/overtls) and [SSRoT](https://github.com/ShadowsocksR-Live/shadowsocksr-native/wiki) functions and is simple to operate. This software is open source software. +[Overtls](https://github.com/ShadowsocksR-Live/overtls) server installation is [here](https://github.com/ShadowsocksR-Live/overtls#server-side-one-click-installation-script) + [SSRoT](https://github.com/ShadowsocksR-Live/shadowsocksr-native/wiki) server installation tutorial is [here](https://github.com/ShadowsocksR-Live/shadowsocksr-native/wiki/%E5%85%A8%E8%87%AA%E5%8A%A8%E5%AE%89%E8%A3%85-SSRoT-%E6%9C%8D%E5%8A%A1%E5%99%A8). Sorry for it's Chinese. ![img](img/img01.png) diff --git a/src/overtls.c b/src/overtls.c new file mode 100644 index 0000000..8b96767 --- /dev/null +++ b/src/overtls.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include "run_ssr_client.h" + +HINSTANCE hOverTls = NULL; + +bool overtls_lib_initialize(void) { + if (hOverTls != NULL) { + return true; + } + hOverTls = LoadLibraryW(L"overtls.dll"); + return (hOverTls != NULL) ? true : false; +} + +void overtls_lib_unload(void) { + if (hOverTls != NULL) { + FreeLibrary(hOverTls); + hOverTls = NULL; + } +} + +typedef int (*p_over_tls_client_run)(const char* config_path, + char verbose, + void (*callback)(int listen_port, void* ctx), + void* ctx); +typedef int (*p_over_tls_client_stop)(void); +typedef void (*p_overtls_set_log_callback)(void (*callback)(int log_level, const char* log, void* ctx), void* ctx); + +const char* get_temp_json_file_path(char json_file_name[MAX_PATH * 2]); +bool write_content_to_file(const char* content, const char* file_path); + +bool overtls_run_loop_begin(const struct server_config* cf, + void(*listen_port_callback)(int listen_port, void* ctx), + void* ctx) +{ + struct ssr_client_ctx* _ctx = (struct ssr_client_ctx*)ctx; + const struct main_wnd_data* data = get_main_wnd_data_from_ctx(_ctx); + p_log_callback callback = get_log_callback_ptr(data); + char* content = NULL; + int res = 0; + p_over_tls_client_run over_tls_client_run; + p_overtls_set_log_callback overtls_set_log_callback; + char json_file_name[MAX_PATH * 2] = { 0 }; + + get_temp_json_file_path(json_file_name); + + overtls_set_log_callback = (p_overtls_set_log_callback)GetProcAddress(hOverTls, "overtls_set_log_callback"); + if (overtls_set_log_callback == NULL) { + return false; + } + // enable overtls log dumping + overtls_set_log_callback(callback, (void*)data); + + content = config_convert_to_overtls_json(cf, &malloc); + if (content == NULL) { + return false; + } + if (false == write_content_to_file(content, json_file_name)) { + free(content); + return false; + } + free(content); + + over_tls_client_run = (p_over_tls_client_run)GetProcAddress(hOverTls, "over_tls_client_run"); + if (over_tls_client_run == NULL) { + return false; + } + // the overtls dead loop + res = over_tls_client_run(json_file_name, (char)TRUE, listen_port_callback, ctx); + assert(res == 0); + + overtls_set_log_callback(NULL, NULL); + + overtls_lib_unload(); + + return true; +} + +const char* get_temp_json_file_path(char json_file_name[MAX_PATH * 2]) { + char temp_path[MAX_PATH]; + char temp_file_name[MAX_PATH]; + + GetTempPathA(MAX_PATH, temp_path); + GetTempFileNameA(temp_path, "temp", 0, temp_file_name); + sprintf(json_file_name, "%s.json", temp_file_name); + return json_file_name; +} + +bool write_content_to_file(const char* content, const char* file_path) { + HANDLE hFile; + DWORD bytesWritten = 0; + if (content == NULL || file_path == NULL) { + return false; + } + hFile = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + if (!WriteFile(hFile, content, (DWORD)strlen(content), &bytesWritten, NULL)) { + CloseHandle(hFile); + return false; + } + CloseHandle(hFile); + return true; +} + +void overtls_client_stop(void) { + p_over_tls_client_stop over_tls_client_stop; + over_tls_client_stop = (p_over_tls_client_stop)GetProcAddress(hOverTls, "over_tls_client_stop"); + if (over_tls_client_stop != NULL) { + // stop overtls client dead loop + over_tls_client_stop(); + } +} diff --git a/src/overtls.h b/src/overtls.h new file mode 100644 index 0000000..1e066bd --- /dev/null +++ b/src/overtls.h @@ -0,0 +1,10 @@ +#pragma once + + +bool overtls_lib_initialize(void); +void overtls_lib_unload(void); + +bool overtls_run_loop_begin(const struct server_config* cf, + void(*listen_port_callback)(int listen_port, void* ctx), + void* ctx); +void overtls_client_stop(void); diff --git a/src/run_ssr_client.c b/src/run_ssr_client.c index 572e62a..66b9f49 100644 --- a/src/run_ssr_client.c +++ b/src/run_ssr_client.c @@ -10,6 +10,7 @@ #include "proxy_settings.h" #include "server_connectivity.h" #include "utf8_to_wchar.h" +#include "overtls.h" #define PRIVOXY_CONFIG_CONTENT_FMT \ "listen-address %s:%d\r\n" \ @@ -29,20 +30,32 @@ struct ssr_client_ctx { uint16_t real_listen_port; char privoxy_listen_host[MAX_PATH]; uint16_t privoxy_listen_port; + const struct main_wnd_data* wnd_data; }; +const struct main_wnd_data* get_main_wnd_data_from_ctx(const struct ssr_client_ctx* ctx) { + return ctx ? ctx->wnd_data : NULL; +} + static char error_info[MAX_PATH * 4] = { 0 }; const char* ssr_client_error_string(void) { return error_info; } -struct ssr_client_ctx* ssr_client_begin_run(struct server_config* config, const char* ssr_listen_host, int ssr_listen_port, const char* proxy_listen_host, int proxy_listen_port, int delay_quit_ms, int change_inet_opts) +struct ssr_client_ctx* ssr_client_begin_run(struct server_config* config, const struct main_wnd_data* data) { struct ssr_client_ctx* ctx = NULL; DWORD threadId = 0; int error_code = 0; + const char* ssr_listen_host = get_ssr_listen_host(data); + int ssr_listen_port = get_ssr_listen_port(data); + const char* proxy_listen_host = get_privoxy_listen_host(data); + int proxy_listen_port = get_privoxy_listen_port(data); + int delay_quit_ms = get_delay_quit_ms(data); + int change_inet_opts = get_change_inet_opts(data); + error_info[0] = '\0'; if (ssr_listen_port != 0) { @@ -69,6 +82,7 @@ struct ssr_client_ctx* ssr_client_begin_run(struct server_config* config, const } ctx = (struct ssr_client_ctx*)calloc(1, sizeof(*ctx)); + ctx->wnd_data = data; ctx->config = config_clone(config); @@ -85,7 +99,12 @@ struct ssr_client_ctx* ssr_client_begin_run(struct server_config* config, const WaitForSingleObject(ctx->hOrderKeeper, INFINITE); CloseHandle(ctx->hOrderKeeper); - error_code = ssr_get_client_error_code(ctx->state); + if (overtls_lib_initialize() && config_is_overtls(ctx->config)) { + error_code = 0; + } + else { + error_code = ssr_get_client_error_code(ctx->state); + } if (error_code == 0) { ctx->hPrivoxySvr = CreateThread(NULL, 0, PrivoxyThread, ctx, 0, &threadId); if (change_inet_opts != 0) { @@ -109,7 +128,12 @@ struct ssr_client_ctx* ssr_client_begin_run(struct server_config* config, const void ssr_client_terminate(struct ssr_client_ctx* ctx) { if (ctx) { - ssr_run_loop_shutdown(ctx->state); + if (overtls_lib_initialize() && config_is_overtls(ctx->config)) { + assert(ctx->state == NULL); + overtls_client_stop(); + }else { + ssr_run_loop_shutdown(ctx->state); + } WaitForSingleObject(ctx->hSsrClient, INFINITE); CloseHandle(ctx->hSsrClient); config_release(ctx->config); @@ -134,9 +158,25 @@ static void ssr_feedback_state(struct ssr_client_state* state, void* p) { SetEvent(ctx->hOrderKeeper); } +static void listen_port_callback(int listen_port, void* p) { + struct ssr_client_ctx* ctx = (struct ssr_client_ctx*)p; + ctx->real_listen_port = listen_port; + SetEvent(ctx->hOrderKeeper); +} + static DWORD WINAPI SsrClientThread(LPVOID lpParam) { struct ssr_client_ctx* ctx = (struct ssr_client_ctx*)lpParam; - ssr_run_loop_begin(ctx->config, &ssr_feedback_state, ctx); + if (overtls_lib_initialize() && config_is_overtls(ctx->config)) { + // run overtls thread + if (false == overtls_run_loop_begin(ctx->config, &listen_port_callback, ctx)) { + listen_port_callback(0, ctx); + } + } + else { + set_dump_info_callback(get_log_callback_ptr(ctx->wnd_data), (void*)ctx->wnd_data); + ssr_run_loop_begin(ctx->config, &ssr_feedback_state, ctx); + set_dump_info_callback(NULL, NULL); + } return 0; } diff --git a/src/run_ssr_client.h b/src/run_ssr_client.h index 121ee12..245b6d8 100644 --- a/src/run_ssr_client.h +++ b/src/run_ssr_client.h @@ -14,11 +14,24 @@ extern "C" { struct ssr_client_ctx; struct server_config; +struct main_wnd_data; -struct ssr_client_ctx* ssr_client_begin_run(struct server_config* config, const char* ssr_listen_host, int ssr_listen_port, const char* proxy_listen_host, int proxy_listen_port, int delay_quit_ms, int change_inet_opts); +struct ssr_client_ctx* ssr_client_begin_run(struct server_config* config, const struct main_wnd_data* data); void ssr_client_terminate(struct ssr_client_ctx* ctx); const char* ssr_client_error_string(void); +const struct main_wnd_data* get_main_wnd_data_from_ctx(const struct ssr_client_ctx *ctx); + +typedef void (*p_log_callback)(int log_level, const char* log, void* ctx); +p_log_callback get_log_callback_ptr(const struct main_wnd_data* data); + +const char* get_ssr_listen_host(const struct main_wnd_data* data); +int get_ssr_listen_port(const struct main_wnd_data* data); +const char* get_privoxy_listen_host(const struct main_wnd_data* data); +int get_privoxy_listen_port(const struct main_wnd_data* data); +int get_delay_quit_ms(const struct main_wnd_data* data); +int get_change_inet_opts(const struct main_wnd_data* data); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/ssrWin/main.c b/src/ssrWin/main.c index 6a5f64c..6323fe2 100644 --- a/src/ssrWin/main.c +++ b/src/ssrWin/main.c @@ -41,6 +41,8 @@ struct main_wnd_data { int privoxy_listen_port; int delay_quit_ms; int change_inet_opts; + + void (*log_info_callback)(int log_level, const char* log, void* ctx); }; #define TRAY_ICON_ID 1 @@ -350,7 +352,7 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar else { assert(wnd_data->client_ctx == NULL); config = retrieve_config_from_list_view(wnd_data->hListView, wnd_data->cur_selected); - wnd_data->client_ctx = ssr_client_begin_run(config, wnd_data->ssr_listen_host, wnd_data->ssr_listen_port, wnd_data->privoxy_listen_host, wnd_data->privoxy_listen_port, wnd_data->delay_quit_ms, wnd_data->change_inet_opts); + wnd_data->client_ctx = ssr_client_begin_run(config, wnd_data); if (wnd_data->client_ctx == NULL) { const char*info = ssr_client_error_string(); put_string_to_rich_edit_control(wnd_data->hWndLogBox, TRUE, info, 2); @@ -416,7 +418,7 @@ struct dump_info { char* info; }; -static void dump_info_callback(int dump_level, const char* info, void* p) { +void dump_info_callback(int dump_level, const char* info, void* p) { struct main_wnd_data* wnd_data = (struct main_wnd_data*)p; WaitForSingleObject(wnd_data->mutex_dump_info, INFINITE); { @@ -540,7 +542,7 @@ static void on_wm_create(HWND hWnd, LPCREATESTRUCTW pcs) } set_app_name(APP_NAME_KEY); - set_dump_info_callback(dump_info_callback, wnd_data); + wnd_data->log_info_callback = dump_info_callback; do { static struct server_config* config; @@ -555,7 +557,7 @@ static void on_wm_create(HWND hWnd, LPCREATESTRUCTW pcs) assert(wnd_data->client_ctx == NULL); config = retrieve_config_from_list_view(wnd_data->hListView, index); assert(config); - wnd_data->client_ctx = ssr_client_begin_run(config, wnd_data->ssr_listen_host, wnd_data->ssr_listen_port, wnd_data->privoxy_listen_host, wnd_data->privoxy_listen_port, wnd_data->delay_quit_ms, wnd_data->change_inet_opts); + wnd_data->client_ctx = ssr_client_begin_run(config, wnd_data); if (wnd_data->client_ctx == NULL) { const char*info = ssr_client_error_string(); put_string_to_rich_edit_control(wnd_data->hWndLogBox, TRUE, info, 2); @@ -563,6 +565,34 @@ static void on_wm_create(HWND hWnd, LPCREATESTRUCTW pcs) } while (0); } +p_log_callback get_log_callback_ptr(const struct main_wnd_data* data) { + return data ? data->log_info_callback : NULL; +} + +const char * get_ssr_listen_host(const struct main_wnd_data* data) { + return data ? data->ssr_listen_host : NULL; +} + +int get_ssr_listen_port(const struct main_wnd_data* data) { + return data ? data->ssr_listen_port : 0; +} + +const char * get_privoxy_listen_host(const struct main_wnd_data* data) { + return data ? data->privoxy_listen_host : NULL; +} + +int get_privoxy_listen_port(const struct main_wnd_data* data) { + return data ? data->privoxy_listen_port : 0; +} + +int get_delay_quit_ms(const struct main_wnd_data* data) { + return data ? data->delay_quit_ms : 0; +} + +int get_change_inet_opts(const struct main_wnd_data* data) { + return data ? data->change_inet_opts : 0; +} + static void on_wm_destroy(HWND hWnd) { struct main_wnd_data* wnd_data; wnd_data = (struct main_wnd_data*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); diff --git a/src/ssrWin/ssrWin.vcxproj b/src/ssrWin/ssrWin.vcxproj index 2b41868..c14ed42 100644 --- a/src/ssrWin/ssrWin.vcxproj +++ b/src/ssrWin/ssrWin.vcxproj @@ -153,6 +153,7 @@ + @@ -172,6 +173,7 @@ + diff --git a/src/ssrWin/ssrWin.vcxproj.filters b/src/ssrWin/ssrWin.vcxproj.filters index ebe3f0c..2ab07fa 100644 --- a/src/ssrWin/ssrWin.vcxproj.filters +++ b/src/ssrWin/ssrWin.vcxproj.filters @@ -66,6 +66,9 @@ Source Files + + Header Files + @@ -119,6 +122,9 @@ Source Files + + Source Files +