diff --git a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
index 3f07548f..722d97f5 100644
--- a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
+++ b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
@@ -119,6 +119,10 @@ public class BaseFmt
{
dicQuery.Add("seed", UrlEncodeSafe(transport.KcpSeed));
}
+ if (transport.KcpMtu > 0)
+ {
+ dicQuery.Add("mtu", transport.KcpMtu.ToString());
+ }
break;
case nameof(ETransport.ws):
@@ -279,10 +283,13 @@ public class BaseFmt
case nameof(ETransport.kcp):
var kcpSeed = GetQueryDecoded(query, "seed");
+ var kcpMtuStr = GetQueryValue(query, "mtu");
+ var kcpMtu = int.TryParse(kcpMtuStr, out var mtu) ? mtu : 0;
transport = transport with
{
KcpHeaderType = GetQueryValue(query, "headerType", Global.None),
KcpSeed = kcpSeed,
+ KcpMtu = kcpMtu > 0 ? mtu : null,
};
break;
diff --git a/v2rayN/ServiceLib/Models/TransportExtraItem.cs b/v2rayN/ServiceLib/Models/TransportExtraItem.cs
index 7ffcc9f5..77fbc984 100644
--- a/v2rayN/ServiceLib/Models/TransportExtraItem.cs
+++ b/v2rayN/ServiceLib/Models/TransportExtraItem.cs
@@ -15,4 +15,5 @@ public record TransportExtraItem
public string? KcpHeaderType { get; init; }
public string? KcpSeed { get; init; }
+ public int? KcpMtu { get; init; }
}
diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs
index b058dfa1..ef22d545 100644
--- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs
+++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs
@@ -328,6 +328,7 @@ public partial class CoreConfigV2rayService
var host = string.Empty;
var path = string.Empty;
var kcpSeed = string.Empty;
+ var kcpMtu = 0;
var headerType = string.Empty;
var xhttpExtra = string.Empty;
switch (network)
@@ -341,6 +342,7 @@ public partial class CoreConfigV2rayService
case nameof(ETransport.kcp):
kcpSeed = transport.KcpSeed?.TrimEx() ?? string.Empty;
headerType = transport.KcpHeaderType?.TrimEx() ?? string.Empty;
+ kcpMtu = transport.KcpMtu > 0 ? transport.KcpMtu!.Value : _config.KcpItem.Mtu;
break;
case nameof(ETransport.ws):
@@ -441,7 +443,7 @@ public partial class CoreConfigV2rayService
case nameof(ETransport.kcp):
KcpSettings4Ray kcpSettings = new()
{
- mtu = _config.KcpItem.Mtu,
+ mtu = kcpMtu,
tti = _config.KcpItem.Tti
};
diff --git a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs
index 3dbea94c..20439a03 100644
--- a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs
@@ -106,6 +106,9 @@ public class AddServerViewModel : MyReactiveObject
[Reactive]
public string KcpSeed { get; set; }
+ [Reactive]
+ public int? KcpMtu { get; set; }
+
public string TransportHeaderType
{
get => SelectedSource.GetNetwork() switch
@@ -287,26 +290,26 @@ public class AddServerViewModel : MyReactiveObject
Cert = SelectedSource?.Cert?.ToString() ?? string.Empty;
CertSha = SelectedSource?.CertSha?.ToString() ?? string.Empty;
- var protocolExtra = SelectedSource?.GetProtocolExtra();
- var transport = SelectedSource?.GetTransportExtra();
- Ports = protocolExtra?.Ports ?? string.Empty;
- AlterId = int.TryParse(protocolExtra?.AlterId, out var result) ? result : 0;
- Flow = protocolExtra?.Flow ?? string.Empty;
- SalamanderPass = protocolExtra?.SalamanderPass ?? string.Empty;
- UpMbps = protocolExtra?.UpMbps;
- DownMbps = protocolExtra?.DownMbps;
- HopInterval = protocolExtra?.HopInterval ?? string.Empty;
- VmessSecurity = protocolExtra?.VmessSecurity?.IsNullOrEmpty() == false ? protocolExtra.VmessSecurity : Global.DefaultSecurity;
- VlessEncryption = protocolExtra?.VlessEncryption.IsNullOrEmpty() == false ? protocolExtra.VlessEncryption : Global.None;
- SsMethod = protocolExtra?.SsMethod ?? string.Empty;
- WgPublicKey = protocolExtra?.WgPublicKey ?? string.Empty;
- WgInterfaceAddress = protocolExtra?.WgInterfaceAddress ?? string.Empty;
- WgReserved = protocolExtra?.WgReserved ?? string.Empty;
- WgMtu = protocolExtra?.WgMtu ?? 1280;
- Uot = protocolExtra?.Uot ?? false;
- CongestionControl = protocolExtra?.CongestionControl ?? string.Empty;
- InsecureConcurrency = protocolExtra?.InsecureConcurrency > 0 ? protocolExtra.InsecureConcurrency : null;
- NaiveQuic = protocolExtra?.NaiveQuic ?? false;
+ var protocolExtra = SelectedSource?.GetProtocolExtra() ?? new();
+ var transport = SelectedSource?.GetTransportExtra() ?? new();
+ Ports = protocolExtra.Ports ?? string.Empty;
+ AlterId = int.TryParse(protocolExtra.AlterId, out var result) ? result : 0;
+ Flow = protocolExtra.Flow ?? string.Empty;
+ SalamanderPass = protocolExtra.SalamanderPass ?? string.Empty;
+ UpMbps = protocolExtra.UpMbps;
+ DownMbps = protocolExtra.DownMbps;
+ HopInterval = protocolExtra.HopInterval ?? string.Empty;
+ VmessSecurity = protocolExtra.VmessSecurity?.IsNullOrEmpty() == false ? protocolExtra.VmessSecurity : Global.DefaultSecurity;
+ VlessEncryption = protocolExtra.VlessEncryption?.IsNullOrEmpty() == false ? protocolExtra.VlessEncryption : Global.None;
+ SsMethod = protocolExtra.SsMethod ?? string.Empty;
+ WgPublicKey = protocolExtra.WgPublicKey ?? string.Empty;
+ WgInterfaceAddress = protocolExtra.WgInterfaceAddress ?? string.Empty;
+ WgReserved = protocolExtra.WgReserved ?? string.Empty;
+ WgMtu = protocolExtra.WgMtu ?? 1280;
+ Uot = protocolExtra.Uot ?? false;
+ CongestionControl = protocolExtra.CongestionControl ?? string.Empty;
+ InsecureConcurrency = protocolExtra.InsecureConcurrency > 0 ? protocolExtra.InsecureConcurrency : null;
+ NaiveQuic = protocolExtra.NaiveQuic ?? false;
RawHeaderType = transport.RawHeaderType ?? Global.None;
Host = transport.Host ?? string.Empty;
@@ -318,6 +321,7 @@ public class AddServerViewModel : MyReactiveObject
GrpcMode = transport.GrpcMode.IsNullOrEmpty() ? Global.GrpcGunMode : transport.GrpcMode;
KcpHeaderType = transport.KcpHeaderType.IsNullOrEmpty() ? Global.None : transport.KcpHeaderType;
KcpSeed = transport.KcpSeed ?? string.Empty;
+ KcpMtu = transport.KcpMtu;
}
private async Task SaveServerAsync()
@@ -381,6 +385,7 @@ public class AddServerViewModel : MyReactiveObject
GrpcMode = GrpcMode.NullIfEmpty(),
KcpHeaderType = KcpHeaderType.NullIfEmpty(),
KcpSeed = KcpSeed.NullIfEmpty(),
+ KcpMtu = KcpMtu > 0 ? KcpMtu : null,
};
SelectedSource.SetProtocolExtra(SelectedSource.GetProtocolExtra() with
diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml
index f29afb7f..00bcff1b 100644
--- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml
+++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml
@@ -831,7 +831,7 @@
x:Name="gridTransportKcp"
ColumnDefinitions="300,Auto"
IsVisible="False"
- RowDefinitions="Auto,Auto">
+ RowDefinitions="Auto,Auto,Auto">
+ Margin="{StaticResource Margin4}"
+ HorizontalAlignment="Left" />
+
+
+ Margin="{StaticResource Margin4}"
+ HorizontalAlignment="Left" />
this.Bind(ViewModel, vm => vm.KcpHeaderType, v => v.cmbHeaderTypeKcp.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KcpSeed, v => v.txtKcpSeed.Text).DisposeWith(disposables);
+ this.Bind(ViewModel, vm => vm.KcpMtu, v => v.txtKcpMtu.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Host, v => v.txtRequestHostWs.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Path, v => v.txtPathWs.Text).DisposeWith(disposables);
diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml b/v2rayN/v2rayN/Views/AddServerWindow.xaml
index e2dec9bc..4efb6b94 100644
--- a/v2rayN/v2rayN/Views/AddServerWindow.xaml
+++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml
@@ -1096,6 +1096,7 @@
+
+
+
diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs
index 5a8b3bf4..aeb6ceaa 100644
--- a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs
@@ -216,6 +216,7 @@ public partial class AddServerWindow
this.Bind(ViewModel, vm => vm.KcpHeaderType, v => v.cmbHeaderTypeKcp.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KcpSeed, v => v.txtKcpSeed.Text).DisposeWith(disposables);
+ this.Bind(ViewModel, vm => vm.KcpMtu, v => v.txtKcpMtu.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Host, v => v.txtRequestHostWs.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Path, v => v.txtPathWs.Text).DisposeWith(disposables);