diff --git a/Furious/Core/CoreManager.py b/Furious/Core/CoreManager.py index c1530be..10a09a2 100644 --- a/Furious/Core/CoreManager.py +++ b/Furious/Core/CoreManager.py @@ -95,6 +95,9 @@ def getUserTUNSettings(*args, **kwargs): userTunAdapterInterfaceDNS, userBypassTUNAdapterInterfaceIP, userDisablePrimaryAdapterInterfaceDNS, + userTcpSendBufferSize, + userTcpReceiveBufferSize, + userTcpAutoTuning, ) = ( functools.partial(getUserTUNSettings, 'primaryAdapterInterfaceName', ''), functools.partial(getUserTUNSettings, 'primaryAdapterInterfaceIP', ''), @@ -102,6 +105,9 @@ def getUserTUNSettings(*args, **kwargs): functools.partial(getUserTUNSettings, 'tunAdapterInterfaceDNS', ''), functools.partial(getUserTUNSettings, 'bypassTUNAdapterInterfaceIP', ''), functools.partial(getUserTUNSettings, 'disablePrimaryAdapterInterfaceDNS', 'True'), + functools.partial(getUserTUNSettings, 'tcpSendBufferSize', ''), + functools.partial(getUserTUNSettings, 'tcpReceiveBufferSize', ''), + functools.partial(getUserTUNSettings, 'tcpAutoTuning', 'False'), ) @@ -161,7 +167,7 @@ class CoreManager(Mixins.CleanupOnExit): # Show the MessageBox asynchronously mbox.open() - return False + return None, False routingObject = { 'domainStrategy': 'IPIfNonMatch', @@ -238,7 +244,7 @@ class CoreManager(Mixins.CleanupOnExit): # Show the MessageBox asynchronously mbox.open() - return False + return None, False routingObject = { 'rule': DATA_DIR / 'hysteria' / 'bypass-mainland-China.acl', @@ -385,12 +391,42 @@ class CoreManager(Mixins.CleanupOnExit): tun = Tun2socks(exitCallback=exitCallback, msgCallback=msgCallbackTUN_) self.processesPool.append(tun) + tcpSendBufferSize, tcpReceiveBufferSize, tcpAutoTuning = ( + userTcpSendBufferSize(), + userTcpReceiveBufferSize(), + userTcpAutoTuning(), + ) + + if tcpSendBufferSize != '': + logger.info( + f'got user defined TUN settings. TcpSendBufferSize: {tcpSendBufferSize}' + ) + + if tcpReceiveBufferSize != '': + logger.info( + f'got user defined TUN settings. TCPReceiveBufferSize: {tcpReceiveBufferSize}' + ) + + if tcpAutoTuning == 'False': + tcpAutoTuning = False + elif tcpAutoTuning == 'True': + tcpAutoTuning = True + + logger.info( + f'got user defined TUN settings. TcpAutoTuning: {tcpAutoTuning}' + ) + else: + tcpAutoTuning = False + if not tun.start( APPLICATION_TUN_DEVICE_NAME, APPLICATION_TUN_NETWORK_INTERFACE_NAME, 'error', f'socks5://{configcopy.socksProxy()}', '', + tcpSendBufferSize, + tcpReceiveBufferSize, + tcpAutoTuning, ): return False diff --git a/Furious/Core/Tun2socks.py b/Furious/Core/Tun2socks.py index e8713b1..0415082 100644 --- a/Furious/Core/Tun2socks.py +++ b/Furious/Core/Tun2socks.py @@ -82,6 +82,9 @@ class Tun2socks(CoreProcessWorker): logLevel: str, proxy: str, restAPI: str, + tcpSendBufferSize: str = '', + tcpReceiveBufferSize: str = '', + tcpAutoTuning: bool = False, **kwargs, ) -> bool: return super().start( @@ -93,6 +96,9 @@ class Tun2socks(CoreProcessWorker): logLevel, proxy, restAPI, + tcpSendBufferSize, + tcpReceiveBufferSize, + tcpAutoTuning, ), **kwargs, ) diff --git a/Furious/Externals/GenTranslation.py b/Furious/Externals/GenTranslation.py index 0cf0537..e63160c 100644 --- a/Furious/Externals/GenTranslation.py +++ b/Furious/Externals/GenTranslation.py @@ -1654,7 +1654,7 @@ TRANSLATION = { "ZH": "TUN适配器接口DNS", "isReviewed": "True" }, - "Bypass TUN adapter interface IP (separated by commas)": { + "Bypass TUN Adapter Interface IP (separated by commas)": { "source": [ "Furious.Widget.GuiTUNSettings" ], @@ -1669,5 +1669,37 @@ TRANSLATION = { "RU": "Отключить DNS основного сетевого адаптера (для предотвращения утечек DNS в Windows)", "ZH": "禁用主适配器接口DNS(在Windows上缓解DNS泄露)", "isReviewed": "True" + }, + "Memory Optimization": { + "source": [ + "Furious.Widget.GuiTUNSettings" + ], + "ZH": "内存优化", + "RU": "Оптимизация памяти", + "isReviewed": "True" + }, + "TCP Send Buffer Size": { + "source": [ + "Furious.Widget.GuiTUNSettings" + ], + "ZH": "TCP发送缓冲区大小", + "RU": "Размер буфера отправки TCP", + "isReviewed": "True" + }, + "TCP Receive Buffer Size": { + "source": [ + "Furious.Widget.GuiTUNSettings" + ], + "ZH": "TCP接收缓冲区大小", + "RU": "Размер буфера приема TCP", + "isReviewed": "True" + }, + "TCP Receive Buffer Auto-tuning": { + "source": [ + "Furious.Widget.GuiTUNSettings" + ], + "ZH": "TCP接收缓冲区自动调优", + "RU": "Автоматическая настройка буфера приема TCP", + "isReviewed": "True" } } diff --git a/Furious/Widget/GuiTUNSettings.py b/Furious/Widget/GuiTUNSettings.py index 38a9fd3..fa1ff4c 100644 --- a/Furious/Widget/GuiTUNSettings.py +++ b/Furious/Widget/GuiTUNSettings.py @@ -57,19 +57,20 @@ class GuiTUNSettingsItemXXX(GuiEditorItemTextInput): self.setText(config.get(self.key, '')) -class GuiTUNSettingsItemDisablePrimaryAdapterInterfaceDNS(GuiEditorItemTextCheckBox): +class GuiTUNSettingsItemCheckBoxXXX(GuiEditorItemTextCheckBox): def __init__(self, *args, **kwargs): self.key = kwargs.pop('key', '') + self.default = kwargs.pop('default', 'False') super().__init__(*args, **kwargs) def inputToFactory(self, config: dict) -> bool: - oldItem = config.get(self.key, 'True') + oldItem = config.get(self.key, self.default) newItem = self.isChecked() if oldItem not in ['False', 'True']: # Invalid value. Set to default - oldItem = 'True' + oldItem = self.default if str(newItem) != oldItem: config[self.key] = str(newItem) @@ -81,7 +82,7 @@ class GuiTUNSettingsItemDisablePrimaryAdapterInterfaceDNS(GuiEditorItemTextCheck return False def factoryToInput(self, config: dict): - self.setChecked(config.get(self.key, 'True') != 'False') + self.setChecked(config.get(self.key, self.default) == 'True') class AppQLabelHelpPage(AppQLabel): @@ -121,7 +122,7 @@ class GuiTUNSettingsItemHelpPage(GuiEditorItemWidgetContainer): return [self._page] -class GuiTUNSettingsGroupBox(GuiEditorWidgetQGroupBox): +class GuiTUNSettingsGroupBoxBasic(GuiEditorWidgetQGroupBox): def __init__(self, **kwargs): super().__init__(_('Basic Configuration'), **kwargs) @@ -144,27 +145,51 @@ class GuiTUNSettingsGroupBox(GuiEditorWidgetQGroupBox): key='tunAdapterInterfaceDNS', ), GuiTUNSettingsItemXXX( - title=_('Bypass TUN adapter interface IP (separated by commas)'), + title=_('Bypass TUN Adapter Interface IP (separated by commas)'), key='bypassTUNAdapterInterfaceIP', ), - GuiTUNSettingsItemDisablePrimaryAdapterInterfaceDNS( + GuiTUNSettingsItemCheckBoxXXX( title=_( 'Disable Primary Adapter Interface DNS (Mitigating DNS leaks on Windows)' ), key='disablePrimaryAdapterInterfaceDNS', + default='True', ), GuiTUNSettingsItemHelpPage(), ] +class GuiTUNSettingsGroupBoxMemory(GuiEditorWidgetQGroupBox): + def __init__(self, **kwargs): + super().__init__(_('Memory Optimization'), **kwargs) + + def containerSequence(self): + return [ + GuiTUNSettingsItemXXX( + title=_('TCP Send Buffer Size'), + key='tcpSendBufferSize', + ), + GuiTUNSettingsItemXXX( + title=_('TCP Receive Buffer Size'), + key='tcpReceiveBufferSize', + ), + GuiTUNSettingsItemCheckBoxXXX( + title=_('TCP Receive Buffer Auto-tuning'), + key='tcpAutoTuning', + default='False', + ), + ] + + class GuiTUNSettings(GuiEditorWidgetQDialog): def __init__(self, *args, **kwargs): tabTranslatable = kwargs.pop('tabTranslatable', True) + style = kwargs.pop('style', 'portrait') - super().__init__(*args, tabTranslatable=tabTranslatable, **kwargs) + super().__init__(*args, tabTranslatable=tabTranslatable, style=style, **kwargs) self.setTabText(_('Customize TUN Settings')) - self.setFixedSize(int(460 * GOLDEN_RATIO), int(460)) + self.setFixedSize(int(480 * GOLDEN_RATIO), int(480)) # Shallow copy config = Storage.UserTUNSettings() @@ -195,16 +220,18 @@ class GuiTUNSettings(GuiEditorWidgetQDialog): def inputToFactory(self, config: dict) -> bool: modified = False - for groupBox in self.groupBoxes: + for groupBox in self.groupBoxSequence(): modified |= groupBox.inputToFactory(config) return modified def factoryToInput(self, config: dict): - for groupBox in self.groupBoxes: + for groupBox in self.groupBoxSequence(): groupBox.factoryToInput(config) + @functools.lru_cache(None) def groupBoxSequence(self): return [ - GuiTUNSettingsGroupBox(), + GuiTUNSettingsGroupBoxBasic(), + GuiTUNSettingsGroupBoxMemory(), ]