Przeglądaj źródła

sub: kcp finalmask

MHSanaei 2 dni temu
rodzic
commit
0aca2d3b3d

Plik diff jest za duży
+ 406 - 612
sub/subService.go


+ 54 - 0
web/assets/js/model/inbound.js

@@ -1370,6 +1370,50 @@ class Inbound extends XrayCommonClass {
         }
     }
 
+    static hasShareableFinalMaskValue(value) {
+        if (value == null) {
+            return false;
+        }
+        if (Array.isArray(value)) {
+            return value.some(item => Inbound.hasShareableFinalMaskValue(item));
+        }
+        if (typeof value === 'object') {
+            return Object.values(value).some(item => Inbound.hasShareableFinalMaskValue(item));
+        }
+        if (typeof value === 'string') {
+            return value.length > 0;
+        }
+        return true;
+    }
+
+    static serializeFinalMask(finalmask) {
+        if (!finalmask) {
+            return '';
+        }
+        const value = typeof finalmask.toJson === 'function' ? finalmask.toJson() : finalmask;
+        return Inbound.hasShareableFinalMaskValue(value) ? JSON.stringify(value) : '';
+    }
+
+    // Export finalmask with the same compact JSON payload shape that
+    // v2rayN-compatible share links use: fm=<json>.
+    static applyFinalMaskToParams(finalmask, params) {
+        if (!params) return;
+        const payload = Inbound.serializeFinalMask(finalmask);
+        if (payload.length > 0) {
+            params.set("fm", payload);
+        }
+    }
+
+    // VMess links are a base64 JSON object, so keep the same fm payload
+    // under a flat property instead of a URL query string.
+    static applyFinalMaskToObj(finalmask, obj) {
+        if (!obj) return;
+        const payload = Inbound.serializeFinalMask(finalmask);
+        if (payload.length > 0) {
+            obj.fm = payload;
+        }
+    }
+
     get clients() {
         switch (this.protocol) {
             case Protocols.VMESS: return this.settings.vmesses;
@@ -1590,6 +1634,8 @@ class Inbound extends XrayCommonClass {
             Inbound.applyXhttpPaddingToObj(xhttp, obj);
         }
 
+        Inbound.applyFinalMaskToObj(this.stream.finalmask, obj);
+
         if (tls === 'tls') {
             if (!ObjectUtil.isEmpty(this.stream.tls.sni)) {
                 obj.sni = this.stream.tls.sni;
@@ -1658,6 +1704,8 @@ class Inbound extends XrayCommonClass {
                 break;
         }
 
+        Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
+
         if (security === 'tls') {
             params.set("security", "tls");
             if (this.stream.isTls) {
@@ -1761,6 +1809,8 @@ class Inbound extends XrayCommonClass {
                 break;
         }
 
+        Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
+
         if (security === 'tls') {
             params.set("security", "tls");
             if (this.stream.isTls) {
@@ -1840,6 +1890,8 @@ class Inbound extends XrayCommonClass {
                 break;
         }
 
+        Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
+
         if (security === 'tls') {
             params.set("security", "tls");
             if (this.stream.isTls) {
@@ -1907,6 +1959,8 @@ class Inbound extends XrayCommonClass {
             }
         }
 
+        Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
+
         const url = new URL(link);
         for (const [key, value] of params) {
             url.searchParams.set(key, value);

+ 10 - 1
web/assets/js/model/outbound.js

@@ -992,6 +992,10 @@ class Outbound extends CommonClass {
             stream.kcp = new KcpStreamSettings();
             stream.type = json.type;
             stream.seed = json.path;
+            const mtu = Number(json.mtu);
+            if (Number.isFinite(mtu) && mtu > 0) stream.kcp.mtu = mtu;
+            const tti = Number(json.tti);
+            if (Number.isFinite(tti) && tti > 0) stream.kcp.tti = tti;
         } else if (network === 'ws') {
             stream.ws = new WsStreamSettings(json.path, json.host);
         } else if (network === 'grpc') {
@@ -1029,6 +1033,7 @@ class Outbound extends CommonClass {
         let headerType = url.searchParams.get('headerType') ?? undefined;
         let host = url.searchParams.get('host') ?? undefined;
         let path = url.searchParams.get('path') ?? undefined;
+        let seed = url.searchParams.get('seed') ?? path ?? undefined;
         let mode = url.searchParams.get('mode') ?? undefined;
 
         if (type === 'tcp' || type === 'none') {
@@ -1036,7 +1041,11 @@ class Outbound extends CommonClass {
         } else if (type === 'kcp') {
             stream.kcp = new KcpStreamSettings();
             stream.kcp.type = headerType ?? 'none';
-            stream.kcp.seed = path;
+            stream.kcp.seed = seed;
+            const mtu = Number(url.searchParams.get('mtu'));
+            if (Number.isFinite(mtu) && mtu > 0) stream.kcp.mtu = mtu;
+            const tti = Number(url.searchParams.get('tti'));
+            if (Number.isFinite(tti) && tti > 0) stream.kcp.tti = tti;
         } else if (type === 'ws') {
             stream.ws = new WsStreamSettings(path, host);
         } else if (type === 'grpc') {

+ 17 - 2
web/html/settings/panel/subscription/subpage.html

@@ -6,6 +6,23 @@
 <script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script>
 <script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
 <style>
+    .subscription-page tr-qr-box.qr-box {
+        display: inline-flex;
+        flex-direction: column;
+        align-items: center;
+        width: 220px;
+    }
+
+    .subscription-page tr-qr-box.qr-box .qr-tag {
+        width: 100%;
+        justify-content: center;
+    }
+
+    .subscription-page tr-qr-box.qr-box .qr-bg,
+    .subscription-page tr-qr-box.qr-box .qr-bg-sub {
+        margin-inline: auto;
+    }
+
     .subscription-page .subscription-link-box {
         cursor: pointer;
         border-radius: 12px;
@@ -193,8 +210,6 @@
                             </div>
                         </div>
                     </div>
-
-                    </div>
                     <br />
 
                     <a-form layout="vertical">

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików