@@ -16,29 +16,17 @@ import com.neko.v2ray.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4
16
16
import com.neko.v2ray.AppConfig.WIREGUARD_LOCAL_ADDRESS_V6
17
17
import com.neko.v2ray.dto.EConfigType
18
18
import com.neko.v2ray.dto.ERoutingMode
19
+ import com.neko.v2ray.dto.ServerConfig
19
20
import com.neko.v2ray.dto.V2rayConfig
20
21
import com.neko.v2ray.dto.V2rayConfig.Companion.DEFAULT_NETWORK
21
22
import com.neko.v2ray.dto.V2rayConfig.Companion.HTTP
22
23
23
24
object V2rayConfigUtil {
24
- private val serverRawStorage by lazy {
25
- MMKV .mmkvWithID(
26
- MmkvManager .ID_SERVER_RAW ,
27
- MMKV .MULTI_PROCESS_MODE
28
- )
29
- }
30
- private val settingsStorage by lazy {
31
- MMKV .mmkvWithID(
32
- MmkvManager .ID_SETTING ,
33
- MMKV .MULTI_PROCESS_MODE
34
- )
35
- }
25
+ private val serverRawStorage by lazy { MMKV .mmkvWithID(MmkvManager .ID_SERVER_RAW , MMKV .MULTI_PROCESS_MODE ) }
26
+ private val settingsStorage by lazy { MMKV .mmkvWithID(MmkvManager .ID_SETTING , MMKV .MULTI_PROCESS_MODE ) }
36
27
37
28
data class Result (var status : Boolean , var content : String )
38
29
39
- /* *
40
- * 生成v2ray的客户端配置文件
41
- */
42
30
fun getV2rayConfig (context : Context , guid : String ): Result {
43
31
try {
44
32
val config = MmkvManager .decodeServerConfig(guid) ? : return Result (false , " " )
@@ -52,16 +40,8 @@ object V2rayConfigUtil {
52
40
// Log.d(ANG_PACKAGE, customConfig)
53
41
return Result (true , customConfig)
54
42
}
55
- val outbound = config.getProxyOutbound() ? : return Result (false , " " )
56
- val address = outbound.getServerAddress() ? : return Result (false , " " )
57
- if (! Utils .isIpAddress(address)) {
58
- if (! Utils .isValidUrl(address)) {
59
- Log .d(ANG_PACKAGE , " $address is an invalid ip or domain" )
60
- return Result (false , " " )
61
- }
62
- }
63
43
64
- val result = getV2rayNonCustomConfig(context, outbound, config.remarks )
44
+ val result = getV2rayNonCustomConfig(context, config)
65
45
// Log.d(ANG_PACKAGE, result.content)
66
46
return result
67
47
} catch (e: Exception ) {
@@ -70,33 +50,32 @@ object V2rayConfigUtil {
70
50
}
71
51
}
72
52
73
- /* *
74
- * 生成v2ray的客户端配置文件
75
- */
76
- private fun getV2rayNonCustomConfig (
77
- context : Context ,
78
- outbound : V2rayConfig .OutboundBean ,
79
- remarks : String ,
80
- ): Result {
53
+ private fun getV2rayNonCustomConfig (context : Context , config : ServerConfig ): Result {
81
54
val result = Result (false , " " )
55
+
56
+ val outbound = config.getProxyOutbound() ? : return result
57
+ val address = outbound.getServerAddress() ? : return result
58
+ if (! Utils .isIpAddress(address)) {
59
+ if (! Utils .isValidUrl(address)) {
60
+ Log .d(ANG_PACKAGE , " $address is an invalid ip or domain" )
61
+ return result
62
+ }
63
+ }
64
+
82
65
// 取得默认配置
83
66
val assets = Utils .readTextFromAssets(context, " v2ray_config.json" )
84
67
if (TextUtils .isEmpty(assets)) {
85
68
return result
86
69
}
87
-
88
- // 转成Json
89
70
val v2rayConfig = Gson ().fromJson(assets, V2rayConfig ::class .java) ? : return result
90
-
91
- v2rayConfig.log.loglevel = settingsStorage?.decodeString(AppConfig .PREF_LOGLEVEL )
92
- ? : " warning"
71
+ v2rayConfig.log.loglevel = settingsStorage?.decodeString(AppConfig .PREF_LOGLEVEL ) ? : " warning"
72
+ v2rayConfig.remarks = config.remarks
93
73
94
74
inbounds(v2rayConfig)
95
75
96
- updateOutboundWithGlobalSettings(outbound)
97
- v2rayConfig.outbounds[0 ] = outbound
76
+ outbounds(v2rayConfig, outbound)
98
77
99
- updateOutboundFragment (v2rayConfig)
78
+ moreOutbounds (v2rayConfig, config.subscriptionId )
100
79
101
80
routing(v2rayConfig)
102
81
@@ -112,16 +91,11 @@ object V2rayConfigUtil {
112
91
v2rayConfig.policy = null
113
92
}
114
93
115
- v2rayConfig.remarks = remarks
116
-
117
94
result.status = true
118
95
result.content = v2rayConfig.toPrettyPrinting()
119
96
return result
120
97
}
121
98
122
- /* *
123
- *
124
- */
125
99
private fun inbounds (v2rayConfig : V2rayConfig ): Boolean {
126
100
try {
127
101
val socksPort = Utils .parseInt(
@@ -170,6 +144,20 @@ object V2rayConfigUtil {
170
144
return true
171
145
}
172
146
147
+ private fun outbounds (v2rayConfig : V2rayConfig , outbound : V2rayConfig .OutboundBean ): Boolean {
148
+ val ret = updateOutboundWithGlobalSettings(outbound)
149
+ if (! ret) return false
150
+
151
+ if (v2rayConfig.outbounds.isNotEmpty()) {
152
+ v2rayConfig.outbounds[0 ] = outbound
153
+ } else {
154
+ v2rayConfig.outbounds.add(outbound)
155
+ }
156
+
157
+ updateOutboundFragment(v2rayConfig)
158
+ return true
159
+ }
160
+
173
161
private fun fakedns (v2rayConfig : V2rayConfig ) {
174
162
if (settingsStorage?.decodeBool(AppConfig .PREF_LOCAL_DNS_ENABLED ) == true
175
163
&& settingsStorage?.decodeBool(AppConfig .PREF_FAKE_DNS_ENABLED ) == true
@@ -178,9 +166,6 @@ object V2rayConfigUtil {
178
166
}
179
167
}
180
168
181
- /* *
182
- * routing
183
- */
184
169
private fun routing (v2rayConfig : V2rayConfig ): Boolean {
185
170
try {
186
171
val routingMode = settingsStorage?.decodeString(AppConfig .PREF_ROUTING_MODE )
@@ -268,12 +253,7 @@ object V2rayConfigUtil {
268
253
return true
269
254
}
270
255
271
- private fun routingGeo (
272
- ipOrDomain : String ,
273
- code : String ,
274
- tag : String ,
275
- v2rayConfig : V2rayConfig
276
- ) {
256
+ private fun routingGeo (ipOrDomain : String , code : String , tag : String , v2rayConfig : V2rayConfig ) {
277
257
try {
278
258
if (! TextUtils .isEmpty(code)) {
279
259
// IP
@@ -343,9 +323,6 @@ object V2rayConfigUtil {
343
323
return domain
344
324
}
345
325
346
- /* *
347
- * Custom Dns
348
- */
349
326
private fun customLocalDns (v2rayConfig : V2rayConfig ): Boolean {
350
327
try {
351
328
if (settingsStorage?.decodeBool(AppConfig .PREF_FAKE_DNS_ENABLED ) == true ) {
@@ -668,4 +645,58 @@ object V2rayConfigUtil {
668
645
}
669
646
return true
670
647
}
671
- }
648
+
649
+ private fun moreOutbounds (v2rayConfig : V2rayConfig , subscriptionId : String ): Boolean {
650
+ // fragment proxy
651
+ if (settingsStorage?.decodeBool(AppConfig .PREF_FRAGMENT_ENABLED , false ) == true ) {
652
+ return true
653
+ }
654
+
655
+ if (subscriptionId.isNullOrEmpty()) {
656
+ return true
657
+ }
658
+ try {
659
+ val subItem = MmkvManager .decodeSubscription(subscriptionId) ? : return false
660
+
661
+ // current proxy
662
+ val outbound = v2rayConfig.outbounds[0 ]
663
+
664
+ // Previous proxy
665
+ val prevNode = MmkvManager .getServerViaRemarks(subItem.prevProfile)
666
+ if (prevNode != null ) {
667
+ val prevOutbound = prevNode.getProxyOutbound()
668
+ if (prevOutbound != null ) {
669
+ updateOutboundWithGlobalSettings(prevOutbound)
670
+ prevOutbound.tag = TAG_PROXY + " 2"
671
+ v2rayConfig.outbounds.add(prevOutbound)
672
+ outbound.streamSettings?.sockopt =
673
+ V2rayConfig .OutboundBean .StreamSettingsBean .SockoptBean (
674
+ dialerProxy = prevOutbound.tag
675
+ )
676
+ }
677
+ }
678
+
679
+ // Next proxy
680
+ val nextNode = MmkvManager .getServerViaRemarks(subItem.nextProfile)
681
+ if (nextNode != null ) {
682
+ val nextOutbound = nextNode.getProxyOutbound()
683
+ if (nextOutbound != null ) {
684
+ updateOutboundWithGlobalSettings(nextOutbound)
685
+ nextOutbound.tag = TAG_PROXY
686
+ v2rayConfig.outbounds.add(0 , nextOutbound)
687
+
688
+ outbound.tag = TAG_PROXY + " 1"
689
+ nextOutbound.streamSettings?.sockopt =
690
+ V2rayConfig .OutboundBean .StreamSettingsBean .SockoptBean (
691
+ dialerProxy = outbound.tag
692
+ )
693
+ }
694
+ }
695
+ } catch (e: Exception ) {
696
+ e.printStackTrace()
697
+ return false
698
+ }
699
+
700
+ return true
701
+ }
702
+ }
0 commit comments