Skip to content

Commit e9573b9

Browse files
committed
Support new fragment
1 parent 66cd746 commit e9573b9

File tree

2 files changed

+70
-46
lines changed

2 files changed

+70
-46
lines changed

V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ data class V2rayConfig(
6868
) {
6969
data class OutSettingsBean(
7070
var vnext: List<VnextBean>? = null,
71-
var fragment: FragmentBean? = null,
72-
var noises: List<NoiseBean>? = null,
7371
var servers: List<ServersBean>? = null,
7472
/*Blackhole*/
7573
var response: Response? = null,
@@ -108,18 +106,6 @@ data class V2rayConfig(
108106
)
109107
}
110108

111-
data class FragmentBean(
112-
var packets: String? = null,
113-
var length: String? = null,
114-
var interval: String? = null
115-
)
116-
117-
data class NoiseBean(
118-
var type: String? = null,
119-
var packet: String? = null,
120-
var delay: String? = null
121-
)
122-
123109
data class ServersBean(
124110
var address: String = "",
125111
var method: String? = null,
@@ -314,9 +300,25 @@ data class V2rayConfig(
314300
var settings: MaskSettingsBean? = null
315301
) {
316302
data class MaskSettingsBean(
317-
var password: String? = null,
318-
var domain: String? = null
319-
)
303+
val password: String? = null,
304+
val domain: String? = null,
305+
// fragment
306+
val packets: String? = null,
307+
val length: String? = null,
308+
val delay: String? = null,
309+
// val maxSplit: String? = null,
310+
// noise
311+
val reset: Int? = null,
312+
val noise: List<NoiseMaskBean>? = null
313+
) {
314+
data class NoiseMaskBean(
315+
val rand: String? = null,
316+
// val randRange: String? = null,
317+
// val type: String? = null,
318+
// val packet: String? = null,
319+
val delay: String? = null,
320+
)
321+
}
320322
}
321323
data class QuicParamsBean(
322324
var congestion: String? = null,

V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2rayConfigManager.kt

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ object V2rayConfigManager {
219219
resolveOutboundDomainsToHosts(v2rayConfig)
220220
}
221221

222+
// apply fragment
223+
for (outbound in v2rayConfig.outbounds) {
224+
updateOutboundFragment(outbound)
225+
}
226+
222227
result.status = true
223228
result.content = JsonUtil.toJsonPretty(v2rayConfig) ?: ""
224229
result.guid = guid
@@ -278,6 +283,11 @@ object V2rayConfigManager {
278283
resolveOutboundDomainsToHosts(v2rayConfig)
279284
}
280285

286+
// apply fragment
287+
for (outbound in v2rayConfig.outbounds) {
288+
updateOutboundFragment(outbound)
289+
}
290+
281291
return v2rayConfig
282292
}
283293

@@ -710,8 +720,6 @@ object V2rayConfigManager {
710720
} else {
711721
v2rayConfig.outbounds.add(outbound)
712722
}
713-
714-
updateOutboundFragment(v2rayConfig)
715723
return true
716724
}
717725

