diff --git a/src/config/config.cpp b/src/config/config.cpp index ffb40728c..9e88b11a3 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -49,9 +49,6 @@ bool ReadConfig() { config_impl->Read("fast_open", &FLAGS_tcp_fastopen); config_impl->Read("fast_open_connect", &FLAGS_tcp_fastopen_connect); -#ifdef __linux__ - config_impl->Read("congestion_algorithm", &FLAGS_congestion_algorithm); -#endif config_impl->Read("doh_url", &FLAGS_doh_url); config_impl->Read("dot_host", &FLAGS_dot_host); config_impl->Read("connect_timeout", &FLAGS_connect_timeout); @@ -62,6 +59,7 @@ bool ReadConfig() { config_impl->Read("tcp_keep_alive_cnt", &FLAGS_tcp_keep_alive_cnt); config_impl->Read("tcp_keep_alive_idle_timeout", &FLAGS_tcp_keep_alive_idle_timeout); config_impl->Read("tcp_keep_alive_interval", &FLAGS_tcp_keep_alive_interval); + config_impl->Read("tcp_congestion_algorithm", &FLAGS_tcp_congestion_algorithm); /* optional tls fields */ config_impl->Read("cacert", &FLAGS_cacert); @@ -121,9 +119,6 @@ bool SaveConfig() { all_fields_written &= config_impl->Write("fast_open", FLAGS_tcp_fastopen); all_fields_written &= config_impl->Write("fast_open_connect", FLAGS_tcp_fastopen_connect); static_cast(config_impl->Delete("threads")); -#ifdef __linux__ - all_fields_written &= config_impl->Write("congestion_algorithm", FLAGS_congestion_algorithm); -#endif all_fields_written &= config_impl->Write("doh_url", FLAGS_doh_url); all_fields_written &= config_impl->Write("dot_host", FLAGS_dot_host); all_fields_written &= config_impl->Write("timeout", FLAGS_connect_timeout); @@ -135,6 +130,7 @@ bool SaveConfig() { all_fields_written &= config_impl->Write("tcp_keep_alive_cnt", FLAGS_tcp_keep_alive_cnt); all_fields_written &= config_impl->Write("tcp_keep_alive_idle_timeout", FLAGS_tcp_keep_alive_idle_timeout); all_fields_written &= config_impl->Write("tcp_keep_alive_interval", FLAGS_tcp_keep_alive_interval); + all_fields_written &= config_impl->Write("tcp_congestion_algorithm", FLAGS_tcp_congestion_algorithm); all_fields_written &= config_impl->Write("cacert", FLAGS_cacert); all_fields_written &= config_impl->Write("capath", FLAGS_capath); diff --git a/src/config/config_network.cpp b/src/config/config_network.cpp index a36fed662..e00fd278c 100644 --- a/src/config/config_network.cpp +++ b/src/config/config_network.cpp @@ -8,9 +8,6 @@ ABSL_FLAG(bool, ipv6_mode, true, "Resolve names to IPv6 addresses"); ABSL_FLAG(bool, reuse_port, true, "Reuse the listening port"); -#ifdef __linux__ -ABSL_FLAG(std::string, congestion_algorithm, "", "TCP Congestion Algorithm"); -#endif ABSL_FLAG(bool, tcp_fastopen, false, "TCP fastopen"); ABSL_FLAG(bool, tcp_fastopen_connect, false, "TCP fastopen connect"); ABSL_FLAG(int32_t, connect_timeout, 0, "Connect timeout (in seconds)"); @@ -24,6 +21,7 @@ ABSL_FLAG(int32_t, 7200, "The number of seconds a connection needs to be idle before TCP begins sending out keep-alive probes."); ABSL_FLAG(int32_t, tcp_keep_alive_interval, 75, "The number of seconds between TCP keep-alive probes."); +ABSL_FLAG(std::string, tcp_congestion_algorithm, "", "TCP Congestion Algorithm (Linux Only)"); ABSL_FLAG(bool, redir_mode, false, "Enable TCP Redir mode support (linux only)"); ABSL_FLAG(std::string, doh_url, "", "Resolve host names over DoH"); diff --git a/src/config/config_network.hpp b/src/config/config_network.hpp index 71f426858..9ca21d057 100644 --- a/src/config/config_network.hpp +++ b/src/config/config_network.hpp @@ -10,9 +10,6 @@ ABSL_DECLARE_FLAG(bool, ipv6_mode); ABSL_DECLARE_FLAG(bool, reuse_port); -#ifdef __linux__ -ABSL_DECLARE_FLAG(std::string, congestion_algorithm); -#endif ABSL_DECLARE_FLAG(bool, tcp_fastopen); ABSL_DECLARE_FLAG(bool, tcp_fastopen_connect); // same with proxy_connect_timeout no need for proxy_read_timeout @@ -25,6 +22,7 @@ ABSL_DECLARE_FLAG(bool, tcp_keep_alive); ABSL_DECLARE_FLAG(int32_t, tcp_keep_alive_cnt); ABSL_DECLARE_FLAG(int32_t, tcp_keep_alive_idle_timeout); ABSL_DECLARE_FLAG(int32_t, tcp_keep_alive_interval); +ABSL_DECLARE_FLAG(std::string, tcp_congestion_algorithm); ABSL_DECLARE_FLAG(bool, redir_mode); ABSL_DECLARE_FLAG(std::string, doh_url); diff --git a/src/gtk/option_dialog.cpp b/src/gtk/option_dialog.cpp index d8e530571..f44286e86 100644 --- a/src/gtk/option_dialog.cpp +++ b/src/gtk/option_dialog.cpp @@ -10,6 +10,7 @@ #include "core/logging.hpp" #include "core/utils.hpp" #include "gtk/utils.hpp" +#include "net/network.hpp" OptionDialog::OptionDialog(const std::string& title, GtkWindow* parent, bool modal) : impl_(GTK_DIALOG(gtk_dialog_new_with_buttons(title.c_str(), @@ -27,12 +28,14 @@ OptionDialog::OptionDialog(const std::string& title, GtkWindow* parent, bool mod auto tcp_keep_alive_interval_label = gtk_label_new(_("TCP keep alive interval")); auto enable_post_quantum_kyber_label = gtk_label_new(_("Kyber post-quantum key agreement for TLS")); + auto tcp_congestion_algorithm = gtk_label_new(_("TCP Congestion Algorithm")); gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_label), 0, 0, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_cnt_label), 0, 1, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_idle_timeout_label), 0, 2, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_interval_label), 0, 3, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(enable_post_quantum_kyber_label), 0, 4, 1, 1); + gtk_grid_attach(grid, GTK_WIDGET(tcp_congestion_algorithm), 0, 5, 1, 1); tcp_keep_alive_ = GTK_CHECK_BUTTON(gtk_check_button_new()); tcp_keep_alive_cnt_ = GTK_ENTRY(gtk_entry_new()); @@ -40,11 +43,19 @@ OptionDialog::OptionDialog(const std::string& title, GtkWindow* parent, bool mod tcp_keep_alive_interval_ = GTK_ENTRY(gtk_entry_new()); enable_post_quantum_kyber_ = GTK_CHECK_BUTTON(gtk_check_button_new()); + algorithms_ = net::GetTCPAvailableCongestionAlgorithms(); + + tcp_congestion_algorithm_ = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new()); + for (const auto& algorithm : algorithms_) { + gtk_combo_box_text_append_text(tcp_congestion_algorithm_, algorithm.c_str()); + } + gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_), 1, 0, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_cnt_), 1, 1, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_idle_timeout_), 1, 2, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(tcp_keep_alive_interval_), 1, 3, 1, 1); gtk_grid_attach(grid, GTK_WIDGET(enable_post_quantum_kyber_), 1, 4, 1, 1); + gtk_grid_attach(grid, GTK_WIDGET(tcp_congestion_algorithm_), 1, 5, 1, 1); gtk_widget_set_margin_top(GTK_WIDGET(grid), 12); gtk_widget_set_margin_bottom(GTK_WIDGET(grid), 12); @@ -79,8 +90,8 @@ OptionDialog::OptionDialog(const std::string& title, GtkWindow* parent, bool mod g_signal_connect(G_OBJECT(cancel_button_), "clicked", G_CALLBACK(*cancel_callback), this); - gtk_grid_attach(grid, GTK_WIDGET(okay_button_), 0, 5, 1, 1); - gtk_grid_attach(grid, GTK_WIDGET(cancel_button_), 1, 5, 1, 1); + gtk_grid_attach(grid, GTK_WIDGET(okay_button_), 0, 6, 1, 1); + gtk_grid_attach(grid, GTK_WIDGET(cancel_button_), 1, 6, 1, 1); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(impl_)), GTK_WIDGET(grid)); @@ -120,6 +131,19 @@ void OptionDialog::LoadChanges() { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_post_quantum_kyber_), absl::GetFlag(FLAGS_enable_post_quantum_kyber)); + + auto algorithm = absl::GetFlag(FLAGS_tcp_congestion_algorithm); + unsigned int i; + for (i = 0; i < std::size(algorithms_); ++i) { + if (algorithm == algorithms_[i]) + break; + } + + // first is unset + if (i == std::size(algorithms_)) { + i = 0; + } + gtk_combo_box_set_active(GTK_COMBO_BOX(tcp_congestion_algorithm_), i); } bool OptionDialog::OnSave() { @@ -143,5 +167,12 @@ bool OptionDialog::OnSave() { absl::SetFlag(&FLAGS_enable_post_quantum_kyber, enable_post_quantum_kyber); + gchar* algorithm_cstr = gtk_combo_box_text_get_active_text(tcp_congestion_algorithm_); + if (algorithm_cstr == nullptr || std::string_view(algorithm_cstr).empty()) { + absl::SetFlag(&FLAGS_tcp_congestion_algorithm, std::string()); + } else { + absl::SetFlag(&FLAGS_tcp_congestion_algorithm, algorithm_cstr); + } + return true; } diff --git a/src/gtk/option_dialog.hpp b/src/gtk/option_dialog.hpp index 3ccc4acff..a4b851390 100644 --- a/src/gtk/option_dialog.hpp +++ b/src/gtk/option_dialog.hpp @@ -6,6 +6,7 @@ #include #include +#include class OptionDialog { public: @@ -26,6 +27,8 @@ class OptionDialog { GtkEntry* tcp_keep_alive_idle_timeout_; GtkEntry* tcp_keep_alive_interval_; GtkCheckButton* enable_post_quantum_kyber_; + GtkComboBoxText* tcp_congestion_algorithm_; + std::vector algorithms_; GtkButton* okay_button_; GtkButton* cancel_button_; diff --git a/src/gtk/yass_en.po b/src/gtk/yass_en.po index 3d4d1dd02..fef372f9d 100644 --- a/src/gtk/yass_en.po +++ b/src/gtk/yass_en.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-07-09 09:55+0800\n" +"POT-Creation-Date: 2024-08-26 14:19+0800\n" "PO-Revision-Date: 2023-09-15 11:18+0800\n" "Last-Translator: Chilledheart \n" "Language-Team: Chilledheart \n" @@ -17,170 +17,174 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: option_dialog.cpp:27 +#: option_dialog.cpp:25 msgid "TCP keep alive" msgstr "TCP keep alive" -#: option_dialog.cpp:28 +#: option_dialog.cpp:26 msgid "The number of TCP keep-alive probes" msgstr "The number of TCP keep-alive probes" -#: option_dialog.cpp:29 +#: option_dialog.cpp:27 msgid "TCP keep alive after idle" msgstr "TCP keep alive after idle" -#: option_dialog.cpp:30 +#: option_dialog.cpp:28 msgid "TCP keep alive interval" msgstr "TCP keep alive interval" -#: option_dialog.cpp:32 +#: option_dialog.cpp:30 msgid "Kyber post-quantum key agreement for TLS" msgstr "Kyber post-quantum key agreement for TLS" -#: option_dialog.cpp:53 +#: option_dialog.cpp:32 +msgid "TCP Congestion Algorithm" +msgstr "TCP Congestion Algorithm" + +#: option_dialog.cpp:76 msgid "Okay" msgstr "Okay" -#: option_dialog.cpp:56 +#: option_dialog.cpp:79 msgid "Cancel" msgstr "Cancel" -#: yass.cpp:234 +#: yass.cpp:232 msgid "Connected with conns: " msgstr "Connected with conns: " -#: yass.cpp:236 +#: yass.cpp:234 msgid "Connecting" msgstr "Connecting" -#: yass.cpp:238 +#: yass.cpp:236 msgid "Failed to connect due to " msgstr "Failed to connect due to " -#: yass.cpp:240 +#: yass.cpp:238 msgid "Disconnecting" msgstr "Disconnecting" -#: yass.cpp:242 +#: yass.cpp:240 msgid "Disconnected with " msgstr "Disconnected with " -#: yass_window.cpp:67 +#: yass_window.cpp:64 msgid "File" msgstr "File" -#: yass_window.cpp:68 yass_window.cpp:311 yass_window.cpp:370 +#: yass_window.cpp:65 yass_window.cpp:323 yass_window.cpp:383 msgid "Option..." msgstr "Option..." -#: yass_window.cpp:69 yass_window.cpp:312 yass_window.cpp:371 +#: yass_window.cpp:66 yass_window.cpp:324 yass_window.cpp:384 msgid "Exit" msgstr "Exit" -#: yass_window.cpp:92 +#: yass_window.cpp:89 msgid "Help" msgstr "Help" -#: yass_window.cpp:93 +#: yass_window.cpp:90 msgid "About..." msgstr "About..." -#: yass_window.cpp:108 +#: yass_window.cpp:105 msgid "Start" msgstr "Start" -#: yass_window.cpp:114 +#: yass_window.cpp:109 msgid "Stop" msgstr "Stop" -#: yass_window.cpp:147 +#: yass_window.cpp:131 msgid "Server Host" msgstr "Server Host" -#: yass_window.cpp:148 +#: yass_window.cpp:132 msgid "Server SNI" msgstr "Server SNI" -#: yass_window.cpp:149 +#: yass_window.cpp:133 msgid "Server Port" msgstr "Server Port" -#: yass_window.cpp:150 +#: yass_window.cpp:134 msgid "Username" msgstr "Username" -#: yass_window.cpp:151 +#: yass_window.cpp:135 msgid "Password" msgstr "Password" -#: yass_window.cpp:152 +#: yass_window.cpp:136 msgid "Cipher/Method" msgstr "Cipher/Method" -#: yass_window.cpp:153 +#: yass_window.cpp:137 msgid "Local Host" msgstr "Local Host" -#: yass_window.cpp:154 +#: yass_window.cpp:138 msgid "Local Port" msgstr "Local Port" -#: yass_window.cpp:155 +#: yass_window.cpp:139 msgid "DNS over HTTPS URL" msgstr "DNS over HTTPS URL" -#: yass_window.cpp:156 +#: yass_window.cpp:140 msgid "DNS over TLS Host" msgstr "DNS over TLS Host" -#: yass_window.cpp:157 +#: yass_window.cpp:141 msgid "Limit Rate" msgstr "Limit Rate" -#: yass_window.cpp:158 +#: yass_window.cpp:142 msgid "Timeout" msgstr "Timeout" -#: yass_window.cpp:159 +#: yass_window.cpp:143 msgid "Auto Start" msgstr "Auto Start" -#: yass_window.cpp:160 +#: yass_window.cpp:144 msgid "System Proxy" msgstr "System Proxy" -#: yass_window.cpp:263 +#: yass_window.cpp:275 msgid "READY" msgstr "READY" -#: yass_window.cpp:336 yass_window.cpp:369 +#: yass_window.cpp:348 yass_window.cpp:382 msgid "Show" msgstr "Show" -#: yass_window.cpp:531 +#: yass_window.cpp:544 msgid " tx rate: " msgstr " tx rate: " -#: yass_window.cpp:534 +#: yass_window.cpp:547 msgid " rx rate: " msgstr " rx rate: " -#: yass_window.cpp:645 +#: yass_window.cpp:658 msgid "YASS Option" msgstr "YASS Option" -#: yass_window.cpp:656 +#: yass_window.cpp:669 msgid "Last Change: " msgstr "Last Change: " -#: yass_window.cpp:659 +#: yass_window.cpp:672 msgid "Enabled Feature: " msgstr "Enabled Feature: " -#: yass_window.cpp:662 +#: yass_window.cpp:675 msgid "GUI Variant: " msgstr "GUI Variant: " -#: yass_window.cpp:671 +#: yass_window.cpp:684 msgid "official-site" msgstr "official-site" diff --git a/src/gtk/yass_zh_CN.po b/src/gtk/yass_zh_CN.po index a7fb02519..94ceccf4c 100644 --- a/src/gtk/yass_zh_CN.po +++ b/src/gtk/yass_zh_CN.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-07-09 09:55+0800\n" +"POT-Creation-Date: 2024-08-26 14:19+0800\n" "PO-Revision-Date: 2023-09-15 11:26+0800\n" "Last-Translator: Chilledheart \n" "Language-Team: Chilledheart \n" @@ -18,170 +18,174 @@ msgstr "" "X-Generator: Poedit 2.2.4\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: option_dialog.cpp:27 +#: option_dialog.cpp:25 msgid "TCP keep alive" msgstr "TCP 保活" -#: option_dialog.cpp:28 +#: option_dialog.cpp:26 msgid "The number of TCP keep-alive probes" msgstr "TCP 保活测量数" -#: option_dialog.cpp:29 +#: option_dialog.cpp:27 msgid "TCP keep alive after idle" msgstr "TCP 在闲置以后的保活次数" -#: option_dialog.cpp:30 +#: option_dialog.cpp:28 msgid "TCP keep alive interval" msgstr "TCP 保活间隔" -#: option_dialog.cpp:32 +#: option_dialog.cpp:30 msgid "Kyber post-quantum key agreement for TLS" msgstr "TLS的Kyber后量子密钥协商" -#: option_dialog.cpp:53 +#: option_dialog.cpp:32 +msgid "TCP Congestion Algorithm" +msgstr "TCP 拥塞算法" + +#: option_dialog.cpp:76 msgid "Okay" msgstr "确认" -#: option_dialog.cpp:56 +#: option_dialog.cpp:79 msgid "Cancel" msgstr "取消" -#: yass.cpp:234 +#: yass.cpp:232 msgid "Connected with conns: " msgstr "已产生连接: " -#: yass.cpp:236 +#: yass.cpp:234 msgid "Connecting" msgstr "连接中" -#: yass.cpp:238 +#: yass.cpp:236 msgid "Failed to connect due to " msgstr "无法连接因为 " -#: yass.cpp:240 +#: yass.cpp:238 msgid "Disconnecting" msgstr "断开连接中" -#: yass.cpp:242 +#: yass.cpp:240 msgid "Disconnected with " msgstr "断开连接于服务器 " -#: yass_window.cpp:67 +#: yass_window.cpp:64 msgid "File" msgstr "文件" -#: yass_window.cpp:68 yass_window.cpp:311 yass_window.cpp:370 +#: yass_window.cpp:65 yass_window.cpp:323 yass_window.cpp:383 msgid "Option..." msgstr "选项..." -#: yass_window.cpp:69 yass_window.cpp:312 yass_window.cpp:371 +#: yass_window.cpp:66 yass_window.cpp:324 yass_window.cpp:384 msgid "Exit" msgstr "退出" -#: yass_window.cpp:92 +#: yass_window.cpp:89 msgid "Help" msgstr "帮助" -#: yass_window.cpp:93 +#: yass_window.cpp:90 msgid "About..." msgstr "关于..." -#: yass_window.cpp:108 +#: yass_window.cpp:105 msgid "Start" msgstr "启动" -#: yass_window.cpp:114 +#: yass_window.cpp:109 msgid "Stop" msgstr "停止" -#: yass_window.cpp:147 +#: yass_window.cpp:131 msgid "Server Host" msgstr "服务器域名" -#: yass_window.cpp:148 +#: yass_window.cpp:132 msgid "Server SNI" msgstr "服务器名称指示" -#: yass_window.cpp:149 +#: yass_window.cpp:133 msgid "Server Port" msgstr "服务器端口号" -#: yass_window.cpp:150 +#: yass_window.cpp:134 msgid "Username" msgstr "用户名" -#: yass_window.cpp:151 +#: yass_window.cpp:135 msgid "Password" msgstr "密码" -#: yass_window.cpp:152 +#: yass_window.cpp:136 msgid "Cipher/Method" msgstr "加密方式" -#: yass_window.cpp:153 +#: yass_window.cpp:137 msgid "Local Host" msgstr "本地域名" -#: yass_window.cpp:154 +#: yass_window.cpp:138 msgid "Local Port" msgstr "本地端口号" -#: yass_window.cpp:155 +#: yass_window.cpp:139 msgid "DNS over HTTPS URL" msgstr "基于 HTTPS 的 DNS (DoH) URL" -#: yass_window.cpp:156 +#: yass_window.cpp:140 msgid "DNS over TLS Host" msgstr "基于 TLS 的 DNS (DoT) 域名" -#: yass_window.cpp:157 +#: yass_window.cpp:141 msgid "Limit Rate" msgstr "限制速率" -#: yass_window.cpp:158 +#: yass_window.cpp:142 msgid "Timeout" msgstr "超时时间" -#: yass_window.cpp:159 +#: yass_window.cpp:143 msgid "Auto Start" msgstr "随系统自启动" -#: yass_window.cpp:160 +#: yass_window.cpp:144 msgid "System Proxy" msgstr "系统代理" -#: yass_window.cpp:263 +#: yass_window.cpp:275 msgid "READY" msgstr "就绪" -#: yass_window.cpp:336 yass_window.cpp:369 +#: yass_window.cpp:348 yass_window.cpp:382 msgid "Show" msgstr "唤醒" -#: yass_window.cpp:531 +#: yass_window.cpp:544 msgid " tx rate: " msgstr " 上传速率: " -#: yass_window.cpp:534 +#: yass_window.cpp:547 msgid " rx rate: " msgstr " 下载速率: " -#: yass_window.cpp:645 +#: yass_window.cpp:658 msgid "YASS Option" msgstr "YASS 选项" -#: yass_window.cpp:656 +#: yass_window.cpp:669 msgid "Last Change: " msgstr "最后改动: " -#: yass_window.cpp:659 +#: yass_window.cpp:672 msgid "Enabled Feature: " msgstr "启用功能: " -#: yass_window.cpp:662 +#: yass_window.cpp:675 msgid "GUI Variant: " msgstr "图形版本: " -#: yass_window.cpp:671 +#: yass_window.cpp:684 msgid "official-site" msgstr "官方网站" diff --git a/src/gtk4/option_dialog.cpp b/src/gtk4/option_dialog.cpp index e065d37ef..5bccd31fb 100644 --- a/src/gtk4/option_dialog.cpp +++ b/src/gtk4/option_dialog.cpp @@ -9,6 +9,7 @@ #include "core/logging.hpp" #include "core/utils.hpp" #include "gtk/utils.hpp" +#include "net/network.hpp" extern "C" { @@ -20,6 +21,7 @@ struct _OptionGtkDialog { GtkWidget* tcp_keep_alive_idle_timeout; GtkWidget* tcp_keep_alive_interval; GtkWidget* enable_post_quantum_kyber; + GtkWidget* tcp_congestion_algorithm; GtkWidget* okay_button; GtkWidget* cancel_button; @@ -44,6 +46,7 @@ static void option_dialog_dispose(GObject* object) { gtk_widget_unparent(dialog->tcp_keep_alive_idle_timeout); gtk_widget_unparent(dialog->tcp_keep_alive_interval); gtk_widget_unparent(dialog->enable_post_quantum_kyber); + gtk_widget_unparent(dialog->tcp_congestion_algorithm); gtk_widget_unparent(dialog->okay_button); gtk_widget_unparent(dialog->cancel_button); @@ -60,6 +63,7 @@ static void option_dialog_class_init(OptionGtkDialogClass* cls) { gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(cls), OptionGtkDialog, tcp_keep_alive_idle_timeout); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(cls), OptionGtkDialog, tcp_keep_alive_interval); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(cls), OptionGtkDialog, enable_post_quantum_kyber); + gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(cls), OptionGtkDialog, tcp_congestion_algorithm); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(cls), OptionGtkDialog, okay_button); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(cls), OptionGtkDialog, cancel_button); @@ -88,6 +92,14 @@ OptionGtkDialog* option_dialog_new(const gchar* title, GtkWindow* parent, GtkDia OptionDialog::OptionDialog(const std::string& title, GtkWindow* parent, bool modal) : impl_(option_dialog_new(title.c_str(), parent, modal ? GTK_DIALOG_MODAL : GTK_DIALOG_DESTROY_WITH_PARENT)) { + algorithms_ = net::GetTCPAvailableCongestionAlgorithms(); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + GtkComboBoxText* tcp_congestion_algorithm = GTK_COMBO_BOX_TEXT(impl_->tcp_congestion_algorithm); + for (const auto& algorithm : algorithms_) { + gtk_combo_box_text_append_text(tcp_congestion_algorithm, algorithm.c_str()); + } + G_GNUC_END_IGNORE_DEPRECATIONS + auto okay_callback = [](GtkButton* self, gpointer pointer) { OptionDialog* window = (OptionDialog*)pointer; window->OnOkayButtonClicked(); @@ -142,6 +154,21 @@ void OptionDialog::LoadChanges() { gtk_check_button_set_active(GTK_CHECK_BUTTON(impl_->enable_post_quantum_kyber), absl::GetFlag(FLAGS_enable_post_quantum_kyber)); + + auto algorithm = absl::GetFlag(FLAGS_tcp_congestion_algorithm); + unsigned int i; + for (i = 0; i < std::size(algorithms_); ++i) { + if (algorithm == algorithms_[i]) + break; + } + + // first is unset + if (i == std::size(algorithms_)) { + i = 0; + } + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_combo_box_set_active(GTK_COMBO_BOX(impl_->tcp_congestion_algorithm), i); + G_GNUC_END_IGNORE_DEPRECATIONS } bool OptionDialog::OnSave() { @@ -165,5 +192,14 @@ bool OptionDialog::OnSave() { absl::SetFlag(&FLAGS_tcp_keep_alive_interval, tcp_keep_alive_interval.value()); absl::SetFlag(&FLAGS_enable_post_quantum_kyber, enable_post_quantum_kyber); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gchar* algorithm_cstr = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(impl_->tcp_congestion_algorithm)); + G_GNUC_END_IGNORE_DEPRECATIONS + if (algorithm_cstr == nullptr || std::string_view(algorithm_cstr).empty()) { + absl::SetFlag(&FLAGS_tcp_congestion_algorithm, std::string()); + } else { + absl::SetFlag(&FLAGS_tcp_congestion_algorithm, algorithm_cstr); + } return true; } diff --git a/src/gtk4/option_dialog.hpp b/src/gtk4/option_dialog.hpp index 38816d160..f37f02fcf 100644 --- a/src/gtk4/option_dialog.hpp +++ b/src/gtk4/option_dialog.hpp @@ -6,6 +6,7 @@ #include #include +#include extern "C" { #define OPTION_DIALOG_TYPE (option_dialog_get_type()) @@ -32,6 +33,7 @@ class OptionDialog { private: friend class YASSWindow; OptionGtkDialog* impl_; + std::vector algorithms_; }; // OptionDialog #endif // OPTION_DIALOG_H diff --git a/src/gtk4/option_dialog.ui b/src/gtk4/option_dialog.ui index 50651a7fb..d54ce57c7 100644 --- a/src/gtk4/option_dialog.ui +++ b/src/gtk4/option_dialog.ui @@ -63,6 +63,16 @@ + + + TCP Congestion Algorithm + 0.0 + + 0 + 5 + + + @@ -103,12 +113,20 @@ + + + + 1 + 5 + + + Okay 0 - 5 + 6 @@ -117,7 +135,7 @@ Cancel 1 - 5 + 6 diff --git a/src/gtk4/yass_en.po b/src/gtk4/yass_en.po index cb96f41cc..a4ede1612 100644 --- a/src/gtk4/yass_en.po +++ b/src/gtk4/yass_en.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-07-25 13:13+0800\n" +"POT-Creation-Date: 2024-08-26 14:25+0800\n" "PO-Revision-Date: 2023-05-24 14:35+0800\n" "Last-Translator: Chilledheart \n" "Language-Team: Chilledheart \n" @@ -17,63 +17,63 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: yass.cpp:302 +#: yass.cpp:297 msgid "Connected with conns: " msgstr "Connected with conns: " -#: yass.cpp:304 +#: yass.cpp:299 msgid "Connecting" msgstr "Connecting" -#: yass.cpp:306 +#: yass.cpp:301 msgid "Failed to connect due to " msgstr "Failed to connect due to " -#: yass.cpp:308 +#: yass.cpp:303 msgid "Disconnecting" msgstr "Disconnecting" -#: yass.cpp:310 +#: yass.cpp:305 msgid "Disconnected with " msgstr "Disconnected with " -#: yass.cpp:421 +#: yass_window.cpp:193 +msgid "READY" +msgstr "READY" + +#: yass_window.cpp:266 msgid "Last Change: " msgstr "Last Change: " -#: yass.cpp:424 +#: yass_window.cpp:269 msgid "Enabled Feature: " msgstr "Enabled Feature: " -#: yass.cpp:427 +#: yass_window.cpp:272 msgid "GUI Variant: " msgstr "GUI Variant: " -#: yass.cpp:436 +#: yass_window.cpp:281 msgid "official-site" msgstr "official-site" -#: yass.cpp:442 +#: yass_window.cpp:298 msgid "YASS Option" msgstr "YASS Option" -#: yass_window.cpp:192 -msgid "READY" -msgstr "READY" - -#: yass_window.cpp:319 +#: yass_window.cpp:397 msgid " tx rate: " msgstr " tx rate: " -#: yass_window.cpp:322 +#: yass_window.cpp:400 msgid " rx rate: " msgstr " rx rate: " -#: yass_window.cpp:357 +#: yass_window.cpp:435 msgid "Start Failed" msgstr "Start Failed" -#: yass_window.cpp:358 +#: yass_window.cpp:436 msgid "OK" msgstr "OK" @@ -113,11 +113,15 @@ msgstr "TCP keep alive interval" msgid "Kyber post-quantum key agreement for TLS" msgstr "Kyber post-quantum key agreement for TLS" -#: option_dialog.ui:108 +#: option_dialog.ui:68 +msgid "TCP Congestion Algorithm" +msgstr "TCP Congestion Algorithm" + +#: option_dialog.ui:126 msgid "Okay" msgstr "Okay" -#: option_dialog.ui:117 +#: option_dialog.ui:135 msgid "Cancel" msgstr "Cancel" @@ -185,6 +189,6 @@ msgstr "System Proxy" msgid "Start" msgstr "Start" -#: yass_window.ui:291 +#: yass_window.ui:292 msgid "Stop" msgstr "Stop" diff --git a/src/gtk4/yass_zh_CN.po b/src/gtk4/yass_zh_CN.po index 0b2f06f98..e40ea5697 100644 --- a/src/gtk4/yass_zh_CN.po +++ b/src/gtk4/yass_zh_CN.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-07-25 13:13+0800\n" +"POT-Creation-Date: 2024-08-26 14:25+0800\n" "PO-Revision-Date: 2023-09-15 11:28+0800\n" "Last-Translator: Chilledheart \n" "Language-Team: Chilledheart \n" @@ -18,63 +18,63 @@ msgstr "" "X-Generator: Poedit 2.2.4\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: yass.cpp:302 +#: yass.cpp:297 msgid "Connected with conns: " msgstr "已产生连接: " -#: yass.cpp:304 +#: yass.cpp:299 msgid "Connecting" msgstr "连接中" -#: yass.cpp:306 +#: yass.cpp:301 msgid "Failed to connect due to " msgstr "无法连接因为 " -#: yass.cpp:308 +#: yass.cpp:303 msgid "Disconnecting" msgstr "断开连接中" -#: yass.cpp:310 +#: yass.cpp:305 msgid "Disconnected with " msgstr "断开连接于服务器 " -#: yass.cpp:421 +#: yass_window.cpp:193 +msgid "READY" +msgstr "就绪" + +#: yass_window.cpp:266 msgid "Last Change: " msgstr "最后改动: " -#: yass.cpp:424 +#: yass_window.cpp:269 msgid "Enabled Feature: " msgstr "启用功能: " -#: yass.cpp:427 +#: yass_window.cpp:272 msgid "GUI Variant: " msgstr "图形版本: " -#: yass.cpp:436 +#: yass_window.cpp:281 msgid "official-site" msgstr "官方网站" -#: yass.cpp:442 +#: yass_window.cpp:298 msgid "YASS Option" msgstr "YASS 选项" -#: yass_window.cpp:192 -msgid "READY" -msgstr "就绪" - -#: yass_window.cpp:319 +#: yass_window.cpp:397 msgid " tx rate: " msgstr " 上传速率: " -#: yass_window.cpp:322 +#: yass_window.cpp:400 msgid " rx rate: " msgstr " 下载速率: " -#: yass_window.cpp:357 +#: yass_window.cpp:435 msgid "Start Failed" msgstr "启动失败" -#: yass_window.cpp:358 +#: yass_window.cpp:436 msgid "OK" msgstr "确认" @@ -114,11 +114,15 @@ msgstr "TCP 保活间隔" msgid "Kyber post-quantum key agreement for TLS" msgstr "TLS的Kyber后量子密钥协商" -#: option_dialog.ui:108 +#: option_dialog.ui:68 +msgid "TCP Congestion Algorithm" +msgstr "TCP 拥塞算法" + +#: option_dialog.ui:126 msgid "Okay" msgstr "确认" -#: option_dialog.ui:117 +#: option_dialog.ui:135 msgid "Cancel" msgstr "取消" @@ -186,6 +190,6 @@ msgstr "系统代理" msgid "Start" msgstr "启动" -#: yass_window.ui:291 +#: yass_window.ui:292 msgid "Stop" msgstr "停止" diff --git a/src/net/network.cpp b/src/net/network.cpp index 81da9b3ba..d4e05880c 100644 --- a/src/net/network.cpp +++ b/src/net/network.cpp @@ -15,6 +15,7 @@ #endif #include +#include #include #include #include "config/config_network.hpp" @@ -44,9 +45,9 @@ void SetSOReusePort(asio::ip::tcp::acceptor::native_handle_type handle, asio::er #ifdef __linux__ static void PrintTcpAllowedCongestionControls() { - constexpr std::string_view kAllowedCongestionControl = "/proc/sys/net/ipv4/tcp_allowed_congestion_control"; + const std::string procfs = "/proc/sys/net/ipv4/tcp_allowed_congestion_control"; uint8_t buf[256]; - auto ret = ReadFileToBuffer(std::string(kAllowedCongestionControl), make_span(buf)); + auto ret = ReadFileToBuffer(procfs, buf); if (ret < 0) { return; } @@ -54,11 +55,32 @@ static void PrintTcpAllowedCongestionControls() { } #endif +std::vector GetTCPAvailableCongestionAlgorithms() { + std::vector ret; + ret.push_back(std::string()); // unspec +#ifdef __linux__ + uint8_t buf[4096]; + const std::string procfs = "/proc/sys/net/ipv4/tcp_available_congestion_control"; + ssize_t bytes = ReadFileToBuffer(procfs, buf); + if (bytes > 0 && bytes < (ssize_t)sizeof(buf)) { + std::string_view sbuf = std::string_view((const char*)buf, bytes); + LOG(INFO) << "Available TCP Congestion Algorithms: " << sbuf; + auto algorithms = absl::StrSplit(sbuf, absl::ByAnyChar(" \n\t\r")); + for (const auto& algorithm : algorithms) { + if (!algorithm.empty()) { + ret.push_back(std::string(algorithm)); + } + } + } +#endif + return ret; +} + void SetTCPCongestion(asio::ip::tcp::acceptor::native_handle_type handle, asio::error_code& ec) { (void)handle; ec = asio::error_code(); #ifdef __linux__ - const std::string new_algo = absl::GetFlag(FLAGS_congestion_algorithm); + const std::string new_algo = absl::GetFlag(FLAGS_tcp_congestion_algorithm); if (new_algo.empty()) { return; } @@ -70,7 +92,7 @@ void SetTCPCongestion(asio::ip::tcp::acceptor::native_handle_type handle, asio:: if (ret < 0 && (errno == EPROTONOSUPPORT || errno == ENOPROTOOPT)) { PLOG(WARNING) << "TCP_CONGESTION is not supported on this platform"; LOG(WARNING) << "Ignore congestion algorithm settings"; - absl::SetFlag(&FLAGS_congestion_algorithm, std::string()); + absl::SetFlag(&FLAGS_tcp_congestion_algorithm, std::string()); return; } if (ret < 0) { @@ -88,7 +110,7 @@ void SetTCPCongestion(asio::ip::tcp::acceptor::native_handle_type handle, asio:: PrintTcpAllowedCongestionControls(); LOG(WARNING) << "Please load the algorithm kernel module before use!"; LOG(WARNING) << "Ignore congestion algorithm settings"; - absl::SetFlag(&FLAGS_congestion_algorithm, std::string()); + absl::SetFlag(&FLAGS_tcp_congestion_algorithm, std::string()); return; } VLOG(2) << "Previous congestion algorithm: " << old_algo; diff --git a/src/net/network.hpp b/src/net/network.hpp index 39eac13af..f79d0c383 100644 --- a/src/net/network.hpp +++ b/src/net/network.hpp @@ -8,12 +8,17 @@ #include #endif +#include +#include + #include "net/asio.hpp" namespace net { void SetSOReusePort(asio::ip::tcp::acceptor::native_handle_type handle, asio::error_code&); +std::vector GetTCPAvailableCongestionAlgorithms(); + void SetTCPCongestion(asio::ip::tcp::acceptor::native_handle_type handle, asio::error_code&); void SetTCPFastOpen(asio::ip::tcp::acceptor::native_handle_type handle, asio::error_code&); diff --git a/src/qt6/lang/yass_en.ts b/src/qt6/lang/yass_en.ts index a330dda6d..a9c0520a4 100644 --- a/src/qt6/lang/yass_en.ts +++ b/src/qt6/lang/yass_en.ts @@ -35,6 +35,10 @@ Cancel + + TCP Congestion Algorithm + + TrayIcon diff --git a/src/qt6/lang/yass_zh_CN.qm b/src/qt6/lang/yass_zh_CN.qm index 1183cef56..51a3b21a4 100644 Binary files a/src/qt6/lang/yass_zh_CN.qm and b/src/qt6/lang/yass_zh_CN.qm differ diff --git a/src/qt6/lang/yass_zh_CN.ts b/src/qt6/lang/yass_zh_CN.ts index a7236bd85..047439d15 100644 --- a/src/qt6/lang/yass_zh_CN.ts +++ b/src/qt6/lang/yass_zh_CN.ts @@ -35,6 +35,10 @@ Cancel 取消 + + TCP Congestion Algorithm + TCP 拥塞算法 + TrayIcon diff --git a/src/qt6/option_dialog.cpp b/src/qt6/option_dialog.cpp index d8a92984b..3f8ab643d 100644 --- a/src/qt6/option_dialog.cpp +++ b/src/qt6/option_dialog.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include "config/config.hpp" #include "core/logging.hpp" #include "core/utils.hpp" +#include "net/network.hpp" OptionDialog::OptionDialog(QWidget* parent) : QDialog(parent) { setWindowTitle(tr("YASS Option")); @@ -29,12 +31,14 @@ OptionDialog::OptionDialog(QWidget* parent) : QDialog(parent) { auto tcp_keep_alive_interval_label = new QLabel(tr("TCP keep alive interval")); auto enable_post_quantum_kyber_label = new QLabel(tr("Kyber post-quantum key agreement for TLS")); + auto tcp_congestion_algorithm_label = new QLabel(tr("TCP Congestion Algorithm")); grid->addWidget(tcp_keep_alive_label, 0, 0); grid->addWidget(tcp_keep_alive_cnt_label, 1, 0); grid->addWidget(tcp_keep_alive_idle_timeout_label, 2, 0); grid->addWidget(tcp_keep_alive_interval_label, 3, 0); grid->addWidget(enable_post_quantum_kyber_label, 4, 0); + grid->addWidget(tcp_congestion_algorithm_label, 5, 0); tcp_keep_alive_ = new QCheckBox; tcp_keep_alive_cnt_ = new QLineEdit; @@ -44,12 +48,20 @@ OptionDialog::OptionDialog(QWidget* parent) : QDialog(parent) { tcp_keep_alive_interval_ = new QLineEdit; tcp_keep_alive_interval_->setValidator(new QIntValidator(0, INT32_MAX, this)); enable_post_quantum_kyber_ = new QCheckBox; + tcp_congestion_algorithm_ = new QComboBox; + + algorithms_ = net::GetTCPAvailableCongestionAlgorithms(); + + for (const auto& algorithm : algorithms_) { + tcp_congestion_algorithm_->addItem(algorithm.c_str()); + } grid->addWidget(tcp_keep_alive_, 0, 1); grid->addWidget(tcp_keep_alive_cnt_, 1, 1); grid->addWidget(tcp_keep_alive_idle_timeout_, 2, 1); grid->addWidget(tcp_keep_alive_interval_, 3, 1); grid->addWidget(enable_post_quantum_kyber_, 4, 1); + grid->addWidget(tcp_congestion_algorithm_, 5, 1); okay_button_ = new QPushButton(tr("Okay")); connect(okay_button_, &QPushButton::clicked, this, &OptionDialog::OnOkayButtonClicked); @@ -57,8 +69,8 @@ OptionDialog::OptionDialog(QWidget* parent) : QDialog(parent) { cancel_button_ = new QPushButton(tr("Cancel")); connect(cancel_button_, &QPushButton::clicked, this, &OptionDialog::OnCancelButtonClicked); - grid->addWidget(okay_button_, 5, 0); - grid->addWidget(cancel_button_, 5, 1); + grid->addWidget(okay_button_, 6, 0); + grid->addWidget(cancel_button_, 6, 1); setLayout(grid); @@ -89,6 +101,20 @@ void OptionDialog::LoadChanges() { QString::fromUtf8(tcp_keep_alive_interval_str.c_str(), tcp_keep_alive_interval_str.size())); enable_post_quantum_kyber_->setChecked(absl::GetFlag(FLAGS_enable_post_quantum_kyber)); + + auto algorithm = absl::GetFlag(FLAGS_tcp_congestion_algorithm); + unsigned int i; + for (i = 0; i < std::size(algorithms_); ++i) { + if (algorithm == algorithms_[i]) + break; + } + + // first is unset + if (i == std::size(algorithms_)) { + i = 0; + } + + tcp_congestion_algorithm_->setCurrentIndex(i); } bool OptionDialog::OnSave() { @@ -112,5 +138,10 @@ bool OptionDialog::OnSave() { absl::SetFlag(&FLAGS_enable_post_quantum_kyber, enable_post_quantum_kyber); + int i = tcp_congestion_algorithm_->currentIndex(); + DCHECK_GE(i, 0); + DCHECK_LE(i, (int)algorithms_.size()); + absl::SetFlag(&FLAGS_tcp_congestion_algorithm, algorithms_[i]); + return true; } diff --git a/src/qt6/option_dialog.hpp b/src/qt6/option_dialog.hpp index 3e222301a..16b9f5874 100644 --- a/src/qt6/option_dialog.hpp +++ b/src/qt6/option_dialog.hpp @@ -5,7 +5,11 @@ #include +#include +#include + class QCheckBox; +class QComboBox; class QLineEdit; class QPushButton; class OptionDialog : public QDialog { @@ -27,6 +31,8 @@ class OptionDialog : public QDialog { QLineEdit* tcp_keep_alive_idle_timeout_; QLineEdit* tcp_keep_alive_interval_; QCheckBox* enable_post_quantum_kyber_; + QComboBox* tcp_congestion_algorithm_; + std::vector algorithms_; QPushButton* okay_button_; QPushButton* cancel_button_;