@@ -955,19 +963,22 @@ object V2rayConfigManager {
955963
*
956964
* Configures packet fragmentation for TLS and REALITY protocols if enabled.
957965
*
958-
* @param v2rayConfig The V2ray configuration object to be modified
966+
* @param outbound The outbound object to be modified
959967
* @return true if fragment configuration was successful, false otherwise
960968
*/
961-
private fun updateOutboundFragment(v2rayConfig: V2rayConfig): Boolean {
969+
private fun updateOutboundFragment(outbound: OutboundBean): Boolean {
962970
try {
963971
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_FRAGMENT_ENABLED, false) == false) {
964972
return true
965973
}
966-
if (v2rayConfig.outbounds[0].streamSettings?.security != AppConfig.TLS
967-
&& v2rayConfig.outbounds[0].streamSettings?.security != AppConfig.REALITY
974+
if (outbound.streamSettings?.security != AppConfig.TLS
975+
&& outbound.streamSettings?.security != AppConfig.REALITY
968976
) {
969977
return true
970978
}
979+
if (outbound.streamSettings?.sockopt?.dialerProxy.isNotNullEmpty()) {
980+
return true
981+
}
971982

972983
val fragmentOutbound =
973984
OutboundBean(
@@ -978,45 +989,56 @@ object V2rayConfigManager {
978989

979990
var packets =
980991
MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_PACKETS) ?: "tlshello"
981-
if (v2rayConfig.outbounds[0].streamSettings?.security == AppConfig.REALITY
992+
if (outbound.streamSettings?.security == AppConfig.REALITY
982993
&& packets == "tlshello"
983994
) {
984995
packets = "1-3"
985-
} else if (v2rayConfig.outbounds[0].streamSettings?.security == AppConfig.TLS
996+
} else if (outbound.streamSettings?.security == AppConfig.TLS
986997
&& packets != "tlshello"
987998
) {
988999
packets = "tlshello"
9891000
}
9901001

991-
fragmentOutbound.settings = OutSettingsBean(
992-
fragment = OutSettingsBean.FragmentBean(
1002+
val fragmentMask = StreamSettingsBean.FinalMaskBean.MaskBean(
1003+
type = "fragment",
1004+
settings = StreamSettingsBean.FinalMaskBean.MaskBean.MaskSettingsBean(
9931005
packets = packets,
9941006
length = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_LENGTH)
9951007
?: "50-100",
996-
interval = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_INTERVAL)
1008+
delay = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_INTERVAL)
9971009
?: "10-20"
998-
),
999-
noises = listOf(
1000-
OutSettingsBean.NoiseBean(
1001-
type = "rand",
1002-
packet = "10-20",
1003-
delay = "10-16",
1004-
)
1005-
),
1010+
)
10061011
)
1007-
fragmentOutbound.streamSettings = StreamSettingsBean(
1008-
sockopt = StreamSettingsBean.SockoptBean(
1009-
TcpNoDelay = true,
1010-
mark = 255
1012+
val noiseMask = StreamSettingsBean.FinalMaskBean.MaskBean(
1013+
type = "noise",
1014+
settings = StreamSettingsBean.FinalMaskBean.MaskBean.MaskSettingsBean(
1015+
noise = listOf(
1016+
StreamSettingsBean.FinalMaskBean.MaskBean.MaskSettingsBean.NoiseMaskBean(
1017+
rand = "10-20",
1018+
delay = "10-16",
1019+
)
1020+
)
10111021
)
10121022
)
1013-
v2rayConfig.outbounds.add(fragmentOutbound)
10141023

1015-
//proxy chain
1016-
v2rayConfig.outbounds[0].streamSettings?.sockopt =
1017-
StreamSettingsBean.SockoptBean(
1018-
dialerProxy = AppConfig.TAG_FRAGMENT
1019-
)
1024+
val finalMaskObj = JsonUtil.parseString(JsonUtil.toJson(outbound.streamSettings?.finalmask))
1025+
?: com.google.gson.JsonObject()
1026+
1027+
// finalmask.tcp / finalmask.udp are arrays; prepend mask at index 0.
1028+
fun prependMask(scope: String, mask: StreamSettingsBean.FinalMaskBean.MaskBean) {
1029+
val newArray = JsonArray()
1030+
newArray.add(JsonUtil.parseString(JsonUtil.toJson(mask)))
1031+
1032+
val current = finalMaskObj.get(scope)
1033+
if (current != null && current.isJsonArray) {
1034+
current.asJsonArray.forEach { newArray.add(it) }
1035+
}
1036+
finalMaskObj.add(scope, newArray)
1037+
}
1038+
1039+
prependMask("tcp", fragmentMask)
1040+
prependMask("udp", noiseMask)
1041+
outbound.streamSettings?.finalmask = finalMaskObj
10201042
} catch (e: Exception) {
10211043
Log.e(AppConfig.TAG, "Failed to update outbound fragment", e)
10221044
return false

0 commit comments

Comments
 (0)