diff --git a/.github/update.log b/.github/update.log index ffc6553d22..df828e09a1 100644 --- a/.github/update.log +++ b/.github/update.log @@ -676,3 +676,4 @@ Update On Fri Jun 14 20:32:58 CEST 2024 Update On Sat Jun 15 20:30:01 CEST 2024 Update On Sun Jun 16 20:31:07 CEST 2024 Update On Mon Jun 17 20:31:27 CEST 2024 +Update On Tue Jun 18 20:32:23 CEST 2024 diff --git a/clash-meta/adapter/outbound/direct.go b/clash-meta/adapter/outbound/direct.go index c904d3b62a..7114045d63 100644 --- a/clash-meta/adapter/outbound/direct.go +++ b/clash-meta/adapter/outbound/direct.go @@ -64,6 +64,10 @@ func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, return d.loopBack.NewPacketConn(newPacketConn(pc, d)), nil } +func (d *Direct) IsL3Protocol(metadata *C.Metadata) bool { + return true // tell DNSDialer don't send domain to DialContext, avoid lookback to DefaultResolver +} + func NewDirectWithOption(option DirectOption) *Direct { return &Direct{ Base: &Base{ diff --git a/clash-meta/component/dialer/dialer.go b/clash-meta/component/dialer/dialer.go index c21e638e4e..54a1aa6ac7 100644 --- a/clash-meta/component/dialer/dialer.go +++ b/clash-meta/component/dialer/dialer.go @@ -378,12 +378,12 @@ func (d Dialer) DialContext(ctx context.Context, network, address string) (net.C } func (d Dialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) { - opt := WithOption(d.Opt) + opt := d.Opt // make a copy if rAddrPort.Addr().Unmap().IsLoopback() { // avoid "The requested address is not valid in its context." - opt = WithInterface("") + WithInterface("")(&opt) } - return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, rAddrPort, opt) + return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, rAddrPort, WithOption(opt)) } func NewDialer(options ...Option) Dialer { diff --git a/clash-meta/go.mod b/clash-meta/go.mod index ee0eeeb42a..6030dd1e57 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -26,7 +26,7 @@ require ( github.com/metacubex/sing-shadowsocks2 v0.2.0 github.com/metacubex/sing-tun v0.2.7-0.20240617013029-d05cf9df9cfe github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f - github.com/metacubex/sing-wireguard v0.0.0-20240321042214-224f96122a63 + github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 github.com/metacubex/utls v1.6.6 github.com/miekg/dns v1.1.59 diff --git a/clash-meta/go.sum b/clash-meta/go.sum index a1d0cf5afe..7f2f105f23 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -120,8 +120,8 @@ github.com/metacubex/sing-tun v0.2.7-0.20240617013029-d05cf9df9cfe h1:NrWjVEkRmE github.com/metacubex/sing-tun v0.2.7-0.20240617013029-d05cf9df9cfe/go.mod h1:WwJGbCx7bQcBzuQXiDOJvZH27R0kIjKNNlISIWsL6kM= github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f h1:QjXrHKbTMBip/C+R79bvbfr42xH1gZl3uFb0RELdZiQ= github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY= -github.com/metacubex/sing-wireguard v0.0.0-20240321042214-224f96122a63 h1:AGyIB55UfQm/0ZH0HtQO9u3l//yjtHUpjeRjjPGfGRI= -github.com/metacubex/sing-wireguard v0.0.0-20240321042214-224f96122a63/go.mod h1:uY+BYb0UEknLrqvbGcwi9i++KgrKxsurysgI6G1Pveo= +github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a h1:NpSGclHJUYndUwBmyIpFBSoBVg8PoVX7QQKhYg0DjM0= +github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a/go.mod h1:uY+BYb0UEknLrqvbGcwi9i++KgrKxsurysgI6G1Pveo= github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 h1:as/aO/fM8nv4W4pOr9EETP6kV/Oaujk3fUNyQSJK61c= github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts= github.com/metacubex/utls v1.6.6 h1:3D12YKHTf2Z41UPhQU2dWerNWJ5TVQD9gKoQ+H+iLC8= diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 117cf9f962..3b0f3a80ca 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -27,7 +27,7 @@ "allotment": "1.20.2", "axios": "1.7.2", "dayjs": "1.11.11", - "framer-motion": "11.2.10", + "framer-motion": "12.0.0-alpha.0", "i18next": "23.11.5", "jotai": "2.8.3", "monaco-editor": "0.49.0", @@ -53,11 +53,11 @@ "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@types/react-transition-group": "4.4.10", - "@typescript-eslint/eslint-plugin": "7.13.0", - "@typescript-eslint/parser": "7.13.0", + "@typescript-eslint/eslint-plugin": "7.13.1", + "@typescript-eslint/parser": "7.13.1", "@vitejs/plugin-react": "4.3.1", "@vitejs/plugin-react-swc": "3.7.0", - "sass": "1.77.5", + "sass": "1.77.6", "shiki": "1.7.0", "tailwindcss-textshadow": "2.1.3", "vite": "5.3.1", diff --git a/clash-nyanpasu/frontend/ui/package.json b/clash-nyanpasu/frontend/ui/package.json index 1f10b9b869..d4366d9ab3 100644 --- a/clash-nyanpasu/frontend/ui/package.json +++ b/clash-nyanpasu/frontend/ui/package.json @@ -13,13 +13,13 @@ "@types/react": "18.3.3", "ahooks": "3.8.0", "d3": "7.9.0", - "framer-motion": "11.2.10", + "framer-motion": "12.0.0-alpha.0", "react": "18.3.1", "react-error-boundary": "4.0.13", "react-i18next": "14.1.2" }, "devDependencies": { - "sass": "1.77.5", + "sass": "1.77.6", "typescript-plugin-css-modules": "5.1.0" } } diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 155942a885..54f3021c18 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.18.5", - "mihomo_alpha": "alpha-0738e18", + "mihomo_alpha": "alpha-09be5cb", "clash_rs": "v0.1.18", "clash_premium": "2023-09-05-gdcc8d87" }, @@ -36,5 +36,5 @@ "darwin-x64": "clash-darwin-amd64-n{}.gz" } }, - "updated_at": "2024-06-16T22:20:26.121Z" + "updated_at": "2024-06-17T22:19:50.540Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 0c7c2b09e9..d47b73d017 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -74,7 +74,7 @@ "@tauri-apps/cli": "1.5.14", "@types/fs-extra": "11.0.4", "@types/lodash-es": "4.17.12", - "@types/node": "20.14.2", + "@types/node": "20.14.5", "autoprefixer": "10.4.19", "conventional-changelog-conventionalcommits": "8.0.0", "cross-env": "7.0.3", @@ -109,7 +109,7 @@ "tsx": "4.15.6", "typescript": "5.4.5" }, - "packageManager": "pnpm@9.3.0", + "packageManager": "pnpm@9.4.0", "engines": { "node": "22.3.0" }, diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 4a479ac08b..bcc218e523 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -24,7 +24,7 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.3.0 - version: 19.3.0(@types/node@20.14.2)(typescript@5.4.5) + version: 19.3.0(@types/node@20.14.5)(typescript@5.4.5) '@commitlint/config-conventional': specifier: 19.2.2 version: 19.2.2 @@ -38,8 +38,8 @@ importers: specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: 20.14.2 - version: 20.14.2 + specifier: 20.14.5 + version: 20.14.5 autoprefixer: specifier: 10.4.19 version: 10.4.19(postcss@8.4.38) @@ -178,7 +178,7 @@ importers: version: 11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) '@generouted/react-router': specifier: 1.19.5 - version: 1.19.5(react-router-dom@6.23.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)) + version: 1.19.5(react-router-dom@6.23.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) '@juggle/resize-observer': specifier: 3.4.0 version: 3.4.0 @@ -219,8 +219,8 @@ importers: specifier: 1.11.11 version: 1.11.11 framer-motion: - specifier: 11.2.10 - version: 11.2.10(@emotion/is-prop-valid@1.2.2)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) + specifier: 12.0.0-alpha.0 + version: 12.0.0-alpha.0(@emotion/is-prop-valid@1.2.2)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) i18next: specifier: 23.11.5 version: 23.11.5 @@ -292,20 +292,20 @@ importers: specifier: 4.4.10 version: 4.4.10 '@typescript-eslint/eslint-plugin': - specifier: 7.13.0 - version: 7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + specifier: 7.13.1 + version: 7.13.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/parser': - specifier: 7.13.0 - version: 7.13.0(eslint@8.57.0)(typescript@5.4.5) + specifier: 7.13.1 + version: 7.13.1(eslint@8.57.0)(typescript@5.4.5) '@vitejs/plugin-react': specifier: 4.3.1 - version: 4.3.1(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)) + version: 4.3.1(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) '@vitejs/plugin-react-swc': specifier: 3.7.0 - version: 3.7.0(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)) + version: 3.7.0(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) sass: - specifier: 1.77.5 - version: 1.77.5 + specifier: 1.77.6 + version: 1.77.6 shiki: specifier: 1.7.0 version: 1.7.0 @@ -314,19 +314,19 @@ importers: version: 2.1.3 vite: specifier: 5.3.1 - version: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + version: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) vite-plugin-monaco-editor: specifier: npm:vite-plugin-monaco-editor-new@1.1.3 version: vite-plugin-monaco-editor-new@1.1.3(monaco-editor@0.49.0) vite-plugin-sass-dts: specifier: 1.3.22 - version: 1.3.22(postcss@8.4.38)(prettier@3.3.2)(sass@1.77.5)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)) + version: 1.3.22(postcss@8.4.38)(prettier@3.3.2)(sass@1.77.6)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) vite-plugin-svgr: specifier: 4.2.0 - version: 4.2.0(rollup@4.17.2)(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)) + version: 4.2.0(rollup@4.17.2)(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) vite-tsconfig-paths: specifier: 4.3.2 - version: 4.3.2(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)) + version: 4.3.2(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) frontend/ui: dependencies: @@ -358,8 +358,8 @@ importers: specifier: 7.9.0 version: 7.9.0 framer-motion: - specifier: 11.2.10 - version: 11.2.10(@emotion/is-prop-valid@1.2.2)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) + specifier: 12.0.0-alpha.0 + version: 12.0.0-alpha.0(@emotion/is-prop-valid@1.2.2)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) react: specifier: npm:react@rc version: 19.0.0-rc-fb9a90fa48-20240614 @@ -371,8 +371,8 @@ importers: version: 14.1.2(i18next@23.11.5)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) devDependencies: sass: - specifier: 1.77.5 - version: 1.77.5 + specifier: 1.77.6 + version: 1.77.6 typescript-plugin-css-modules: specifier: 5.1.0 version: 5.1.0(typescript@5.4.5) @@ -1929,8 +1929,8 @@ packages: '@types/node@20.12.10': resolution: {integrity: sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==} - '@types/node@20.14.2': - resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==} + '@types/node@20.14.5': + resolution: {integrity: sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -1959,8 +1959,8 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@7.13.0': - resolution: {integrity: sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==} + '@typescript-eslint/eslint-plugin@7.13.1': + resolution: {integrity: sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -1970,8 +1970,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.13.0': - resolution: {integrity: sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==} + '@typescript-eslint/parser@7.13.1': + resolution: {integrity: sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -1980,12 +1980,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@7.13.0': - resolution: {integrity: sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==} + '@typescript-eslint/scope-manager@7.13.1': + resolution: {integrity: sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.13.0': - resolution: {integrity: sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==} + '@typescript-eslint/type-utils@7.13.1': + resolution: {integrity: sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -1994,12 +1994,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@7.13.0': - resolution: {integrity: sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==} + '@typescript-eslint/types@7.13.1': + resolution: {integrity: sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/typescript-estree@7.13.0': - resolution: {integrity: sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==} + '@typescript-eslint/typescript-estree@7.13.1': + resolution: {integrity: sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -2007,14 +2007,14 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.13.0': - resolution: {integrity: sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==} + '@typescript-eslint/utils@7.13.1': + resolution: {integrity: sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@7.13.0': - resolution: {integrity: sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==} + '@typescript-eslint/visitor-keys@7.13.1': + resolution: {integrity: sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': @@ -3223,8 +3223,8 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@11.2.10: - resolution: {integrity: sha512-/gr3PLZUVFCc86a9MqCUboVrALscrdluzTb3yew+2/qKBU8CX6nzs918/SRBRCqaPbx0TZP10CB6yFgK2C5cYQ==} + framer-motion@12.0.0-alpha.0: + resolution: {integrity: sha512-rw0+O0kqsSFPrYrSnHXrZTGAKteCj9D9HzDdHjJR8GyPWADLoQstgUYeSvLxrO3P+HlBfQtmu/SOsM9eLhKXtQ==} peerDependencies: '@emotion/is-prop-valid': '*' react: npm:react@rc @@ -4890,8 +4890,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sass@1.77.5: - resolution: {integrity: sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==} + sass@1.77.6: + resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==} engines: {node: '>=14.0.0'} hasBin: true @@ -5839,11 +5839,11 @@ snapshots: '@babel/helper-validator-identifier': 7.24.5 to-fast-properties: 2.0.0 - '@commitlint/cli@19.3.0(@types/node@20.14.2)(typescript@5.4.5)': + '@commitlint/cli@19.3.0(@types/node@20.14.5)(typescript@5.4.5)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.2.0(@types/node@20.14.2)(typescript@5.4.5) + '@commitlint/load': 19.2.0(@types/node@20.14.5)(typescript@5.4.5) '@commitlint/read': 19.2.1 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -5890,7 +5890,7 @@ snapshots: '@commitlint/rules': 19.0.3 '@commitlint/types': 19.0.3 - '@commitlint/load@19.2.0(@types/node@20.14.2)(typescript@5.4.5)': + '@commitlint/load@19.2.0(@types/node@20.14.5)(typescript@5.4.5)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 @@ -5898,7 +5898,7 @@ snapshots: '@commitlint/types': 19.0.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.4.5) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.2)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.5)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -6272,13 +6272,13 @@ snapshots: postcss: 7.0.32 purgecss: 2.3.0 - '@generouted/react-router@1.19.5(react-router-dom@6.23.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0))': + '@generouted/react-router@1.19.5(react-router-dom@6.23.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': dependencies: fast-glob: 3.3.2 - generouted: 1.19.5(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)) + generouted: 1.19.5(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) react: 19.0.0-rc-fb9a90fa48-20240614 react-router-dom: 6.23.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) - vite: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + vite: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) '@humanwhocodes/config-array@0.11.14': dependencies: @@ -6973,12 +6973,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.14.2 + '@types/node': 20.14.5 '@types/responselike': 1.0.3 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 20.14.2 + '@types/node': 20.14.5 '@types/d3-array@3.2.1': {} @@ -7112,7 +7112,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 20.14.2 + '@types/node': 20.14.5 '@types/geojson@7946.0.14': {} @@ -7128,11 +7128,11 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 20.14.2 + '@types/node': 20.14.5 '@types/keyv@3.1.4': dependencies: - '@types/node': 20.14.2 + '@types/node': 20.14.5 '@types/lodash-es@4.17.12': dependencies: @@ -7152,7 +7152,7 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@20.14.2': + '@types/node@20.14.5': dependencies: undici-types: 5.26.5 @@ -7174,7 +7174,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 20.14.2 + '@types/node': 20.14.5 '@types/unist@2.0.10': {} @@ -7182,17 +7182,17 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.14.2 + '@types/node': 20.14.5 optional: true - '@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.13.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.13.0 - '@typescript-eslint/type-utils': 7.13.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.0 + '@typescript-eslint/parser': 7.13.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.13.1 + '@typescript-eslint/type-utils': 7.13.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.13.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.13.1 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -7203,12 +7203,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/scope-manager': 7.13.0 - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.0 + '@typescript-eslint/scope-manager': 7.13.1 + '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.13.1 debug: 4.3.4 eslint: 8.57.0 optionalDependencies: @@ -7216,15 +7216,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.13.0': + '@typescript-eslint/scope-manager@7.13.1': dependencies: - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/visitor-keys': 7.13.0 + '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/visitor-keys': 7.13.1 - '@typescript-eslint/type-utils@7.13.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@7.13.1(eslint@8.57.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) + '@typescript-eslint/utils': 7.13.1(eslint@8.57.0)(typescript@5.4.5) debug: 4.3.4 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) @@ -7233,12 +7233,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@7.13.0': {} + '@typescript-eslint/types@7.13.1': {} - '@typescript-eslint/typescript-estree@7.13.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.13.1(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/visitor-keys': 7.13.0 + '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/visitor-keys': 7.13.1 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -7250,39 +7250,39 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.13.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.13.1(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.13.0 - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.13.1 + '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) eslint: 8.57.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.13.0': + '@typescript-eslint/visitor-keys@7.13.1': dependencies: - '@typescript-eslint/types': 7.13.0 + '@typescript-eslint/types': 7.13.1 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react-swc@3.7.0(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0))': + '@vitejs/plugin-react-swc@3.7.0(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': dependencies: '@swc/core': 1.6.1 - vite: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + vite: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.3.1(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0))': + '@vitejs/plugin-react@4.3.1(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': dependencies: '@babel/core': 7.24.5 '@babel/plugin-transform-react-jsx-self': 7.24.5(@babel/core@7.24.5) '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.5) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + vite: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - supports-color @@ -7770,9 +7770,9 @@ snapshots: dependencies: is-what: 3.14.1 - cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.2)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): + cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.5)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): dependencies: - '@types/node': 20.14.2 + '@types/node': 20.14.5 cosmiconfig: 9.0.0(typescript@5.4.5) jiti: 1.21.0 typescript: 5.4.5 @@ -8711,7 +8711,7 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@11.2.10(@emotion/is-prop-valid@1.2.2)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614): + framer-motion@12.0.0-alpha.0(@emotion/is-prop-valid@1.2.2)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614): dependencies: tslib: 2.6.2 optionalDependencies: @@ -8747,9 +8747,9 @@ snapshots: functions-have-names@1.2.3: {} - generouted@1.19.5(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)): + generouted@1.19.5(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: - vite: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + vite: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) gensync@1.0.0-beta.2: {} @@ -10490,7 +10490,7 @@ snapshots: safer-buffer@2.1.2: {} - sass@1.77.5: + sass@1.77.6: dependencies: chokidar: 3.6.0 immutable: 4.3.5 @@ -11073,7 +11073,7 @@ snapshots: postcss-modules-local-by-default: 4.0.5(postcss@8.4.38) postcss-modules-scope: 3.2.0(postcss@8.4.38) reserved-words: 0.1.2 - sass: 1.77.5 + sass: 1.77.6 source-map-js: 1.2.0 stylus: 0.62.0 tsconfig-paths: 4.2.0 @@ -11219,46 +11219,46 @@ snapshots: esbuild: 0.19.12 monaco-editor: 0.49.0 - vite-plugin-sass-dts@1.3.22(postcss@8.4.38)(prettier@3.3.2)(sass@1.77.5)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)): + vite-plugin-sass-dts@1.3.22(postcss@8.4.38)(prettier@3.3.2)(sass@1.77.6)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: postcss: 8.4.38 postcss-js: 4.0.1(postcss@8.4.38) prettier: 3.3.2 - sass: 1.77.5 - vite: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + sass: 1.77.6 + vite: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) - vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)): + vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.17.2) '@svgr/core': 8.1.0(typescript@5.4.5) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5)) - vite: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + vite: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@4.3.2(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0)): + vite-tsconfig-paths@4.3.2(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: debug: 4.3.4 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.4.5) optionalDependencies: - vite: 5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0) + vite: 5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - supports-color - typescript - vite@5.3.1(@types/node@20.14.2)(less@4.2.0)(sass@1.77.5)(stylus@0.62.0): + vite@5.3.1(@types/node@20.14.5)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0): dependencies: esbuild: 0.21.4 postcss: 8.4.38 rollup: 4.17.2 optionalDependencies: - '@types/node': 20.14.2 + '@types/node': 20.14.5 fsevents: 2.3.3 less: 4.2.0 - sass: 1.77.5 + sass: 1.77.6 stylus: 0.62.0 void-elements@3.1.0: {} diff --git a/clash-verge-rev/src-tauri/src/core/core.rs b/clash-verge-rev/src-tauri/src/core/core.rs index a1c917d791..afdf35576d 100644 --- a/clash-verge-rev/src-tauri/src/core/core.rs +++ b/clash-verge-rev/src-tauri/src/core/core.rs @@ -2,12 +2,12 @@ use super::service; use super::{clash_api, logger::Logger}; use crate::log_err; use crate::{config::*, utils::dirs}; -use anyhow::{bail, Context, Result}; +use anyhow::{bail, Result}; use once_cell::sync::OnceCell; use parking_lot::Mutex; use serde_yaml::Mapping; -use std::{fs, io::Write, sync::Arc, time::Duration}; -use sysinfo::{Pid, System}; +use std::{sync::Arc, time::Duration}; +use sysinfo::System; use tauri::api::process::{Command, CommandChild, CommandEvent}; use tokio::time::sleep; @@ -30,21 +30,6 @@ impl CoreManager { } pub fn init(&self) -> Result<()> { - // kill old clash process - let _ = dirs::clash_pid_path() - .and_then(|path| fs::read(path).map(|p| p.to_vec()).context("")) - .and_then(|pid| String::from_utf8_lossy(&pid).parse().context("")) - .map(|pid| { - let mut system = System::new(); - system.refresh_all(); - if let Some(proc) = system.process(Pid::from_u32(pid)) { - if proc.name().contains("clash") { - log::debug!(target: "app", "kill old clash process"); - proc.kill(); - } - } - }); - tauri::async_runtime::spawn(async { // 启动clash log_err!(Self::global().run_core().await); @@ -95,6 +80,14 @@ impl CoreManager { None => false, }; + let mut system = System::new(); + system.refresh_all(); + let procs = system.processes_by_name("clash-meta"); + for proc in procs { + log::debug!(target: "app", "kill all clash process"); + proc.kill(); + } + if *self.use_service_mode.lock() { log::debug!(target: "app", "stop the core by service"); log_err!(service::stop_core_by_service().await); @@ -149,17 +142,6 @@ impl CoreManager { let cmd = Command::new_sidecar(clash_core)?; let (mut rx, cmd_child) = cmd.args(args).spawn()?; - // 将pid写入文件中 - crate::log_err!((|| { - let pid = cmd_child.pid(); - let path = dirs::clash_pid_path()?; - fs::File::create(path) - .context("failed to create the pid file")? - .write(format!("{pid}").as_bytes()) - .context("failed to write pid to the file")?; - >::Ok(()) - })()); - let mut sidecar = self.sidecar.lock(); *sidecar = Some(cmd_child); drop(sidecar); @@ -256,6 +238,13 @@ impl CoreManager { log::debug!(target: "app", "stop the core by sidecar"); let _ = child.kill(); } + let mut system = System::new(); + system.refresh_all(); + let procs = system.processes_by_name("clash-meta"); + for proc in procs { + log::debug!(target: "app", "kill all clash process"); + proc.kill(); + } Ok(()) } diff --git a/clash-verge-rev/src-tauri/src/utils/dirs.rs b/clash-verge-rev/src-tauri/src/utils/dirs.rs index 675a78ebc7..deda1c1fda 100644 --- a/clash-verge-rev/src-tauri/src/utils/dirs.rs +++ b/clash-verge-rev/src-tauri/src/utils/dirs.rs @@ -88,10 +88,6 @@ pub fn profiles_path() -> Result { Ok(app_home_dir()?.join(PROFILE_YAML)) } -pub fn clash_pid_path() -> Result { - Ok(app_home_dir()?.join("clash.pid")) -} - #[cfg(not(target_os = "windows"))] pub fn service_path() -> Result { Ok(app_resources_dir()?.join("clash-verge-service")) diff --git a/lede/package/firmware/ipq-wifi/Makefile b/lede/package/firmware/ipq-wifi/Makefile index 8ed43f29ed..b79ccf6475 100644 --- a/lede/package/firmware/ipq-wifi/Makefile +++ b/lede/package/firmware/ipq-wifi/Makefile @@ -36,6 +36,8 @@ ALLWIFIBOARDS:= \ edimax_cax1800 \ glinet_gl-ax1800 \ glinet_gl-axt1800 \ + jdcloud_ax1800pro \ + jdcloud_ax6600 \ linksys_mr7350 \ linksys_mx4200 \ linksys_mx5300 \ @@ -143,6 +145,8 @@ $(eval $(call generate-ipq-wifi-package,edgecore_eap102,Edgecore EAP102)) $(eval $(call generate-ipq-wifi-package,edimax_cax1800,Edimax CAX1800)) $(eval $(call generate-ipq-wifi-package,glinet_gl-ax1800,GL.iNet GL-AX1800)) $(eval $(call generate-ipq-wifi-package,glinet_gl-axt1800,GL.iNet GL-AXT1800)) +$(eval $(call generate-ipq-wifi-package,jdcloud_ax1800pro,JDCloud AX1800 Pro)) +$(eval $(call generate-ipq-wifi-package,jdcloud_ax6600,JDCloud AX6600)) $(eval $(call generate-ipq-wifi-package,linksys_mr7350,Linksys MR7350)) $(eval $(call generate-ipq-wifi-package,linksys_mx4200,Linksys MX4200)) $(eval $(call generate-ipq-wifi-package,linksys_mx5300,Linksys MX5300)) diff --git a/lede/package/qca/nss-firmware/Makefile b/lede/package/qca/nss-firmware/Makefile index 1b686174aa..fda27749c5 100644 --- a/lede/package/qca/nss-firmware/Makefile +++ b/lede/package/qca/nss-firmware/Makefile @@ -22,9 +22,6 @@ PKG_MAINTAINER:=Robert Marko include $(INCLUDE_DIR)/package.mk -RSTRIP:=: -STRIP:=: - VERSION_PATH=$(PKG_BUILD_DIR)/QCA_Networking_2022.SPF_12.0.0/ED1 define Package/nss-firmware-default @@ -34,6 +31,12 @@ define Package/nss-firmware-default DEPENDS:=@TARGET_qualcommax endef +define Package/nss-firmware-ipq5018 +$(Package/nss-firmware-default) + TITLE:=NSS firmware for IPQ5018 devices + NSS_ARCHIVE:=$(VERSION_PATH)/IPQ5018.ATH.12.0.0/BIN-NSS.FW.12.1-022-MP.R.tar.bz2 +endef + define Package/nss-firmware-ipq6018 $(Package/nss-firmware-default) TITLE:=NSS firmware for IPQ6018 devices @@ -47,7 +50,16 @@ $(Package/nss-firmware-default) endef define Build/Compile + true +endef +define Package/nss-firmware-ipq5018/install + mkdir -p $(PKG_BUILD_DIR)/IPQ5018 + $(TAR) -C $(PKG_BUILD_DIR)/IPQ5018 -xf $(NSS_ARCHIVE) --strip-components=1 + $(INSTALL_DIR) $(1)/lib/firmware/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/IPQ5018/retail_router0.bin \ + $(1)/lib/firmware/qca-nss0.bin endef define Package/nss-firmware-ipq6018/install @@ -56,7 +68,7 @@ define Package/nss-firmware-ipq6018/install $(INSTALL_DIR) $(1)/lib/firmware/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/IPQ6018/retail_router0.bin \ - $(1)/lib/firmware/qca-nss0-retail.bin + $(1)/lib/firmware/qca-nss0.bin endef define Package/nss-firmware-ipq8074/install @@ -65,11 +77,12 @@ define Package/nss-firmware-ipq8074/install $(INSTALL_DIR) $(1)/lib/firmware/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/IPQ8074/retail_router0.bin \ - $(1)/lib/firmware/qca-nss0-retail.bin + $(1)/lib/firmware/qca-nss0.bin $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/IPQ8074/retail_router1.bin \ - $(1)/lib/firmware/qca-nss1-retail.bin + $(1)/lib/firmware/qca-nss1.bin endef +$(eval $(call BuildPackage,nss-firmware-ipq5018)) $(eval $(call BuildPackage,nss-firmware-ipq6018)) $(eval $(call BuildPackage,nss-firmware-ipq8074)) diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-re-ss-01.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-re-ss-01.dts new file mode 100644 index 0000000000..dbd6fcd471 --- /dev/null +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-re-ss-01.dts @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq6018-512m.dtsi" +#include "ipq6018-ess.dtsi" +#include "ipq6018-nss.dtsi" + +#include +#include + +/ { + model = "JDCloud RE-SS-01"; + compatible = "jdcloud,re-ss-01", "qcom,ipq6018"; + + aliases { + serial0 = &blsp1_uart3; + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_blue; + led-upgrade = &led_status_red; + + ethernet1 = "/soc/dp2"; + ethernet2 = "/soc/dp3"; + ethernet3 = "/soc/dp4"; + ethernet4 = "/soc/dp5"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_red: red { + label = "red:status"; + gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>; + }; + + led_status_blue: blue { + label = "blue:status"; + gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>; + }; + + led_status_green: green { + label = "green:status"; + gpios = <&tlmm 50 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + gpio-reserved-ranges = <20 1>; + + button_pins: button_pins { + mux { + pins = "gpio8", "gpio9"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + mdio_pins: mdio-pins { + mdc { + pins = "gpio64"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio65"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart3 { + pinctrl-0 = <&serial_3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&rpm { + status = "disabled"; +}; + +&sdhc { + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + non-removable; + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb3 { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + + qca8075_1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + qca8075_2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + qca8075_3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; + + qca8075_4: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x1e>; /* lan port bitmap */ + switch_wan_bmp = <0x20>; /* wan port bitmap */ + switch_inner_bmp = <0xc0>; /*inner port bitmap*/ + switch_mac_mode = <0x0>; /* mac mode for uniphy 0*/ + switch_mac_mode1 = <0xff>; /* mac mode for uniphy 1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy 2*/ + + qcom,port_phyinfo { + port@2 { + port_id = <2>; + phy_address = <1>; + }; + port@3 { + port_id = <3>; + phy_address = <2>; + }; + port@4 { + port_id = <4>; + phy_address = <3>; + }; + port@5 { + port_id = <5>; + phy_address = <4>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan1"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan2"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan3"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "wan"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6010-re-cs-02.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6010-re-cs-02.dts new file mode 100644 index 0000000000..9d3e398e5d --- /dev/null +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6010-re-cs-02.dts @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq6018.dtsi" +#include "ipq6018-ess.dtsi" +#include "ipq6018-nss.dtsi" + +#include +#include + +/ { + model = "JDCloud RE-CS-02"; + compatible = "jdcloud,re-cs-02", "qcom,ipq6018"; + + aliases { + serial0 = &blsp1_uart3; + serial1 = &blsp1_uart6; + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_blue; + led-upgrade = &led_status_red; + + ethernet0 = "/soc/dp1"; + ethernet1 = "/soc/dp2"; + ethernet2 = "/soc/dp3"; + ethernet3 = "/soc/dp4"; + ethernet4 = "/soc/dp5"; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 72 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 56 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_red: red { + label = "red:status"; + gpios = <&tlmm 57 GPIO_ACTIVE_HIGH>; + }; + + led_status_blue: blue { + label = "blue:status"; + gpios = <&tlmm 79 GPIO_ACTIVE_HIGH>; + }; + + led_status_green: green { + label = "green:status"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + gpio-reserved-ranges = <20 1>; + + button_pins: button_pins { + mux { + pins = "gpio56", "gpio72"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + btuart_pins: btuart_pins { + mux { + pins = "gpio48", "gpio49"; + function = "blsp5_uart"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + mdio_pins: mdio-pins { + mdc { + pins = "gpio64"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio65"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart3 { + pinctrl-0 = <&serial_3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_uart6 { + pinctrl-0 = <&btuart_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&pcie0 { + perst-gpio = <&tlmm 53 GPIO_ACTIVE_LOW>; + status = "okay"; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + compatible = "pci17cb,1104"; + reg = <0x00010000 0 0 0 0>; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&rpm { + status = "disabled"; +}; + +&sdhc { + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + non-removable; + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb3 { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + + qca8075_0: ethernet-phy@24 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <24>; + }; + + qca8075_1: ethernet-phy@25 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <25>; + }; + + qca8075_2: ethernet-phy@26 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <26>; + }; + + qca8075_3: ethernet-phy@27 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <27>; + }; + + qca8081: ethernet-phy@12 { + compatible = "ethernet-phy-id004d.d101"; + reg = <12>; + reset-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x1e>; /* lan port bitmap */ + switch_wan_bmp = <0x20>; /* wan port bitmap */ + switch_inner_bmp = <0xc0>; /*inner port bitmap*/ + switch_mac_mode = <0x0>; /* mac mode for uniphy 0*/ + switch_mac_mode1 = <0xf>; /* mac mode for uniphy 1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy 2*/ + + qcom,port_phyinfo { + port@1 { + port_id = <1>; + phy_address = <24>; + }; + port@2 { + port_id = <2>; + phy_address = <25>; + }; + port@3 { + port_id = <3>; + phy_address = <26>; + }; + port@4 { + port_id = <4>; + phy_address = <27>; + }; + port@5 { + port_id = <5>; + phy_address = <12>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp1 { + status = "okay"; + phy-handle = <&qca8075_0>; + label = "lan1"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan2"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan3"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan4"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8081>; + label = "wan"; +}; diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts deleted file mode 100644 index 980e0c8d5a..0000000000 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts +++ /dev/null @@ -1,668 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2020 The Linux Foundation. All rights reserved. - */ - -/dts-v1/; - -#include "ipq8074-512m.dtsi" -#include "ipq8074-ac-cpu.dtsi" -#include "ipq8074-ess.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include "ipq8074-nss.dtsi" -#include -#include -#include -/ { - #address-cells = <0x2>; - #size-cells = <0x2>; - model = "TP-Link TL-ER2260T"; - compatible = "tplink,tl-er2260t", "qcom,ipq8074"; - qcom,msm-id = <0x143 0x0>; - interrupt-parent = <&intc>; - - aliases { - led-boot = &led_sys; - led-failsafe = &led_sys; - led-running = &led_sys; - led-upgrade = &led_sys; - serial0 = &blsp1_uart5; - - ethernet0 = "/soc/dp1"; - ethernet1 = "/soc/dp2"; - ethernet2 = "/soc/dp3"; - ethernet3 = "/soc/dp4"; - ethernet4 = "/soc/dp5"; - ethernet5 = "/soc/dp6"; - }; - - chosen { - stdout-path = "serial0"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - gpio_keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; - linux,input-type = <1>; - debounce-interval = <60>; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-0 = <&leds_pins>; - pinctrl-names = "default"; - - led_sys: sys { - label = "green:sys"; - gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; - }; - - usb { - label = "green:usb"; - gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "usbport"; - }; - - sfp1-green { - label = "green:sfp1"; - gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; - }; - - sfp2-green { - label = "green:sfp2"; - gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>; - }; - }; - - spi@78b5000 { - status = "ok"; - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-select = <0>; - - m25p80@0 { - compatible = "n25q128a11"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - spi-max-frequency = <50000000>; - }; - }; -}; - -&tlmm { - mdio_pins: mdio_pinmux { - mux_0 { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - mux_1 { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - mux_2 { - pins = "gpio44"; - function = "gpio"; - bias-pull-up; - }; - }; - - i2c_1_pins: i2c_1_pins { - pins = "gpio46", "gpio47"; - function = "blsp2_i2c"; - drive-strength = <8>; - bias-disable; - }; - - button_pins: button_pins { - reset { - pins = "gpio50"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - uniphy_pins: uniphy_pinmux { - mux { - pins = "gpio60"; - function = "rx2"; - bias-disable; - }; - sfp_tx { - pins = "gpio59"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - output-high; - }; - }; - - leds_pins: leds_pinmux { - mux { - pins = "gpio21", "gpio22", "gpio65"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_sfp1_active { - pins = "gpio51"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_sfp2_active { - pins = "gpio55"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; -}; - -&mdio { - status = "okay"; - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - phy0:ethernet-phy@0 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <0>; - }; - phy1:ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - }; - phy2:ethernet-phy@2 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <2>; - }; - phy3:ethernet-phy@3 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <3>; - }; - phy4: ethernet-phy@29 { - reg = <29>; - }; - phy5: ethernet-phy@30 { - reg = <30>; - }; -}; - -&switch { - status = "okay"; - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xe>; /* mac mode for uniphy instance1*/ //use 10g_baser mode for default - switch_mac_mode2 = <0xe>; /* mac mode for uniphy instance2*/ //use 10g_baser mode for default - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - cmnblk_clk = "external_50MHz"; - - qcom,port_phyinfo { - port@0 { - port_id = <1>; - phy_address = <0>; - }; - port@1 { - port_id = <2>; - phy_address = <1>; - }; - port@2 { - port_id = <3>; - phy_address = <2>; - }; - port@3 { - port_id = <4>; - phy_address = <3>; - }; - port@4 { - port_id = <5>; - phy_address = <29>;//29 - phy_i2c_address = <29>;//29 - phy-i2c-mode; /*i2c access phy */ - media-type = "sfp"; /* fiber mode */ - }; - port@5 { - port_id = <6>; - phy_address = <30>;//30 - phy_i2c_address = <30>;//30 - phy-i2c-mode; /*i2c access phy */ - media-type = "sfp"; /* fiber mode */ - }; - }; - port_scheduler_resource { - port@0 { - port_id = <0>; - ucast_queue = <0 143>; - mcast_queue = <256 271>; - l0sp = <0 35>; - l0cdrr = <0 47>; - l0edrr = <0 47>; - l1cdrr = <0 7>; - l1edrr = <0 7>; - }; - port@1 { - port_id = <1>; - ucast_queue = <144 159>; - mcast_queue = <272 275>; - l0sp = <36 39>; - l0cdrr = <48 63>; - l0edrr = <48 63>; - l1cdrr = <8 11>; - l1edrr = <8 11>; - }; - port@2 { - port_id = <2>; - ucast_queue = <160 175>; - mcast_queue = <276 279>; - l0sp = <40 43>; - l0cdrr = <64 79>; - l0edrr = <64 79>; - l1cdrr = <12 15>; - l1edrr = <12 15>; - }; - port@3 { - port_id = <3>; - ucast_queue = <176 191>; - mcast_queue = <280 283>; - l0sp = <44 47>; - l0cdrr = <80 95>; - l0edrr = <80 95>; - l1cdrr = <16 19>; - l1edrr = <16 19>; - }; - port@4 { - port_id = <4>; - ucast_queue = <192 207>; - mcast_queue = <284 287>; - l0sp = <48 51>; - l0cdrr = <96 111>; - l0edrr = <96 111>; - l1cdrr = <20 23>; - l1edrr = <20 23>; - }; - port@5 { - port_id = <5>; - ucast_queue = <208 223>; - mcast_queue = <288 291>; - l0sp = <52 55>; - l0cdrr = <112 127>; - l0edrr = <112 127>; - l1cdrr = <24 27>; - l1edrr = <24 27>; - }; - port@6 { - port_id = <6>; - ucast_queue = <224 239>; - mcast_queue = <292 295>; - l0sp = <56 59>; - l0cdrr = <128 143>; - l0edrr = <128 143>; - l1cdrr = <28 31>; - l1edrr = <28 31>; - }; - port@7 { - port_id = <7>; - ucast_queue = <240 255>; - mcast_queue = <296 299>; - l0sp = <60 63>; - l0cdrr = <144 159>; - l0edrr = <144 159>; - l1cdrr = <32 35>; - l1edrr = <32 35>; - }; - }; - port_scheduler_config { - port@0 { - port_id = <0>; - l1scheduler { - group@0 { - sp = <0 1>; /*L0 SPs*/ - /*cpri cdrr epri edrr*/ - cfg = <0 0 0 0>; - }; - }; - l0scheduler { - group@0 { - /*unicast queues*/ - ucast_queue = <0 4 8>; - /*multicast queues*/ - mcast_queue = <256 260>; - /*sp cpri cdrr epri edrr*/ - cfg = <0 0 0 0 0>; - }; - group@1 { - ucast_queue = <1 5 9>; - mcast_queue = <257 261>; - cfg = <0 1 1 1 1>; - }; - group@2 { - ucast_queue = <2 6 10>; - mcast_queue = <258 262>; - cfg = <0 2 2 2 2>; - }; - group@3 { - ucast_queue = <3 7 11>; - mcast_queue = <259 263>; - cfg = <0 3 3 3 3>; - }; - }; - }; - port@1 { - port_id = <1>; - l1scheduler { - group@0 { - sp = <36>; - cfg = <0 8 0 8>; - }; - group@1 { - sp = <37>; - cfg = <1 9 1 9>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <144>; - ucast_loop_pri = <16>; - mcast_queue = <272>; - mcast_loop_pri = <4>; - cfg = <36 0 48 0 48>; - }; - }; - }; - port@2 { - port_id = <2>; - l1scheduler { - group@0 { - sp = <40>; - cfg = <0 12 0 12>; - }; - group@1 { - sp = <41>; - cfg = <1 13 1 13>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <160>; - ucast_loop_pri = <16>; - mcast_queue = <276>; - mcast_loop_pri = <4>; - cfg = <40 0 64 0 64>; - }; - }; - }; - port@3 { - port_id = <3>; - l1scheduler { - group@0 { - sp = <44>; - cfg = <0 16 0 16>; - }; - group@1 { - sp = <45>; - cfg = <1 17 1 17>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <176>; - ucast_loop_pri = <16>; - mcast_queue = <280>; - mcast_loop_pri = <4>; - cfg = <44 0 80 0 80>; - }; - }; - }; - port@4 { - port_id = <4>; - l1scheduler { - group@0 { - sp = <48>; - cfg = <0 20 0 20>; - }; - group@1 { - sp = <49>; - cfg = <1 21 1 21>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <192>; - ucast_loop_pri = <16>; - mcast_queue = <284>; - mcast_loop_pri = <4>; - cfg = <48 0 96 0 96>; - }; - }; - }; - port@5 { - port_id = <5>; - l1scheduler { - group@0 { - sp = <52>; - cfg = <0 24 0 24>; - }; - group@1 { - sp = <53>; - cfg = <1 25 1 25>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <208>; - ucast_loop_pri = <16>; - mcast_queue = <288>; - mcast_loop_pri = <4>; - cfg = <52 0 112 0 112>; - }; - }; - }; - port@6 { - port_id = <6>; - l1scheduler { - group@0 { - sp = <56>; - cfg = <0 28 0 28>; - }; - group@1 { - sp = <57>; - cfg = <1 29 1 29>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <224>; - ucast_loop_pri = <16>; - mcast_queue = <292>; - mcast_loop_pri = <4>; - cfg = <56 0 128 0 128>; - }; - }; - }; - port@7 { - port_id = <7>; - l1scheduler { - group@0 { - sp = <60>; - cfg = <0 32 0 32>; - }; - group@1 { - sp = <61>; - cfg = <1 33 1 33>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <240>; - ucast_loop_pri = <16>; - mcast_queue = <296>; - cfg = <60 0 144 0 144>; - }; - }; - }; - }; -}; - -&soc { - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <0>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <1>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <2>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <3>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <29>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <30>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - nss-macsec1 { - compatible = "qcom,nss-macsec"; - phy_addr = <0x1c>; - phy_access_mode = <0x00>; - mdiobus = <&mdio>; - }; - - watchdog@b017000 { - compatible = "qcom,kpss-wdt-ipq807x"; - reg = <0xb017000 0x1000>; - reg-names = "kpss_wdt"; - interrupt-names = "bark_irq"; - interrupts = <0x00 0x03 0x00>; - clocks = <&sleep_clk>; - timeout-sec = <0x0a>; - wdt-max-timeout = <0x20>; - }; -}; - -&blsp1_i2c2 { - status = "okay"; -}; - -&blsp1_i2c3 { - pinctrl-0 = <&i2c_1_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - - partitions { - compatible = "qcom,smem-part"; - }; - }; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&usb_0 { - status = "okay"; -}; diff --git a/lede/target/linux/qualcommax/image/ipq60xx.mk b/lede/target/linux/qualcommax/image/ipq60xx.mk index 6ef006faf6..ef05a150be 100644 --- a/lede/target/linux/qualcommax/image/ipq60xx.mk +++ b/lede/target/linux/qualcommax/image/ipq60xx.mk @@ -18,9 +18,9 @@ define Device/UbiFit endef define Device/EmmcImage - IMAGES += factory.bin sysupgrade.bin - IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 64k - IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to 64k | sysupgrade-tar rootfs=$$$$@ | append-metadata + IMAGES := factory.bin recovery.bin sysupgrade.bin + IMAGE/factory.bin := append-kernel | pad-to 12288k | append-rootfs | append-metadata + IMAGE/recovery.bin := append-kernel | pad-to 6144k | append-rootfs | append-metadata endef define Device/cmiot_ax18 @@ -61,6 +61,32 @@ define Device/glinet_gl-axt1800 endef TARGET_DEVICES += glinet_gl-axt1800 +define Device/jdcloud_re-cs-02 + $(call Device/FitImage) + $(call Device/EmmcImage) + DEVICE_VENDOR := JDCloud + DEVICE_MODEL := AX6600 + SOC := ipq6010 + BLOCKSIZE := 64k + KERNEL_SIZE := 6144k + DEVICE_DTS_CONFIG := config@cp03-c3 + DEVICE_PACKAGES := ipq-wifi-jdcloud_ax6600 kmod-ath11k-pci ath11k-firmware-qcn9074 +endef +TARGET_DEVICES += jdcloud_re-cs-02 + +define Device/jdcloud_re-ss-01 + $(call Device/FitImage) + $(call Device/EmmcImage) + DEVICE_VENDOR := JDCloud + DEVICE_MODEL := AX1800 Pro + SOC := ipq6000 + BLOCKSIZE := 64k + KERNEL_SIZE := 6144k + DEVICE_DTS_CONFIG := config@cp03-c2 + DEVICE_PACKAGES := ipq-wifi-jdcloud_ax1800pro +endef +TARGET_DEVICES += jdcloud_re-ss-01 + define Device/linksys_mr7350 $(call Device/FitImage) DEVICE_VENDOR := Linksys diff --git a/lede/target/linux/qualcommax/image/ipq807x.mk b/lede/target/linux/qualcommax/image/ipq807x.mk index 42c4cbaa9d..6406d00131 100644 --- a/lede/target/linux/qualcommax/image/ipq807x.mk +++ b/lede/target/linux/qualcommax/image/ipq807x.mk @@ -219,20 +219,6 @@ define Device/redmi_ax6 endef TARGET_DEVICES += redmi_ax6 -define Device/tplink_tl-er2260t - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := TPLINK - DEVICE_MODEL := TL-ER2260T - SOC := ipq8070 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@hk07 - BOARD_NAME := tplink,tl-er2260t - DEVICE_PACKAGES += -kmod-ath11k-ahb -wpad-openssl kmod-i2c-gpio kmod-sfp -endef -TARGET_DEVICES += tplink_tl-er2260t - define Device/xiaomi_ax3600 $(call Device/FitImage) $(call Device/UbiFit) diff --git a/lede/target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network b/lede/target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network index ead1fb8f0f..fc123c9a1b 100644 --- a/lede/target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network +++ b/lede/target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network @@ -12,12 +12,14 @@ ipq60xx_setup_interfaces() case "$board" in cmiot,ax18|\ + jdcloud,re-ss-01|\ qihoo,360v6|\ redmi,ax5-*|\ xiaomi,rm1800) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" ;; glinet,gl-ax1800|\ + jdcloud,re-cs-02|\ linksys,mr7350) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; diff --git a/lede/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/lede/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata index a05c55005a..b82946cdc5 100644 --- a/lede/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata +++ b/lede/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata @@ -16,11 +16,20 @@ case "$FIRMWARE" in xiaomi,rm1800) caldata_extract "0:art" 0x1000 0x10000 ;; + jdcloud,re-cs-02|\ + jdcloud,re-ss-01|\ redmi,ax5-jdcloud) caldata_extract_mmc "0:ART" 0x1000 0x10000 ;; esac ;; +"ath11k/QCN9074/hw1.0/cal-pci-0000:01:00.0.bin") + case "$board" in + jdcloud,re-cs-02) + caldata_extract_mmc "0:ART" 0x26800 0x20000 + ;; + esac + ;; *) exit 1 ;; diff --git a/lede/target/linux/qualcommax/ipq60xx/base-files/lib/preinit/81_fix_eeprom b/lede/target/linux/qualcommax/ipq60xx/base-files/lib/preinit/81_fix_eeprom new file mode 100644 index 0000000000..34b91f4dfa --- /dev/null +++ b/lede/target/linux/qualcommax/ipq60xx/base-files/lib/preinit/81_fix_eeprom @@ -0,0 +1,19 @@ +. /lib/functions/caldata.sh + +preinit_fix_eeprom() { + case $(board_name) in + jdcloud,re-cs-02|\ + jdcloud,re-ss-01|\ + redmi,ax5-jdcloud) + mmc_part=$(find_mmc_part 0:ART) + FIRMWARE=""ath11k/IPQ6018/hw1.0/cal-ahb-c000000.wifi.bin"" + [ ! -e /lib/firmware/"$FIRMWARE" ] && \ + export FIRMWARE="$FIRMWARE" && \ + caldata_extract_mmc "0:ART" 0x1000 0x10000 + ;; + *) + ;; + esac +} + +boot_hook_add preinit_main preinit_fix_eeprom diff --git a/lede/target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh b/lede/target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh index b04d230c4f..e199c33c1c 100644 --- a/lede/target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh +++ b/lede/target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh @@ -17,6 +17,13 @@ platform_do_upgrade() { xiaomi,rm1800) nand_do_upgrade "$1" ;; + jdcloud,re-cs-02|\ + jdcloud,re-ss-01|\ + redmi,ax5-jdcloud) + kernelname="0:HLOS" + rootfsname="rootfs" + mmc_do_upgrade "$1" + ;; linksys,mr7350) boot_part="$(fw_printenv -n boot_part)" if [ "$boot_part" -eq "1" ]; then @@ -31,11 +38,6 @@ platform_do_upgrade() { fw_setenv auto_recovery yes nand_do_upgrade "$1" ;; - redmi,ax5-jdcloud) - kernelname="0:HLOS" - rootfsname="rootfs" - mmc_do_upgrade "$1" - ;; *) default_do_upgrade "$1" ;; diff --git a/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds b/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds index 46620a24fc..5e478d75ee 100644 --- a/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds +++ b/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds @@ -32,10 +32,6 @@ redmi,ax6|\ xiaomi,ax3600) ucidef_set_led_netdev "wan" "WAN" "blue:network" "wan" ;; -tplink,tl-er2260t) - ucidef_set_led_netdev "SFP1_active" "SFP1_ACTIVE" "green:sfp1" "eth5" - ucidef_set_led_netdev "SFP2_active" "SFP2_ACTIVE" "green:sfp2" "eth4" - ;; qnap,301w) ucidef_set_led_netdev "lan1" "LAN1" "green:lan1" "lan1" ucidef_set_led_netdev "lan2" "LAN2" "green:lan2" "lan2" diff --git a/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network b/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network index da8b478331..7c630e096f 100644 --- a/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network +++ b/lede/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network @@ -46,9 +46,6 @@ ipq807x_setup_interfaces() prpl,haze) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" ;; - tplink,tl-er2260t) - ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth5" "eth4" - ;; qnap,301w) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 10g-2" "10g-1" ;; diff --git a/lede/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/lede/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh index f2c075cdd0..4c8a38c261 100644 --- a/lede/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/lede/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -19,7 +19,6 @@ platform_do_upgrade() { netgear,wax218|\ netgear,wax620|\ netgear,wax630|\ - tplink,tl-er2260t|\ zte,mf269) nand_do_upgrade "$1" ;; diff --git a/mihomo/adapter/outbound/direct.go b/mihomo/adapter/outbound/direct.go index c904d3b62a..7114045d63 100644 --- a/mihomo/adapter/outbound/direct.go +++ b/mihomo/adapter/outbound/direct.go @@ -64,6 +64,10 @@ func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, return d.loopBack.NewPacketConn(newPacketConn(pc, d)), nil } +func (d *Direct) IsL3Protocol(metadata *C.Metadata) bool { + return true // tell DNSDialer don't send domain to DialContext, avoid lookback to DefaultResolver +} + func NewDirectWithOption(option DirectOption) *Direct { return &Direct{ Base: &Base{ diff --git a/mihomo/component/dialer/dialer.go b/mihomo/component/dialer/dialer.go index c21e638e4e..54a1aa6ac7 100644 --- a/mihomo/component/dialer/dialer.go +++ b/mihomo/component/dialer/dialer.go @@ -378,12 +378,12 @@ func (d Dialer) DialContext(ctx context.Context, network, address string) (net.C } func (d Dialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) { - opt := WithOption(d.Opt) + opt := d.Opt // make a copy if rAddrPort.Addr().Unmap().IsLoopback() { // avoid "The requested address is not valid in its context." - opt = WithInterface("") + WithInterface("")(&opt) } - return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, rAddrPort, opt) + return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, rAddrPort, WithOption(opt)) } func NewDialer(options ...Option) Dialer { diff --git a/mihomo/go.mod b/mihomo/go.mod index ee0eeeb42a..6030dd1e57 100644 --- a/mihomo/go.mod +++ b/mihomo/go.mod @@ -26,7 +26,7 @@ require ( github.com/metacubex/sing-shadowsocks2 v0.2.0 github.com/metacubex/sing-tun v0.2.7-0.20240617013029-d05cf9df9cfe github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f - github.com/metacubex/sing-wireguard v0.0.0-20240321042214-224f96122a63 + github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 github.com/metacubex/utls v1.6.6 github.com/miekg/dns v1.1.59 diff --git a/mihomo/go.sum b/mihomo/go.sum index a1d0cf5afe..7f2f105f23 100644 --- a/mihomo/go.sum +++ b/mihomo/go.sum @@ -120,8 +120,8 @@ github.com/metacubex/sing-tun v0.2.7-0.20240617013029-d05cf9df9cfe h1:NrWjVEkRmE github.com/metacubex/sing-tun v0.2.7-0.20240617013029-d05cf9df9cfe/go.mod h1:WwJGbCx7bQcBzuQXiDOJvZH27R0kIjKNNlISIWsL6kM= github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f h1:QjXrHKbTMBip/C+R79bvbfr42xH1gZl3uFb0RELdZiQ= github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY= -github.com/metacubex/sing-wireguard v0.0.0-20240321042214-224f96122a63 h1:AGyIB55UfQm/0ZH0HtQO9u3l//yjtHUpjeRjjPGfGRI= -github.com/metacubex/sing-wireguard v0.0.0-20240321042214-224f96122a63/go.mod h1:uY+BYb0UEknLrqvbGcwi9i++KgrKxsurysgI6G1Pveo= +github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a h1:NpSGclHJUYndUwBmyIpFBSoBVg8PoVX7QQKhYg0DjM0= +github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a/go.mod h1:uY+BYb0UEknLrqvbGcwi9i++KgrKxsurysgI6G1Pveo= github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 h1:as/aO/fM8nv4W4pOr9EETP6kV/Oaujk3fUNyQSJK61c= github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts= github.com/metacubex/utls v1.6.6 h1:3D12YKHTf2Z41UPhQU2dWerNWJ5TVQD9gKoQ+H+iLC8= diff --git a/openwrt-packages/luci-theme-alpha/luasrc/favicon.ico b/openwrt-packages/luci-theme-alpha/luasrc/favicon.ico index c84d86b23e..06ac3fb001 100644 Binary files a/openwrt-packages/luci-theme-alpha/luasrc/favicon.ico and b/openwrt-packages/luci-theme-alpha/luasrc/favicon.ico differ diff --git a/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css b/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css index 0bdbaa1be9..7e45b96214 100755 --- a/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css +++ b/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css @@ -825,6 +825,7 @@ user-select: none; } + .main>.main-left>.nav>li>[data-title="Log out"], .main>.main-left>.nav>li>[data-title="Logout"] { display: flex; padding: 0.5rem 1rem; @@ -835,6 +836,7 @@ color: #cbcbcb; } + .main>.main-left>.nav>li>[data-title="Log out"], .main>.main-left>.nav>li>[data-title="Logout"], .main>.main-left>.nav>li>[data-title="iStore"] { font-size: 1rem; @@ -1042,7 +1044,8 @@ transition: transform 0.2s ease-in-out; } - .main>.main-left>.nav>li>[data-title="Logout"]::before { + .main>.main-left>.nav>li>[data-title="Logout"]::before, + .main>.main-left>.nav>li>[data-title="Log out"]::before { position: absolute; right: 14px; width: 25px; @@ -1073,6 +1076,7 @@ .main>.main-left>.nav>.slide>.menu, .main>.main-left>.nav>.slide>.slide-menu>li, .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="Log out"], .main>.main-left>.nav>li>[data-title="iStore"] { position: relative; overflow: hidden; @@ -1082,6 +1086,7 @@ .main>.main-left>.nav>.slide>.menu::after, .main>.main-left>.nav>.slide>.slide-menu>li::after, .main>.main-left>.nav>li>[data-title="Logout"]::after, + .main>.main-left>.nav>li>[data-title="Log out"]::after, .main>.main-left>.nav>li>[data-title="iStore"]::after { position: absolute; top: 0; @@ -1102,6 +1107,7 @@ .main>.main-left>.nav>.slide>.menu:active::after, .main>.main-left>.nav>.slide>.slide-menu>li:active::after, .main>.main-left>.nav>li>[data-title="Logout"]:active::after, + .main>.main-left>.nav>li>[data-title="Log out"]:active::after, .main>.main-left>.nav>li>[data-title="iStore"]:active::after { transition: 0s; transform: scale(0, 0); @@ -1858,7 +1864,7 @@ min-height: 20px; white-space: nowrap; text-overflow: ellipsis; - padding: 0.3rem; + padding: 0.3rem 1rem 0.3rem 1rem; } .cbi-dropdown>ul>li[display]:not([display="0"]) { @@ -2091,6 +2097,7 @@ .spinning { position: relative; + align-items: center; padding-left: 32px !important; color: #fff; } @@ -2100,14 +2107,13 @@ font-size: medium; font-style: "Quicksand-Bold"; left: 8px; - width: 20px; - height: 20px; + width: 16px; + height: 16px; content: ""; animation: anim-rotate 2s infinite cubic-bezier(0.18, 0.89, 0.32, 1.28); background: url(./icon/loading.svg) no-repeat center; background-size: 20px; } - } .left, .left::before { @@ -2311,6 +2317,7 @@ align-content: center; justify-content: flex-start; align-items: center; + color: #fff; } div.ifacebox-head { @@ -2760,7 +2767,7 @@ } .cbi-rowstyle-2 { - background-color: ; + /*background-color: 0px;*/ } .pull-right, @@ -3132,6 +3139,7 @@ .main>.main-left>.nav>li a, .main>.main-left>.nav>.slide>.menu, .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="Logout"], .main>.main-left>.nav>li>[data-title="iStore"] { font-size: 1rem; color: #fff; @@ -3405,6 +3413,7 @@ .main>.main-left>.nav>.slide>.menu, .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="Log out"], .main>.main-left>.nav>li>[data-title="iStore"] { font-size: 1.1rem; } @@ -3564,7 +3573,6 @@ .cbi-value-field .cbi-input-select, .cbi-value input[type="text"], .node-system-packages>.main .cbi-value .cbi-value-field input { - width: 30%; color: #fff; } @@ -3584,6 +3592,7 @@ font-size: 0.9rem; } + @media screen and (min-width: 600px) { ::-webkit-scrollbar { width: 10px; diff --git a/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css.bak b/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css.bak new file mode 100644 index 0000000000..0b9b3d5435 --- /dev/null +++ b/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css.bak @@ -0,0 +1,3625 @@ + /* Base */ + @font-face { + font-family: "Inter-Regular"; + src: url('/luci-static/alpha/fonts/Inter-Regular.woff2'); + } + + @font-face { + font-family: "Inter-Medium"; + src: url('/luci-static/alpha/fonts/Inter-Medium.woff2'); + } + + @font-face { + font-family: "Inter-Black"; + src: url('/luci-static/alpha/fonts/Inter-Black.woff2'); + } + + @font-face { + font-family: "Inter-Bold"; + src: url('/luci-static/alpha/fonts/Inter-Bold.woff2'); + } + + @font-face { + font-family: "Quicksand-Bold"; + src: url('/luci-static/alpha/fonts/Quicksand-Bold.ttf'); + } + + @font-face { + font-family: argon; + src: url('/luci-static/alpha/fonts/argon.woff'); + + } + + [class^="icon-"], + [class*=" icon-"] { + font-family: argon !important; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + a { + color: #5a8dee; + text-decoration: none; + background-color: transparent; + } + + b { + color: #5a8dee; + text-decoration: none; + background-color: transparent; + font-family: "Quicksand-Bold"; + + } + + ::-webkit-scrollbar:hover { + background-color: rgba(100, 100, 100, 0.09); + } + + ::-webkit-scrollbar-thumb:vertical { + background: rgba(100, 100, 100, 0.5); + -webkit-border-radius: 100px; + } + + ::-webkit-scrollbar-thumb:vertical:active { + background: rgba(100, 100, 100, 0.61); + -webkit-border-radius: 100px; + } + + ::-webkit-scrollbar { + width: 0.2em !important; + overflow: visible; + border-radius: 4px; + -webkit-border-radius: 4px; + } + + ::-webkit-scrollbar-track { + opacity: 0; + -webkit-transition: all 0.5s; + } + + ::-webkit-scrollbar-thumb { + overflow: visible; + border-radius: 4px; + background: rgba(100, 100, 100, 0.2); + } + + .icon-hello-world:before { + content: "\e90e"; + } + + .icon-expand_more:before { + content: "\e20b"; + } + + .icon-menu:before { + content: "\e20e"; + } + + .icon-favorite:before { + content: "\e291"; + } + + .icon-spinner:before { + content: "\e603"; + } + + .icon-delete:before { + content: "\e900"; + } + + .icon-edit:before { + content: "\e901"; + } + + .icon-use:before { + content: "\e902"; + } + + .icon-loading:before { + content: "\e903"; + } + + .icon-switch:before { + content: "\e904"; + } + + .icon-error:before { + content: "\e905"; + } + + .icon-dashboard:before { + content: "\e906"; + } + + .icon-logout:before { + content: "\e907"; + } + + .icon-Network:before { + content: "\e908"; + } + + .icon-services:before { + content: "\e909"; + } + + .icon-system:before { + content: "\e90a"; + } + + .icon-vpn:before { + content: "\e90b"; + } + + .icon-storage:before { + content: "\e90c"; + } + + .icon-statistics:before { + content: "\e90d"; + } + + .icon-angle-right:before { + content: "\e90f"; + } + + .icon-user:before { + content: "\e971"; + } + + .icon-question:before { + content: "\f059"; + } + + :root { + --main-color: #09c; + --header-bg: #161624; + --header-color: rgb(10, 10, 10); + --bar-bg: #3f3f3f69; + --menu-bg-color: #fff; + --menu-color: #5f6368; + --menu-color-hover: #202124; + --main-menu-color: #202124; + --submenu-bg-hover: #4d5ca5; + --submenu-bg-hover-active: #09c; + --font-body: 'Inter-Regular'; + } + + tt { + font-family: "Quicksand-Bold"; + color: #09c; + } + + em { + font-style: italic; + color: #fff + } + + p { + display: block; + margin-block-start: 1em; + margin-block-end: 1em; + margin-inline-start: 0px; + margin-inline-end: 0px; + color: #ffffff; + } + + li { + display: block; + list-style-type: disc; + margin-block-start: 5px; + margin-block-end: 5px; + margin-inline-start: 0px; + margin-inline-end: 0px; + color: #ffffff; + } + + small { + font-size: smaller; + color: #ffff; + } + + label { + cursor: default; + color: #ffffff; + } + + .table { + position: relative; + display: table; + } + + .tr { + display: table-row; + } + + .thead { + display: table-header-group; + } + + .tbody { + display: table-row-group; + } + + .tfoot { + display: table-footer-group; + } + + .td, + .th { + line-height: normal; + display: table-cell; + vertical-align: middle; + padding: 0.5em; + } + + .th { + font-weight: 700; + } + + .tr.placeholder { + height: 4em; + } + + .tr.placeholder>.td { + line-height: 3; + position: absolute; + right: 0; + bottom: 0; + left: 0; + text-align: center !important; + background: inherit; + } + + .table[width="33%"], + .th[width="33%"], + .td[width="33%"] { + width: 33%; + } + + .col-1 { + flex: 1 1 30px !important; + } + + .col-2 { + flex: 2 2 60px !important; + } + + .col-3 { + flex: 3 3 90px !important; + } + + .col-4 { + flex: 4 4 120px !important; + } + + .col-5 { + flex: 5 5 150px !important; + } + + .col-6 { + flex: 6 6 180px !important; + } + + .col-7 { + flex: 7 7 210px !important; + } + + .col-8 { + flex: 8 8 240px !important; + } + + .col-9 { + flex: 9 9 270px !important; + } + + .col-10 { + flex: 10 10 300px !important; + } + + * { + box-sizing: border-box; + padding: 0; + } + + .h1, + .h2, + .h3, + .h4, + .h5, + .h6, + h1, + h2, + h3, + h4, + h5, + h6 { + font-family: inherit; + font-weight: 400; + line-height: 1.1 !important; + color: #fff; + } + + html { + overflow-y: hidden; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + } + + body { + font-size: 0.8rem; + height: 100%; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + background-attachment: fixed; + background-color: rgb(10, 10, 10); + } + + .text { + font-style: italic; + color: #fff; + } + + html, + body { + font-family: var(--font-body); + height: 100%; + margin: 0; + padding: 0; + } + + select { + color: #555; + border: thin solid #ccc; + background-color: #fff; + background-image: none; + padding: 0.36rem 0.8rem; + } + + .btn, + button, + select, + input, + .cbi-dropdown { + height: 2.3rem; + color: rgba(255, 255, 255, 0.87); + border: 0; + border-bottom: 2px solid #30304b; + border-radius: 10px; + border-radius: 20px; + outline: 0; + background-color: #222235; + background-image: none; + box-shadow: none; + padding: 0.5rem; + } + + select, + .cbi-dropdown { + width: inherit; + cursor: default; + } + + select:not([multiple="multiple"]):focus, + input:not(.cbi-button):focus, + .cbi-dropdown:focus { + border-color: var(--main-color); + } + + .cbi-dropdown, + select[multiple="multiple"] { + height: auto; + } + + pre { + overflow: auto; + color: #fff; + } + + code { + font-size: 1rem; + font-size-adjust: 0.35; + color: #101010; + border-radius: 0px; + background: #ddd; + padding: 1px 3px; + } + + abbr { + cursor: help; + text-decoration: underline; + color: #84d0ea; + } + + hr { + opacity: 0.1; + border-color: #eee; + margin: 1rem 0; + } + + /* End Base */ + + /* Header */ + header, + .main { + position: absolute; + width: 100%; + } + + header { + position: fixed; + z-index: 2000; + float: left; + height: 4rem; + transition: box-shadow 0.2s; + color: var(--header-color); + background: #2222359a; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + } + + header>.fill>.container { + margin-top: 0.5rem; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0.5rem 1rem 0; + } + + header>.fill>.container>#logo { + padding: 0; + margin: 0 !important; + position: absolute; + left: 0; + top: 50%; + height: 100%; + transform: translateY(-50%); + padding: 1rem; + display: flex; + justify-content: center; + width: calc(16rem); + } + + header>.fill>.container>#logo>img { + width: auto; + height: 100%; + margin-top: -0.1rem; + } + + header>.fill>.container>.brand { + font-size: 1.4rem; + position: absolute; + cursor: default; + vertical-align: text-bottom; + text-decoration: none; + color: var(--header-color); + } + + header>.fill>.container>.status { + position: fixed; + top: 9px; + right: 1em; + float: right; + } + + header>.fill>.container>.status>* { + position: relative; + top: 0.2rem; + float: left; + left: -2.5rem; + margin-left: 0.3rem; + cursor: pointer; + } + + header>.fill>.container>.logout { + position: fixed; + top: 9px; + right: 1em; + float: right; + } + + header>.fill>.container>.logout>* { + position: relative; + top: 0.2rem; + float: left; + right: 0rem; + margin-left: 0.3rem; + cursor: pointer; + content: ""; + } + + .logout a { + position: absolute; + right: 14px; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/logout.svg) no-repeat; + text-indent: -9999px; + background-size: 32px; + } + + /* End Header */ + + /* Footer */ + footer { + font-size: 0.8rem; + overflow: hidden; + text-align: center; + white-space: nowrap; + color: #000000; + padding: 1rem; + } + + footer>a { + text-decoration: none; + align-items: center; + color: #e6e6e696; + border-bottom: 0; + background-color: #2222359a; + border-radius: 10px; + padding: 9px; + padding-bottom: 3px; + padding-top: 3px; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + } + + small { + font-size: 90%; + line-height: 1.42857143; + white-space: normal; + } + + /* End Footer */ + + /* Navbar */ + @media screen and (min-width: 720px) { + .navbar { + position: fixed; + bottom: 50%; + transform: translateY(50%); + transition-duration: 200ms; + right: 30px; + border-top: var(--navBorder); + text-align: center; + background-color: #000000da; + box-shadow: 0 0 10px 0px #0000002d; + box-sizing: content-box; + border-radius: 10px; + } + + .navbar--hidden { + transform: translateY(60px); + box-shadow: none; + } + + .navbar .toggler { + transition-duration: 100ms; + position: absolute; + background: #ffffffb0; + box-shadow: 0 0 10px 0 #0000000f; + transform: translateY(50%); + bottom: 50%; + right: calc(100% + 10px); + width: 32px; + height: 32px; + padding: 8px; + border-radius: 100%; + content: ""; + box-sizing: border-box; + cursor: pointer; + } + + .navbar .toggler img { + transform: rotate(270deg); + } + + .navbar .dropdown { + display: flex; + flex-direction: column; + overflow: hidden; + width: 64px; + padding: 0.25rem; + } + + .navbar .dropdown a { + display: block; + text-align: center; + padding: 8px; + text-decoration: none; + max-width: 100px; + width: 100%; + } + + .navbar .dropdown a img { + width: 100%; + } + + .navbar.active { + right: -64px; + } + + .navbar.active .toggler { + right: calc(100% + 10px); + } + + .navbar.active .toggler img { + transform: rotate(90deg); + } + } + + @media screen and (max-width: 720px) { + .navbar { + + overflow: hidden; + position: fixed; + bottom: 5px; + top: auto; + left: 10px; + right: auto; + width: 95%; + align: center; + transition: transform 0.5s; + border-top: var(--navBorder); + text-align: center; + height: calc(50px + constant(safe-area-inset-bottom)); + height: calc(50px + env(safe-area-inset-bottom)); + background-color: #00000079; + border-radius: 20px; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + + } + + .navbar--hidden { + transform: translateY(60px); + box-shadow: none; + } + + .navbar a { + float: left; + text-align: center; + padding: 8px 0; + text-decoration: none; + } + + .navbar a img { + width: 28px; + } + } + + /* End Navbar */ + + .main { + position: relative; + top: 4rem; + bottom: 0; + overflow-y: auto; + height: calc(100% - 4rem); + } + + .main>.loading { + position: fixed; + z-index: 1000; + top: 0; + opacity: 1; + visibility: visible; + width: 100%; + height: 100%; + pointer-events: none; + background-color: rgba(0, 0, 0, 0.781); + transition: .4s ease-in-out; + border-radius: 10px; + } + + .main>.loading>span { + font-family: monospace; + font-size: 2rem; + font-size-adjust: 0.35; + position: relative; + top: 12.5%; + display: block; + text-align: center; + color: #888; + } + + .main>.loading>span>.loading-img { + display: inline-flex; + gap: 10px; + } + + .main>.loading>span>.loading-img:before, + .loading-img:after { + content: ""; + height: 20px; + aspect-ratio: 1; + border-radius: 50%; + background: + linear-gradient(#222 0 0) top/100% 0% no-repeat, + radial-gradient(farthest-side, #000 95%, #0000) 50%/8px 8px no-repeat #ffffff; + animation: l9 4s infinite ease-in; + } + + @keyframes l9 { + 0% { + background-size: 100% 0%, 8px 8px; + background-position: top, 50% 50% + } + + 80% { + background-size: 100% 70%, 8px 8px; + background-position: top, 50% 70% + } + + 84%, + 100% { + background-size: 100% 0%, 8px 8px; + background-position: top, 50% 50% + } + } + + .cbi-map { + margin-top: 10px; + } + + #cbi-shadowsocksr .cbi-map-descr { + display: none; + } + + strong { + font-weight: bold; + color: rgb(255, 255, 255); + } + + .main-right { + float: right; + width: calc(100% - 16rem); + height: 100%; + } + + .nowrap:not(.td) { + white-space: nowrap; + color: #ffffff; + } + + [disabled="disabled"] { + pointer-events: none; + } + + /* Sidebar */ + .main>.main-left { + position: fixed; + top: 4.8rem; + width: calc(0% + 16rem); + float: left; + overflow-x: auto; + background-color: #2222359a; + transition: visibility 400ms, width 400ms; + border-top-left-radius: 0px; + border-top-right-radius: 20px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 20px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + height: calc(100% - 3.5rem); + + } + + .main>.main-left>.nav { + padding: 0.5rem 0.5rem 2rem; + } + + .main>.main-left>.nav>li { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .main>.main-left>.nav>li>[data-title="Log out"], + .main>.main-left>.nav>li>[data-title="Logout"] { + display: flex; + padding: 0.5rem 1rem; + } + + .main>.main-left>.nav>li a { + display: block; + color: #cbcbcb; + } + + .main>.main-left>.nav>li>[data-title="Log out"], + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"] { + font-size: 1rem; + color: #fff; + } + + .main>.main-left>.nav>li.slide.active { + background-color: unset; + } + + .main>.main-left>.nav>.slide { + padding: 0; + } + + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"], + .main>.main-left>.nav>li>[data-title="Dashboard"] { + font-size: 1rem; + font-weight: 500; + display: flex; + align-items: center; + width: 100%; + text-decoration: none; + color: #fff; + padding: 0.5rem 1rem; + transition-duration: 200ms; + margin-bottom: 5px; + } + + .main>.main-left>.nav>.slide>.menu::before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/app.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>.menu.active::before {} + + .main>.main-left>.nav>.slide>[data-title="Status"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/status.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="System"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/system.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Services"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/services.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="NAS"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/nas.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Modem"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/modem.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Network"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/network.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="VPN"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/vpn.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Docker"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/docker.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>li>[data-title="iStore"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/istore.svg) no-repeat; + background-size: 25px; + } + + /* End Sidebar */ + + .modemenu-buttons { + display: flex; + flex-wrap: wrap; + align-items: center; + color: var(--header-color); + background: var(--header-bg); + transition: box-shadow 0.2s; + box-shadow: 0 2px 5px rgb(0 0 0 / 26%); + padding: 0.5rem; + } + + #modemenu { + display: flex; + align-items: center; + flex-wrap: wrap; + margin: 0.25rem; + } + + #modemenu>li.divider { + margin-left: 0.25rem; + margin-right: 0.25rem; + border: 0.5rem solid var(--submenu-bg-hover); + border-left: 1px solid var(--submenu-bg-hover); + border-right: 1px solid var(--submenu-bg-hover); + border-radius: 1rem; + } + + .danger { + background-color: #ff7d60 !important; + } + + .warning { + background-color: #bebebe87 !important; + border-radius: 10px; + color: #fff; + } + + .success { + background-color: #5cb85c !important; + } + + .error { + color: red; + } + + .alert, + .alert-message { + font-weight: 700; + margin-bottom: 1em; + border: 0; + border-radius: 20px; + background-color: #2222359a; + padding: 1rem; + margin: 1rem; + } + + .alert-message>h4 { + font-size: 110%; + font-weight: 700; + } + + .alert-message>* { + margin: 0.5rem 0; + } + + body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { + transition: transform 0.1s ease-in-out; + } + + body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { + transition: transform 0.2s ease-in-out; + } + + .main>.main-left>.nav>li>[data-title="Logout"]::before, + .main>.main-left>.nav>li>[data-title="Log out"]::before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/logout.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide:hover { + background: none; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a { + white-space: nowrap; + text-decoration: none; + padding: 0.4rem 2rem; + } + + .main>.main-left>.nav>.slide>.slide-menu>li:not(.active):hover>a { + color: #fff; + } + + .main>.main-left>.nav>.slide>.slide-menu>.active:hover { + background-color: var(--main-color); + } + + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>.slide>.slide-menu>li, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="Log out"], + .main>.main-left>.nav>li>[data-title="iStore"] { + position: relative; + overflow: hidden; + transform: translate3d(0, 0, 0); + } + + .main>.main-left>.nav>.slide>.menu::after, + .main>.main-left>.nav>.slide>.slide-menu>li::after, + .main>.main-left>.nav>li>[data-title="Logout"]::after, + .main>.main-left>.nav>li>[data-title="Log out"]::after, + .main>.main-left>.nav>li>[data-title="iStore"]::after { + position: absolute; + top: 0; + left: 0; + display: block; + width: 100%; + height: 100%; + content: ""; + transition: transform 0.5s, opacity 1s; + transform: scale(10, 10); + pointer-events: none; + opacity: 0; + background-image: radial-gradient(circle, #000 10%, transparent 10.01%); + background-repeat: no-repeat; + background-position: 50%; + } + + .main>.main-left>.nav>.slide>.menu:active::after, + .main>.main-left>.nav>.slide>.slide-menu>li:active::after, + .main>.main-left>.nav>li>[data-title="Logout"]:active::after, + .main>.main-left>.nav>li>[data-title="Log out"]:active::after, + .main>.main-left>.nav>li>[data-title="iStore"]:active::after { + transition: 0s; + transform: scale(0, 0); + opacity: 0.2; + } + + #maincontent>.container { + margin: 0 2rem 1rem; + } + + ul { + line-height: normal; + } + + li { + list-style-type: none; + } + + h1 { + font-size: 2rem; + padding-bottom: 10px; + border-bottom: thin solid #eee; + } + + h2 { + font-size: 1.8rem; + font-family: "Quicksand-Bold"; + letter-spacing: 5px; + text-align: center; + padding-bottom: 10px; + margin: 2rem 0 0; + color: #ffffff; + animation-duration: 1s; + animation-name: down; + } + + h3 { + font-size: 1.2rem; + font-family: 'Inter-Bold'; + letter-spacing: 2px; + padding-bottom: 10px; + margin: 2rem 0 0; + color: #ffffff; + } + + h4 { + font-size: 1.2rem; + color: #fff; + padding-bottom: 10px; + margin: 2rem 0 0; + } + + h5 { + font-size: 1rem; + padding-bottom: 10px; + margin: 2rem 0 0; + } + + .cbi-tab-descr { + color: #09c; + margin: 1em; + padding: 1rem; + } + + #tabmenu { + padding: 0; + } + + .cbi-section, + .cbi-section-error, + #iptables, + .Firewall form, + #cbi-network>.cbi-section-node, + #cbi-wireless>.cbi-section-node, + #cbi-wireless>#wifi_assoclist_table, + [data-tab-title], + [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), + [data-page="admin-system-opkg"] #maincontent>.container { + font-family: inherit; + font-weight: 400; + font-style: normal; + line-height: normal; + min-width: inherit; + border: 0; + border-radius: 0; + background-color: #2222359a; + margin: 1rem 0 0; + padding: 2rem; + border-radius: 20px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + } + + .cbi-modal .cbi-section, + .cbi-section .cbi-section {} + + .cbi-modal .cbi-tabmenu { + margin-left: 0; + } + + .cbi-map-descr, + .cbi-section-descr { + font-size: small; + text-align: center; + line-height: 1.42857143; + color: #999; + padding: 0.5rem; + } + + .cbi-section>legend { + display: none !important; + } + + fieldset>fieldset, + .cbi-section>.cbi-section { + border: 0; + box-shadow: none; + margin: 0; + padding: 0; + } + + .cbi-section>h3:first-child, + .panel-title { + font-size: 1.4rem; + line-height: 1; + display: block; + width: 100%; + padding-bottom: 1rem; + color: #e4e4e4; + border-bottom: thin solid #eeeeee00; + margin: 0 0 0.5rem; + } + + .cbi-section>h4:first-child, + .cbi-section>p:first-child, + [data-tab-title]>h3:first-child, + [data-tab-title]>h4:first-child, + [data-tab-title]>p:first-child { + padding-top: 1rem; + } + + table { + border-spacing: 0; + border-collapse: collapse; + } + + table, + .table { + overflow-y: hidden; + width: 100%; + border-radius: 10px; + } + + .container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { + padding: 0.6rem; + } + + .cbi-section-table-cell { + line-height: 1.1; + align-self: flex-end; + flex: 1 1 auto; + } + + tr>td, + tr>th, + .tr>.td, + .tr>.th, + .cbi-section-table-row::before, + #cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { + color: #ffffff; + border-top: thin solid rgba(255, 255, 255, 0); + } + + .table[width="100%"]>.tr:first-child>.td { + margin: auto 0; + } + + .cbi-section-table-row { + margin-bottom: 1rem; + text-align: center !important; + } + + .cbi-section-table-row:last-child { + margin-bottom: 0; + } + + .cbi-section-table-row>.cbi-value-field [data-dynlist]>input, + .cbi-section-table-row>.cbi-value-field input.cbi-input-password { + width: calc(100% - 1.5rem); + } + + table table, + .table .table, + .cbi-value-field table, + .cbi-value-field .table, + td>table>tbody>tr>td, + .td>.table>.tbody>.tr>.td, + .cbi-value-field>table>tbody>tr>td, + .cbi-value-field>.table>.tbody>.tr>.td { + border: 0; + } + + .btn, + .cbi-button, + .item::after { + font-size: 0.8rem; + display: inline-block; + width: auto !important; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all 0.2s ease-in-out; + text-align: center; + vertical-align: middle; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: rgba(0, 0, 0, 0.87); + border: 0; + background-color: #f0f0f0; + background-image: none; + -webkit-appearance: none; + -ms-touch-action: manipulation; + touch-action: manipulation; + padding: 0 0.8rem; + } + + .cbi-button-up { + transform: scaleY(-1); + } + + .cbi-button:not(select) { + -webkit-appearance: none !important; + } + + .cbi-button+.cbi-button { + margin-left: 0.6rem; + } + + .btn:hover, + .btn:focus, + .btn:active, + .cbi-button:hover, + .cbi-button:focus, + .cbi-button:active, + .item:hover::after, + .item:focus::after, + .item:active::after, + .cbi-page-actions .cbi-button-apply+.cbi-button-save:hover, + .cbi-page-actions .cbi-button-apply+.cbi-button-save:focus, + .cbi-page-actions .cbi-button-apply+.cbi-button-save:active { + text-decoration: none; + outline: 0; + } + + .btn:hover, + .btn:focus, + .cbi-button:hover, + .cbi-button:focus, + .item:hover::after, + .item:focus::after { + box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 2px rgba(0, 0, 0, 0.2); + } + + .btn:active, + .cbi-button:active, + .item:active::after { + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); + } + + .cbi-button-up:hover, + .cbi-button-up:focus { + box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 -2px 2px rgba(0, 0, 0, 0.2); + } + + .cbi-button-up:active { + box-shadow: 0 -10px 20px rgba(0, 0, 0, 0.19), 0 -6px 6px rgba(0, 0, 0, 0.23); + } + + .btn:disabled, + .cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: 0.5; + box-shadow: none; + } + + .alert-message [class="btn"], + .modal div[class="btn"], + .cbi-button-find, + .cbi-button-link, + .cbi-button-up, + .cbi-button-down, + .cbi-button-neutral, + .cbi-button[name="zero"], + .cbi-button[name="restart"], + .cbi-button[onclick="hide_empty(this)"] { + font-weight: 700; + background-color: #d4d4d4; + } + + .btn.primary, + .cbi-page-actions .cbi-button-save, + .cbi-page-actions .cbi-button-apply+.cbi-button-save, + .cbi-button-add, + .cbi-button-save, + .cbi-button-positive, + .cbi-button-link, + .cbi-button[value="Enable"], + .cbi-button[value="Scan"], + .cbi-button[value^="Back"], + .cbi-button-neutral[onclick="handleConfig(event)"] { + font-weight: 400; + color: #fff; + background-color: rgba(0, 229, 255, 0.47); + border-radius: 20px; + } + + .cbi-page-actions .cbi-button-apply, + .cbi-section-actions .cbi-button-edit, + .cbi-button-edit, + .cbi-button-apply, + .cbi-button-reload, + .cbi-button-action, + .cbi-button[value="Submit"], + .cbi-button[value="Upload"], + .cbi-button[value$="Apply"], + .cbi-button[onclick="addKey(event)"] { + font-weight: 400; + color: #fff; + background-color: rgba(0, 229, 255, 0.47); + border-radius: 20px; + } + + .btn.danger, + .cbi-section-remove>.cbi-button, + .cbi-button-remove, + .cbi-button-reset, + .cbi-button-negative, + .cbi-button[value="Stop"], + .cbi-button[value="Kill"], + .cbi-button[onclick="reboot(this)"], + .cbi-button-neutral[value="Restart"] { + font-weight: 400; + color: #fff; + background-color: rgba(255, 0, 0, 0.47); + border-radius: 20px; + } + + .btn[value="Dismiss"], + .cbi-button[value="Terminate"], + .cbi-button[value="Reset"], + .cbi-button[value="Disabled"], + .cbi-button[onclick^="iface_reconnect"], + .cbi-button[onclick="handleReset(event)"], + .cbi-button-neutral[value="Disable"] { + font-weight: 400; + color: #fff; + border: thin solid #eea236; + background-color: #f0ad4e; + } + + .cbi-button-success, + .cbi-button-download, + .cbi-button[name="backup"], + .cbi-button[value="Download"], + .cbi-button[value="Save mtdblock"] { + font-weight: 400; + color: #fff; + border: thin solid #4cae4c; + background-color: #5cb85c; + } + + .a-to-btn { + text-decoration: none; + } + + .cbi-value-field .cbi-button-add { + font-weight: 700; + margin: 9px 0 4px 3px; + padding: 1px 6px; + } + + .tabs { + border-bottom: 0; + background-color: #2222359a; + border-radius: 20px; + padding: 9px; + padding-bottom: 3px; + padding-top: 3px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + } + + .tabs>li, + .cbi-tabmenu>li { + display: inline-block; + cursor: pointer; + padding: 0.4rem; + margin: 0.3rem; + align-items: center; + + } + + .tool_label_span { + color: aqua; + } + + .tabs>li { + padding-bottom: 0.4rem; + } + + .tabs>li[class~="active"], + .tabs>li:hover { + border-bottom-color: var(--main-color); + } + + .tabs>li:hover { + cursor: pointer; + border-bottom-color: #c9c9c9; + } + + .tabs>li>a, + .cbi-tabmenu>li>a { + text-decoration: none; + color: #ffffff; + padding: 0.6rem 0.9rem; + + } + + .tabs>li[class~="active"]>a { + color: var(--main-color); + } + + .cbi-tabmenu { + border-bottom: 0; + background-color: #2222359a; + border-radius: 20px; + padding: 9px; + padding-bottom: 3px; + padding-top: 3px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + } + + .cbi-tabmenu>li:hover { + background-color: #474747; + border-radius: 20px; + + + } + + .cbi-tabmenu>li[class~="cbi-tab"] { + background-color: #ff94946a; + border-radius: 20px; + } + + .cbi-tabmenu>li[class~=data-tab=] { + color: #ffffff; + } + + [data-tab-title] { + overflow: hidden; + height: 0; + opacity: 0; + margin: 0; + padding: 0rem 1rem !important; + } + + [data-tab-active="true"] { + overflow: visible; + height: auto; + opacity: 1; + transition: opacity 0.25s ease-in; + margin: inherit !important; + } + + .cbi-section-node-tabbed { + margin-top: 0; + border-top: 0; + padding: 0; + } + + .cbi-value-field, + .cbi-value-description { + line-height: 1.25; + display: table-cell; + } + + .cbi-value-description { + font-size: small; + padding-top: 0.4rem; + opacity: 0.5; + color: #fff; + } + + .cbi-value-title { + display: table-cell; + float: left; + width: 23rem; + padding-top: 0.35rem; + padding-right: 2rem; + text-align: right; + word-wrap: break-word; + } + + .cbi-value { + display: inline-block; + width: 100%; + padding: 0.35rem 1rem 0.2rem; + } + + .cbi-value ul { + line-height: 1.25; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 25rem; + } + + #cbi-firewall-zone .cbi-input-select, + #cbi-network-switch_vlan .cbi-input-select { + min-width: 11rem; + } + + #cbi-network-switch_vlan .cbi-input-text { + max-width: 3rem; + } + + .cbi-input-invalid { + color: red; + border-bottom-color: red; + } + + .cbi-section-error { + font-weight: 700; + line-height: 1.42857143; + border: thin solid red; + border-radius: 3px; + background-color: #fce6e6; + margin: 18px; + padding: 6px; + } + + .cbi-section-error ul { + margin: 0 0 0 20px; + } + + .cbi-section-error ul li { + font-weight: 700; + color: red; + } + + .td[data-title]::before { + font-weight: 700; + display: none; + content: attr(data-title) ":\20"; + text-align: left; + white-space: nowrap; + padding: 0.25rem 0; + } + + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-weight: 700; + display: table-cell; + align-self: center; + flex: 1 1 5%; + content: attr(data-title) "\20"; + text-align: center; + vertical-align: middle; + white-space: normal; + word-wrap: break-word; + padding: 0.25rem; + } + + .cbi-rowstyle-2 .cbi-button-up, + .cbi-rowstyle-2 .cbi-button-down, + body:not(.Interfaces) .cbi-rowstyle-2:first-child {} + + .cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; + } + + .td.cbi-section-actions { + text-align: right !important; + vertical-align: middle; + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 5px; + } + + .td.cbi-section-actions>* { + display: inline-flex; + } + + .td.cbi-section-actions>button { + display: block; + } + + .td.cbi-section-actions>*>*, + .td.cbi-section-actions>*>form>* { + margin: 0 5px; + } + + .td.cbi-section-actions>*>form { + display: inline-flex; + margin: 0; + } + + .cbi-dynlist { + line-height: 1.3; + flex-direction: column; + min-height: 30px; + cursor: text; + } + + .cbi-dynlist>.item { + position: relative; + max-width: 25rem; + margin-right: 2em; + pointer-events: none; + color: #666; + border-bottom: 2px solid rgba(0, 0, 0, 0.26); + outline: 0; + padding: 0.5em 0.25em 0.25em 0; + } + + .cbi-dynlist[name="sshkeys"]>.item { + max-width: none; + } + + .cbi-dynlist>.item::after { + font-weight: 700; + position: absolute; + right: -2em; + bottom: 0; + display: inline-flex; + min-height: 17px; + content: "\00D7"; + pointer-events: auto; + color: #fff; + border: thin solid #d43f3a; + background-color: #d9534f; + padding: 0 6px; + border-radius: 5px; + } + + .cbi-dynlist>.item>span { + white-space: normal; + word-break: break-word; + } + + .cbi-dynlist>.add-item { + display: inline-flex; + align-items: center; + width: 100%; + min-width: 16rem; + } + + .cbi-dynlist>.add-item:not([ondrop])>input { + overflow: hidden; + width: 100%; + min-width: 15rem; + white-space: nowrap; + text-overflow: ellipsis; + } + + .cbi-dynlist>.add-item[ondrop]>input { + min-width: 13rem; + } + + .cbi-dynlist, + .cbi-dropdown { + position: relative; + display: inline-flex; + padding: 0; + } + + .cbi-dropdown[placeholder*="select"] { + max-width: 25rem; + height: auto; + margin-top: -3px; + } + + .cbi-dropdown>ul { + display: flex; + overflow-x: hidden; + overflow-y: auto; + width: 100%; + list-style: none; + outline: 0; + margin: 0 !important; + padding: 0; + } + + .cbi-dropdown>.open { + flex-basis: 15px; + } + + .cbi-dropdown>.open, + .cbi-dropdown>.more { + font-size: 1rem; + font-weight: 900; + line-height: 2; + display: flex; + flex-direction: column; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + cursor: default; + text-align: center; + outline: 0; + padding: 0 0.25em; + } + + .cbi-dropdown.btn { + min-height: 1.8rem; + padding-top: 0px; + padding-bottom: 0px; + padding-right: 0px; + } + + .cbi-dropdown.btn>.open { + font-size: 0.8rem; + margin: 0 5px; + padding: 0px; + } + + .cbi-dropdown.btn>div { + margin: 0px; + } + + .cbi-dropdown>.more, + .cbi-dropdown>ul>li[placeholder] { + font-weight: 700; + display: none; + color: #777; + } + + .cbi-dropdown>ul>li { + display: none; + overflow: hidden; + align-items: center; + align-self: center; + flex-grow: 1; + flex-shrink: 1; + min-height: 20px; + white-space: nowrap; + text-overflow: ellipsis; + padding: 0.3rem 1rem 0.3rem 1rem; + } + + .cbi-dropdown>ul>li[display]:not([display="0"]) { + border-left: thin solid #ccc; + } + + .cbi-dropdown[empty]>ul { + max-width: 1px; + } + + .cbi-dropdown>ul>li>form { + display: none; + pointer-events: none; + margin: 0; + padding: 0; + } + + .cbi-dropdown>ul>li img { + margin-right: 0.25em; + vertical-align: middle; + } + + .cbi-dropdown>ul>li>form>input[type="checkbox"] { + height: auto; + margin: 0; + } + + .cbi-dropdown>ul>li input[type="text"] { + height: 20px; + } + + .cbi-dropdown[open]>ul.dropdown { + position: absolute; + z-index: 1100; + display: block; + width: auto; + min-width: 100%; + max-width: none; + max-height: 200px !important; + border: thin solid #918e8c; + background: #787878a8; + box-shadow: 0 0 4px #918e8c; + color: var(--main-menu-color); + } + + .cbi-dropdown>ul>li[display], + .cbi-dropdown[open]>ul.preview, + .cbi-dropdown[open]>ul.dropdown>li, + .cbi-dropdown[multiple]>ul>li>label, + .cbi-dropdown[multiple][open]>ul.dropdown>li, + .cbi-dropdown[multiple][more]>.more, + .cbi-dropdown[multiple][empty]>.more { + display: flex; + align-items: center; + flex-grow: 1; + justify-content: space-around; + } + + .cbi-dropdown[open]>ul.dropdown>li {} + + .cbi-dropdown[open]>ul.dropdown>li[selected] { + background: #b0d0f0; + } + + .cbi-dropdown[open]>ul.dropdown>li.focus { + background: linear-gradient(90deg, #a3c2e8 0%, #84aad9 100%); + } + + .cbi-dropdown[open]>ul.dropdown>li:last-child { + margin-bottom: 0; + } + + .cbi-dropdown[open]>ul.dropdown>li[unselectable] { + opacity: 0.7; + } + + .cbi-dropdown[disabled] { + pointer-events: none; + opacity: 0.6; + } + + .cbi-dropdown[open] .zonebadge { + width: auto; + } + + .cbi-progressbar { + border-radius: 15px; + overflow: hidden; + position: relative; + min-width: 170px; + height: 30px; + background: #11111d61; + margin: 6px 0; + } + + .cbi-progressbar title { + font-family: "Quicksand-Bold"; + letter-spacing: 5px; + text-align: center; + padding-bottom: 10px; + margin: 2rem 0 0; + color: #ffffff; + } + + .cbi-progressbar>div { + width: 0; + height: 100%; + transition: width 2s ease-in; + background: #0099cc; + padding: 0.5rem; + } + + .cbi-progressbar::after { + font-family: monospace; + font-size: 1.2em; + font-weight: 700; + font-size-adjust: 0.38; + line-height: normal; + position: absolute; + top: 50%; + transform: translateY(-50%); + right: 0; + left: 0; + overflow: hidden; + content: attr(title); + text-align: center; + white-space: pre; + text-overflow: ellipsis; + text-shadow: 0 0 2px #eee; + } + + #modal_overlay { + position: fixed; + z-index: 900; + top: 4rem; + right: 10000px; + bottom: 0; + left: -10000px; + overflow-y: scroll; + transition: opacity 0.125s ease-in; + opacity: 0; + background: rgba(0, 0, 0, 0.7); + -webkit-overflow-scrolling: touch; + } + + .modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 90%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + border-radius: 20px !important; + background: #8f8f8f75; + margin: 5em auto; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + padding: 1em; + + } + + .modal>* { + line-height: normal; + flex-basis: 100%; + margin-bottom: 0.5em; + max-width: 100%; + } + + .modal>pre, + .modal>textarea { + font-size: 1rem; + font-size-adjust: 0.35; + overflow: auto; + margin-bottom: 0.5em; + cursor: auto; + white-space: pre-wrap; + color: #eee; + outline: 0; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 8.5px; + } + + .modal>h4 { + margin: 0.5em 0; + } + + .modal ul { + margin-left: 2.2em; + } + + .modal li { + list-style-type: square; + color: rgb(216, 216, 216); + } + + .modal p { + padding-left: 0.25rem; + word-break: break-word; + } + + .modal .label { + font-size: 0.6rem; + font-weight: 400; + cursor: default; + border-radius: 0; + padding: 0.1rem 0.3rem 0; + } + + .modal .label.warning { + background-color: #f0ad4e !important; + } + + .modal.cbi-modal { + max-width: 90%; + max-height: none; + } + + body.modal-overlay-active { + overflow: hidden; + height: 100vh; + } + + body.modal-overlay-active #modal_overlay { + right: 0; + left: 0; + opacity: 1; + } + + .spinning { + position: relative; + align-items: center; + padding-left: 32px !important; + color: #fff; + } + + .spinning::before { + position: absolute; + font-size: medium; + font-style: "Quicksand-Bold"; + left: 8px; + width: 16px; + height: 16px; + content: ""; + animation: anim-rotate 2s infinite cubic-bezier(0.18, 0.89, 0.32, 1.28); + background: url(./icon/loading.svg) no-repeat center; + background-size: 20px; + } + + .left, + .left::before { + text-align: left !important; + } + + .right, + .right::before { + text-align: right !important; + } + + .top { + align-self: flex-start !important; + vertical-align: top !important; + } + + .bottom { + align-self: flex-end !important; + vertical-align: bottom !important; + } + + .inline { + display: inline; + } + + .cbi-page-actions { + padding-top: 1rem; + text-align: center; + } + + .cbi-page-actions>form[method="post"] { + display: inline-block; + } + + .th[data-type="button"], + .td[data-type="button"], + .th[data-type="fvalue"], + .td[data-type="fvalue"] { + flex: 1 1 2em; + text-align: center; + } + + .ifacebadge { + display: inline-flex; + background: #ffffff33; + padding: 0.5rem 0.8rem; + border-radius: 10px; + } + + td>.ifacebadge, + .td>.ifacebadge { + font-size: 0.8rem; + background-color: #000000; + border-radius: 10px; + } + + .ifacebadge>em, + .ifacebadge>img { + display: inline-block; + align-self: flex-start; + margin: 0 0.2rem; + } + + .ifacebadge>img+img { + margin: 0 0.2rem 0 0; + } + + .network-status-table .ifacebox { + flex-grow: 1; + margin: 0.5em; + } + + .network-status-table .ifacebox-body { + display: flex; + flex-direction: column; + height: 100%; + } + + .network-status-table .ifacebox-body>span { + flex: 10 10 auto; + height: 100%; + } + + .network-status-table .ifacebox-body .ifacebadge { + align-items: center; + flex: 1 1 auto; + min-width: 220px; + background-color: #11111d; + margin: 0.5em 0.25em 0; + padding: 0.5em; + border-radius: 10px; + } + + .cbi-input-textarea { + font-family: monospace; + width: 100%; + min-height: 14rem; + color: #000; + padding: 0.8rem; + } + + #syslog { + font-size: small; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + resize: none; + color: #eee; + border: 0; + border-radius: 20px; + background-color: #10101057; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 1rem; + } + + #syslog:focus { + outline: 0; + } + + .uci-change-list { + font-family: monospace; + } + + .uci-change-list ins, + .uci-change-legend-label ins { + display: block; + text-decoration: none; + border: thin solid #0f0; + background-color: #cfc; + padding: 2px; + } + + .uci-change-list del, + .uci-change-legend-label del { + font-style: normal; + display: block; + text-decoration: none; + border: thin solid red; + background-color: #fcc; + padding: 2px; + } + + .uci-change-list var, + .uci-change-legend-label var { + font-style: normal; + display: block; + text-decoration: none; + border: thin solid #ccc; + background-color: #eee; + padding: 2px; + } + + .uci-change-list var ins, + .uci-change-list var del { + font-style: normal; + white-space: pre; + border: 0; + padding: 0; + } + + .uci-change-legend { + padding: 5px; + } + + .uci-change-legend-label { + float: left; + width: 150px; + color: #fff; + } + + .uci-change-legend-label>ins, + .uci-change-legend-label>del, + .uci-change-legend-label>var { + display: block; + float: left; + width: 10px; + height: 10px; + margin-right: 4px; + } + + .uci-change-legend-label var ins, + .uci-change-legend-label var del { + line-height: 0.4; + border: 0; + } + + #iwsvg, + #iwsvg2, + #bwsvg { + border: thin solid #d4d4d4 !important; + } + + .ifacebox { + line-height: 1.25; + display: inline-flex; + flex-direction: column; + min-width: 100px; + background-color: #54545450; + border-radius: 20px; + flex-wrap: nowrap; + align-content: center; + justify-content: flex-start; + align-items: center; + color: #fff; + } + + div.ifacebox-head { + --zone-color-rgb: 144, 240, 144; + background-color: rgb(43, 79, 43); + } + + style attribute { + --zone-color-rgb: 144, 240, 144; + background-color: rgb(43, 79, 43); + } + + .ifacebox-head { + background: #939393; + padding: 0.25em; + color: #fff; + } + + .ifacebox-head.active { + background: var(--bar-bg); + } + + .ifacebox-body { + padding: 0.25em; + } + + .cbi-image-button { + margin-left: 0.5rem; + } + + .zonebadge { + display: inline-block; + padding: 0.2rem 0.5rem; + } + + .zonebadge .ifacebadge { + border: thin solid #6c6c6c; + margin: 0.1rem 0.2rem; + padding: 0.2rem 0.3rem; + } + + .zonebadge>input[type="text"] { + min-width: 10rem; + margin-top: 0.3rem; + padding: 0.16rem 1rem; + } + + .zonebadge>em, + .zonebadge>strong { + display: inline-block; + margin: 0 0.2rem; + } + + .cbi-value-field .cbi-input-checkbox, + .cbi-value-field .cbi-input-radio { + margin-top: 0.1rem; + } + + .cbi-value-field>ul>li .ifacebadge { + margin-top: -0.5rem; + margin-left: 0.4rem; + background-color: #eee; + } + + .cbi-section-table-row>.cbi-value-field .cbi-dropdown { + min-width: 7rem; + } + + .cbi-section-create { + display: inline-flex; + align-items: center; + margin: 0.5rem -3px; + } + + .cbi-section-create>* { + margin: 0.5rem; + } + + div.cbi-value var, + td.cbi-value-field var, + .td.cbi-value-field var { + font-style: italic; + color: #0069d6; + } + + .cbi-optionals { + border-top: thin solid #ccc; + padding: 1rem 1rem 0; + } + + .cbi-dropdown-container { + position: relative; + } + + .cbi-tooltip-container, + span[data-tooltip], + span[data-tooltip] .label { + cursor: help !important; + text-align: left !important; + font-size: 80% !important; + color: #fff !important; + } + + .cbi-tooltip { + position: absolute; + z-index: 1000; + left: -1000px; + transition: opacity 0.25s ease-out; + white-space: pre; + pointer-events: none; + opacity: 0; + border-radius: 20px; + background: #54545450; + box-shadow: 0 0 2px #444; + padding: 2px 5px; + -webkit-backdrop-filter: blur(20px); + backdrop-filter: blur(20px); + + } + + .cbi-tooltip-container:hover .cbi-tooltip { + left: auto; + transition: opacity 0.25s ease-in; + opacity: 1; + } + + .zonebadge .cbi-tooltip { + background: inherit; + margin: -1.5rem 0 0 -0.5rem; + padding: 0.25rem; + } + + .zonebadge-empty { + color: #404040; + background: repeating-linear-gradient(45deg, + rgba(204, 204, 204, 0.5), + rgba(204, 204, 204, 0.5) 5px, + rgba(255, 255, 255, 0.5) 5px, + rgba(255, 255, 255, 0.5) 10px); + } + + .zone-forwards { + display: flex; + min-width: 10rem; + } + + .zone-forwards>* { + flex: 1 1 45%; + } + + .zone-forwards>span { + flex-basis: 10%; + text-align: center; + padding: 0 0.25rem; + } + + .zone-forwards .zone-src, + .zone-forwards .zone-dest { + display: flex; + flex-direction: column; + } + + label>input[type="checkbox"], + label>input[type="radio"] { + position: relative; + top: 0.4rem; + right: 0.2rem; + vertical-align: bottom; + margin: 0; + } + + label[data-index][data-depends] { + padding-right: 2em; + } + + .darkMask { + position: fixed; + z-index: 99; + width: 100%; + height: 100%; + content: ""; + transition: opacity 400ms, visibility 400ms; + visibility: hidden; + opacity: 0; + background-color: #2222359a; + } + + #diag-rc-output>pre, + #command-rc-output>pre, + [data-page="admin-services-wol"] .notice code { + font-size: 1.2rem; + font-size-adjust: 0.35; + line-height: normal; + display: block; + overflow-y: hidden; + width: 100%; + white-space: pre; + color: #eee; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 8.5px; + } + + input[name="ping"], + input[name="traceroute"], + input[name="nslookup"] { + width: 80%; + } + + .node-main-login>.main fieldset { + display: inline; + overflow: hidden; + margin-bottom: 1rem; + border: 0; + background: none; + box-shadow: none; + padding: 0.5rem; + } + + .node-main-login>.main .cbi-value-title { + width: 9.5rem; + } + + .node-main-login>.main #maincontent { + text-align: center; + } + + .node-main-login>.main .container { + display: inline-block; + margin-top: 2rem !important; + text-align: left; + background-color: #2e2b2b00; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 1rem 3.5rem 2rem; + } + + .node-main-login>.main .cbi-value>* { + display: inline-block !important; + } + + .node-main-login>.main .cbi-input-text { + width: 100% !important; + min-width: 15rem; + } + + .node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2), + .node-status-processes>.main .table .tr .td:nth-child(3) { + white-space: normal; + } + + [data-page="admin-system-reboot"] p { + padding-left: 2rem; + } + + [data-page="admin-system-reboot"] p>span { + position: relative; + top: 0.1rem; + left: 1rem; + } + + #cbi-samba [data-tab="template"] .cbi-value-title { + width: auto; + padding-bottom: 0.6rem; + } + + .controls>*>.btn:not([aria-label$="page"]) { + flex-grow: initial !important; + margin-top: 0.1rem; + } + + .controls>#pager>.btn[aria-label$="page"] { + font-size: 1.4rem; + font-weight: 700; + } + + .controls>*>label { + margin-bottom: 0.2rem; + } + + [data-page="admin-system-opkg"] div.btn { + display: inline; + padding: 0.3rem 0.6rem; + } + + [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), + [data-page="admin-system-opkg"] #maincontent>.container { + margin-top: 2rem; + padding-top: 0.1rem; + } + + [data-page="admin-system-opkg"] #maincontent>.container { + margin: 2rem 2rem 1rem; + } + + .td.version, + .td.size { + white-space: normal !important; + word-break: break-word; + } + + .cbi-tabmenu+.cbi-section { + margin-top: 0; + } + + #cbi-wireless>#wifi_assoclist_table>.tr { + box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; + } + + #cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { + right: 33px; + bottom: 33px; + left: 33px; + border-top: thin solid #ddd !important; + } + + #cbi-wireless>#wifi_assoclist_table>.tr.table-titles { + box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; + } + + #cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { + border-bottom: thin solid #ddd; + box-shadow: 0 -1px 0 0 #ddd; + } + + #wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { + width: 23rem; + } + + #iptables { + margin: 0; + } + + .Firewall form { + box-shadow: none; + margin: 2rem 2rem 0 0; + padding: 0; + } + + #cbi-firewall-redirect table *, + #cbi-network-switch_vlan table *, + #cbi-firewall-zone table * { + font-size: small; + } + + #cbi-firewall-redirect table input[type="text"], + #cbi-network-switch_vlan table input[type="text"], + #cbi-firewall-zone table input[type="text"] { + width: 5rem; + } + + #cbi-firewall-redirect table select, + #cbi-network-switch_vlan table select, + #cbi-firewall-zone table select { + min-width: 3.5rem; + } + + #cbi-network-switch_vlan .th, + #cbi-network-switch_vlan .td { + flex-basis: 12%; + } + + #applyreboot-container { + margin: 2rem; + } + + #applyreboot-section { + line-height: 300%; + margin: 2rem; + } + + .OpenVPN a { + line-height: initial !important; + } + + .commandbox { + width: 24% !important; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), + 0 1px 2px rgba(0, 0, 0, 0.05); + margin: 10px 0 0 10px !important; + padding: 0.5rem 1rem; + } + + .commandbox h3 { + line-height: normal !important; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin: 6px 0 !important; + } + + .commandbox div { + left: auto !important; + } + + .commandbox code { + position: absolute; + overflow: hidden; + max-width: 60%; + margin-left: 4px; + white-space: nowrap; + text-overflow: ellipsis; + padding: 2px 3px; + } + + .commandbox code:hover { + overflow-y: auto; + max-height: 50px; + white-space: normal; + } + + .commandbox p:first-of-type { + margin-top: -6px; + } + + .commandbox p:nth-of-type(2) { + margin-top: 2px; + } + + #command-rc-output .alert-message { + line-height: 1.42857143; + position: absolute; + top: 40px; + right: 32px; + max-width: 40%; + animation: anim-fade-in 1.5s forwards; + word-break: break-word; + opacity: 0; + margin: 0; + } + + .table[width="100%"], + .th[width="100%"], + .td[width="100%"], + .cbi-section-table-row>.cbi-value-field .cbi-dropdown, + .cbi-section-table-row>.cbi-value-field .cbi-input-select, + .cbi-section-table-row>.cbi-value-field .cbi-input-text, + .cbi-section-table-row>.cbi-value-field .cbi-input-password, + .cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child, + .cbi-dropdown .zonebadge, + .node-main-login>.main>.main-right, + #cbi-firewall-zone .td, + #cbi-network-switch_vlan .td { + width: 100%; + min-width: 60px; + } + + .cbi-rowstyle-2 { + background-color: ; + } + + .pull-right, + .node-main-login>.main form>div:last-child { + float: right; + } + + .pull-left, + .cbi-page-actions .cbi-button-link:first-child { + float: left; + } + + #modemenu>li>a, + .label { + background-color: rgb(104, 104, 104); + color: #fff !important; + font-size: 0.8rem; + font-weight: 700; + text-decoration: none; + text-shadow: none; + text-transform: uppercase; + white-space: nowrap; + padding: 0.3rem 0.8rem; + border-radius: 10px; + } + + [data-indicator="poll-status"][data-style="active"] { + position: absolute; + right: 14px; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/loading.svg) no-repeat; + text-indent: -9999px; + animation: anim-rotate 5s infinite ease-in-out; + background-size: 32px; + } + + [data-indicator="poll-status"][data-style="inactive"] { + position: absolute; + right: 14px; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/pause.svg) no-repeat; + text-indent: -9999px; + background-size: 32px; + } + + + [data-indicator="uci-changes"][data-style="active"] { + position: absolute; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/save.svg) no-repeat; + text-indent: -9999px; + background-size: 32px; + } + + #modemenu>li>a.active, + .notice { + background-color: rgb(66, 66, 66) !important; + } + + #xhr_poll_status, + .cbi-value-field>ul>li { + display: flex; + } + + .alert-message .btn, + .modal .btn { + padding: 0.3rem 0.6rem; + } + + .container .alert, + .container .alert-message, + .cbi-map-descr+fieldset { + margin-top: 1rem; + } + + .main>.main-left>.nav, + .cbi-value-field>ul>li>label { + margin-top: 0.5rem; + } + + .main>.main-left>.nav>li.active>a, + .main>.main-left>.nav>.slide>.slide-menu>.active>a { + color: #fff; + } + + .main>.main-left>.nav>li.active, + .main>.main-left>.nav>.slide>.slide-menu>.active { + + background-color: var(--submenu-bg-hover-active); + border-radius: 10px; + } + + .main>.main-left>.nav>.slide>ul, + .main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before, + .tr.placeholder .td[data-title]::before, + .cbi-dropdown>ul.preview, + .cbi-dropdown>ul>li .hide-close, + .cbi-dropdown[open]>ul.dropdown>li .hide-open, + .hidden, + .showSide, + .node-main-login>.main>.main-left, + [data-page^="admin-system-commands"] .panel-title, + [data-page^="command-cfg"] .mobile-hide, + [data-page^="command-cfg"] .showSide { + display: none; + } + + .main>.main-left>.nav>.slide.active>ul, + .cbi-dropdown[empty]>ul>li, + .cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], + .cbi-dropdown[multiple][open]>ul.dropdown>li>form, + .node-main-login>.main .cbi-value, + #cbi-samba [data-tab="template"] .cbi-value-field, + #cbi-firewall-zone .table, + #cbi-network-switch_vlan .table { + display: block; + } + + .main>.main-left>.nav>li:hover, + .main>.main-left>.nav>.slide>.menu:hover, + .main>.main-left>.nav>.slide>.slide-menu>li:hover { + background: var(--submenu-bg-hover); + border-radius: 10px; + } + + table>tbody>tr>td, + table>tbody>tr>th, + table>tfoot>tr>td, + table>tfoot>tr>th, + table>thead>tr>td, + table>thead>tr>th, + .table>.tbody>.tr>.td, + .table>.tbody>.tr>.th, + .table>.tfoot>.tr>.td, + .table>.tfoot>.tr>.th, + .table>.thead>.tr>.td, + .table>.thead>.tr>.th, + .table>.tr>.td.cbi-value-field, + .table>.tr>.th.cbi-section-table-cell, + .uci-change-list var, + .uci-change-list del, + .uci-change-list ins, + .cbi-section-remove { + padding: 0.5rem; + } + + #cbi-wireless .td, + #cbi-network .tr:first-child>.td, + .table[width="100%"]>.tr:first-child>.td, + [data-page="admin-network-diagnostics"] .tr>.td, + .tr.table-titles>.th, + .tr.cbi-section-table-titles>.th, + #iwsvg, + [data-page="admin-status-realtime-bandwidth"] #bwsvg { + border-top: 0 !important; + } + + .cbi-section-table-row .td, + .center, + .center::before { + text-align: center !important; + } + + div>table>tbody>tr:nth-of-type(2n), + div>.table>.tr:nth-of-type(2n), + .cbi-section .cbi-section-remove:nth-of-type(2n), + .container>.cbi-section .cbi-section-node:nth-of-type(2n), + .cbi-section[id] .cbi-section-remove:nth-of-type(4n + 3), + .cbi-section[id] .cbi-section-node:nth-of-type(4n + 4), + .cbi-tabcontainer>.cbi-value:nth-of-type(2n), + .cbi-rowstyle-1 {} + + .cbi-dropdown>ul>li .hide-open, + .cbi-dropdown[open]>ul.dropdown>li .hide-close { + display: initial; + } + + .network-status-table, + .network-status-table .ifacebox-body>div { + display: flex; + flex-wrap: wrap; + } + + [data-page="admin-network-diagnostics"] .table, + .node-main-login .cbi-section { + box-shadow: none; + } + + @keyframes down { + from { + margin-left: 50%; + opacity: 0; + } + + to { + margin-left: 0%; + opacity: 1; + } + } + + @keyframes anim-rotate { + 0% { + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + @media screen and (min-height: 585px) { + .node-main-login footer { + position: absolute; + bottom: 0; + width: 100%; + } + } + + @keyframes anim-fade-in { + 100% { + opacity: 1; + } + } + + @media all and (-ms-high-contrast: none) { + .main>.main-left>.nav>.slide>.menu::before { + top: 30.25%; + } + + .main>.main-left>.nav>li:last-child::before { + top: 20%; + } + + .showSide::before { + top: -12px; + } + } + + @media screen and (max-width: 1600px) { + header>.fill>.container { + display: flex; + align-items: center; + margin-top: 0; + } + + header>.fill>.container>#logo { + width: calc(13rem); + } + + .main>.main-left { + width: calc(0% + 13rem); + } + + .main>.main-right { + width: calc(100% - 13rem); + } + + .btn:not(button), + .cbi-button { + font-size: 0.8rem; + padding: 0.3rem 0.6rem; + position: relative; + /*bottom: -0.5rem;*/ + } + + .label, + [data-indicator] { + padding: 0.2rem 0.6rem; + } + + fieldset, + .cbi-section { + padding: 1rem; + } + + .cbi-value-title { + width: 15rem; + padding-right: 0.6rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 22rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 9rem; + } + + .cbi-input-textarea { + font-size: small; + } + + .node-admin-status>.main fieldset li>a { + padding: 0.3rem 0.6rem; + } + } + + @media screen and (max-width: 2000000000px) { + header { + height: 3.5rem; + } + + header>.fill>.container { + margin-top: 0.25rem; + cursor: default; + padding: 0.5rem 1rem; + } + + .main { + top: 3.5rem; + height: calc(100% - 3.5rem); + } + + .main>.main-left { + top: 4.3rem; + width: calc(0% + 13rem); + height: calc(100% - 3.5rem); + } + + .main>.main-right { + width: calc(100% - 13rem); + } + + .tabs>li>a, + .cbi-tabmenu>li>a { + padding: 0.2rem 0.5rem; + } + + .cbi-section>h3:first-child, + .panel-title { + font-size: 1.1rem; + padding-bottom: 1rem; + } + + table { + font-size: 0.7rem !important; + width: 100% !important; + } + + .table .cbi-input-text { + width: 100%; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 19rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 4rem; + } + + .main>.main-left>.nav>li, + .main>.main-left>.nav>li a, + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"] { + font-size: 1rem; + color: #fff; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a { + font-size: 0.7rem; + color: #fff; + } + + #modal_overlay { + top: 3.5rem; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { + display: block; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), + [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), + [data-page="admin-network-hosts"] .table, + [data-page="admin-network-routes"] .table { + overflow-y: visible; + } + + .commandbox { + width: 32% !important; + } + } + + @media screen and (max-width: 1152px) { + header>.fill>.container>.brand { + position: relative; + } + + html, + .main { + overflow-y: visible; + } + + .main>.loading>span { + top: 25%; + } + + .main>.main-left { + position: fixed; + z-index: 100; + visibility: hidden; + } + + .main>.main-right { + width: 100%; + } + + .showSide { + position: -webkit-sticky; + position: sticky; + top: 0rem; + display: inline-flex; + align-items: center; + height: 100%; + margin-right: 0.7rem; + cursor: pointer; + } + + body:not(.logged-in) .showSide { + visibility: hidden; + width: 0; + margin: 0; + } + + .cbi-value-title { + width: 12rem; + padding-right: 1rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"] { + width: 16rem; + min-width: 16rem; + color: rgb(255, 255, 255); + } + + .cbi-value input[type="password"], + .cbi-value input[name^="pw"], + .cbi-value input[data-update="change"]:nth-child(2) { + width: 13rem !important; + min-width: 13rem; + color: #fff; + } + + #diag-rc-output>pre, + #command-rc-output>pre, + [data-page="admin-services-wol"] .notice code { + font-size: 1rem; + } + + .Interfaces .table { + overflow-x: hidden; + } + + #packages.table { + display: grid; + } + + .tr { + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + + .Overview .table[width="100%"]>.tr { + flex-wrap: nowrap; + } + + .tr.placeholder { + border-bottom: thin solid #ddd; + } + + .tr.placeholder>.td, + #cbi-firewall .tr>.td, + #cbi-network .tr:nth-child(2)>.td, + .cbi-section #wifi_assoclist_table .tr>.td { + border-top: 0; + } + + .th, + .td { + display: inline-block; + align-self: flex-start; + flex: 2 2 25%; + text-overflow: ellipsis; + word-wrap: break-word; + } + + .td select, + .td input[type="text"] { + width: 100%; + word-wrap: normal; + } + + .td [data-dynlist]>input, + .td input.cbi-input-password { + width: calc(100% - 1.5rem); + } + + .td[data-type="button"], + .td[data-type="fvalue"] { + flex: 1 1 12.5%; + text-align: left; + } + + .th.cbi-value-field, + .td.cbi-value-field, + .th.cbi-section-table-cell, + .td.cbi-section-table-cell { + flex-basis: auto; + padding-top: 1rem; + } + + .cbi-section-table-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + } + + .td.cbi-value-field, + .cbi-section-table-cell { + display: inline-block; + flex: 10 10 auto; + flex-basis: 50%; + text-align: center; + } + + .td.cbi-section-actions { + vertical-align: bottom; + } + + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-size: 0.9rem; + display: block; + flex: 1 1 100%; + border-bottom: thin solid rgba(0, 0, 0, 0.26); + background: #90c0e0; + } + + .cbi-button+.cbi-button { + margin-left: 0; + } + + .td.cbi-section-actions>*>*, + .td.cbi-section-actions>*>form>* { + margin: 2.1px 3px; + } + + .Firewall form { + position: static !important; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + margin: 0 0 2rem; + padding: 2rem; + } + + .Firewall form input { + width: 100% !important; + margin: 1rem 0 0; + } + + .Firewall .center, + .Firewall .center::before { + text-align: left !important; + } + + .commandbox { + width: 100% !important; + margin-left: 0 !important; + } + + .tr.table-titles, + .tr.cbi-section-table-titles, + .tr.cbi-section-table-descr { + display: none; + } + + .node-main-login>.main .cbi-value-title, + .td[data-title], + [data-page^="admin-status-realtime"] .td[id] { + text-align: left; + color: #ffffff; + } + + .table, + .td[data-title]::before { + display: block; + } + } + + @media screen and (max-width: 600px) { + header>.fill>.container>#logo { + padding: 1rem; + margin: 0; + position: absolute; + left: 50%; + top: 0; + width: 100px; + transform: translateX(-50%); + } + + header>.fill>.container>#logo>img { + width: 100%; + margin-top: 0; + } + + .cbi-progressbar::after { + font-size: 0.95em; + line-height: 1.5; + } + + fieldset, + .cbi-section { + margin: 1rem 0 0; + } + + } + + #maincontent>.container { + margin: 0 0.5rem 1.5rem; + } + + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="Log out"], + .main>.main-left>.nav>li>[data-title="iStore"] { + font-size: 1.1rem; + } + + .cbi-value-title { + display: block; + min-width: 0 !important; + text-align: left; + margin: 0.5rem 0; + } + + .cbi-value>.cbi-value-field { + display: inline-block; + } + + .tabs>li>a, + .cbi-tabmenu>li>a { + padding: 0.2rem 0.3rem; + } + + .cbi-page-actions>.cbi-button { + margin-top: 0.2rem; + } + + .node-main-login>.main .container { + margin: 2rem 1.2rem 1.5rem !important; + padding: 0.3rem 1.7rem 2rem 1.6rem; + } + + .node-main-login>.main .cbi-value { + padding: 0; + } + + .node-main-login>.main form>div:last-child { + margin-top: 2rem; + } + + .node-main-login>.main .cbi-value-title { + font-size: 1.2rem; + width: 100% !important; + } + + .node-main-login>.main fieldset { + margin: 0; + padding: 0.5rem; + } + + .commandbox p:first-of-type { + margin-top: -8px; + } + + #syslog, + #diag-rc-output>pre, + #command-rc-output>pre, + [data-page="admin-services-wol"] .notice code { + font-size: 0.8rem !important; + } + + h2 {} + + .cbi-section>h3:first-child, + .panel-title { + font-size: 1.2rem; + padding-bottom: 1rem; + } + + .node-system-packages>.main .cbi-value.cbi-value-last>div { + width: 100% !important; + } + + .th, + .td { + flex-basis: 50%; + color: #fff; + } + + .tr>.td[data-title="Sensor"] { + text-align: center; + } + + .tr>.td[data-title="Temperature"] { + text-align: center; + } + + .tr>.td[data-title="Hostname"] { + text-align: center; + } + + .tr>.td[data-title="IPv4 address"] { + text-align: center; + } + + .tr>.td[data-title="MAC address"] { + text-align: center; + } + + .tr>.td[data-title="Lease time remaining"] { + text-align: center; + } + + + .td.cbi-value-field { + flex-basis: 100%; + } + + .td.cbi-value-field[data-type="button"], + .td.cbi-value-field[data-type="fvalue"] { + flex-basis: 25%; + text-align: left; + } + + td>.ifacebadge, + .td>.ifacebadge { + font-size: 0.62rem; + } + + #cbi-wireless>#wifi_assoclist_table .td { + overflow: hidden; + } + + #cbi-wireless>.cbi-section-node .td, + .Interfaces .td.cbi-section-actions { + text-align: center !important; + } + + .cbi-modal { + padding: 0.5rem; + } + + .cbi-modal .cbi-value { + padding: 0 0 0.25rem; + } + + .cbi-modal [data-tab-title] { + padding: 0 0.25rem !important; + } + + [data-tab-title] { + padding: 0 0.5rem !important; + } + + body, + code { + font-size: 0.8rem; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a, + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-size: + } + + .cbi-value-title, + .cbi-value-description, + .cbi-value-field, + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .node-system-packages>.main .cbi-value .cbi-value-field input { + width: 100%; + display: flex; + color: #fff; + flex-direction: column-reverse; + flex-wrap: wrap; + align-content: stretch; + align-items: flex-start; +} + } + + .cbi-page-actions>div>input, + .mobile-hide, + [data-page="admin-status-processes"] .td[data-title="Hang Up"]::before, + [data-page="admin-status-processes"] .td[data-title="Terminate"]::before, + [data-page="admin-status-processes"] .td[data-title="Kill"]::before, + .hide-sm, + .hide-xs:not([data-title="MAC-Address"]) { + display: none; + } + + .tabs>li>a, + select, + input { + font-size: 0.9rem; + } + + + @media screen and (min-width: 600px) { + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + ::-webkit-scrollbar, + ::-webkit-scrollbar-corner { + background: transparent; + } + + ::-webkit-scrollbar-thumb { + background: #9e9e9e; + } + + ::-webkit-scrollbar-thumb:hover { + background: #757575; + } + + ::-webkit-scrollbar-thumb:active { + background: #424242; + } + } diff --git a/openwrt-packages/luci-theme-alpha/luasrc/style/openwrt20thanniversary.png b/openwrt-packages/luci-theme-alpha/luasrc/style/openwrt20thanniversary.png new file mode 100644 index 0000000000..18ae1ecdd3 Binary files /dev/null and b/openwrt-packages/luci-theme-alpha/luasrc/style/openwrt20thanniversary.png differ diff --git a/openwrt-packages/luci-theme-alpha/luasrc/style/style.css b/openwrt-packages/luci-theme-alpha/luasrc/style/style.css index a162c10517..f43a7c5255 100644 --- a/openwrt-packages/luci-theme-alpha/luasrc/style/style.css +++ b/openwrt-packages/luci-theme-alpha/luasrc/style/style.css @@ -404,10 +404,13 @@ img.tengah { img.bawah { position: absolute; - bottom: 0; - left: 50%; - transform: translateX(-50%); - padding: 2rem; + bottom: 0; + left: 50%; + transform: translateX(-50%); + display: block; + padding: 20px; + text-decoration: none; + width: 25rem; } .icon-credits a { diff --git a/openwrt-packages/luci-theme-alpha/template/footer.htm b/openwrt-packages/luci-theme-alpha/template/footer.htm index 0166861dbc..71faefbd83 100644 --- a/openwrt-packages/luci-theme-alpha/template/footer.htm +++ b/openwrt-packages/luci-theme-alpha/template/footer.htm @@ -67,7 +67,7 @@ local background_color = config.color @@ -50,7 +50,7 @@
<%- if fuser then %>
-

<%:Sandi gagal,silahkan ulangi.%>

+

<%:Wrong Password. Try Again.%>

<% end -%> diff --git a/shadowsocks-rust/Cargo.lock b/shadowsocks-rust/Cargo.lock index 70744bb39b..af7ba9ca03 100644 --- a/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-rust/Cargo.lock @@ -1221,8 +1221,8 @@ dependencies = [ "bytes", "futures", "h3", - "quinn", - "quinn-proto", + "quinn 0.10.2", + "quinn-proto 0.10.6", "tokio-util", ] @@ -1291,7 +1291,7 @@ dependencies = [ "ipnet", "native-tls", "once_cell", - "quinn", + "quinn 0.10.2", "rand", "rustls 0.21.12", "rustls-native-certs 0.6.3", @@ -1410,9 +1410,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1449,19 +1449,21 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", "hyper", "hyper-util", - "rustls 0.22.4", + "rustls 0.23.10", + "rustls-native-certs 0.7.0", "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tower-service", + "webpki-roots 0.26.3", ] [[package]] @@ -2001,9 +2003,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -2473,8 +2475,8 @@ checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" dependencies = [ "bytes", "pin-project-lite", - "quinn-proto", - "quinn-udp", + "quinn-proto 0.10.6", + "quinn-udp 0.4.1", "rustc-hash", "rustls 0.21.12", "thiserror", @@ -2482,6 +2484,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto 0.11.3", + "quinn-udp 0.5.2", + "rustc-hash", + "rustls 0.23.10", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "quinn-proto" version = "0.10.6" @@ -2499,6 +2518,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls 0.23.10", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + [[package]] name = "quinn-udp" version = "0.4.1" @@ -2512,6 +2548,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -2641,9 +2690,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "async-compression", "base64 0.22.1", @@ -2668,7 +2717,8 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.22.4", + "quinn 0.11.2", + "rustls 0.23.10", "rustls-native-certs 0.7.0", "rustls-pemfile 2.1.2", "rustls-pki-types", @@ -2679,14 +2729,14 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.2", + "webpki-roots 0.26.3", "winreg 0.52.0", ] @@ -2829,11 +2879,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" dependencies = [ "log", + "once_cell", "ring 0.17.8", "rustls-pki-types", "rustls-webpki 0.102.4", @@ -3247,9 +3298,9 @@ dependencies = [ "thiserror", "tokio", "tokio-native-tls", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tun2", - "webpki-roots 0.26.2", + "webpki-roots 0.26.3", "windows-sys 0.52.0", "zstd", ] @@ -3437,9 +3488,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "synstructure" @@ -3672,11 +3723,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.22.4", + "rustls 0.23.10", "rustls-pki-types", "tokio", ] @@ -3809,9 +3860,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tun2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27292e82cd2fdfe35a1cdffd2936f213d1a1f2abcb5115ba2ba465681a3c9cdf" +checksum = "dfa430061b1bfcc7b0e22931aa706f3f20471aeb13346eceec4071a0191fca20" dependencies = [ "bytes", "cfg-if", @@ -4074,9 +4125,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ "rustls-pki-types", ] @@ -4460,9 +4511,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.11+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" dependencies = [ "cc", "pkg-config", diff --git a/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml b/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml index 407b71b30a..a24ee93e08 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml +++ b/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml @@ -156,7 +156,11 @@ tokio = { version = "1.38", features = [ tokio-native-tls = { version = "0.3", optional = true } native-tls = { version = "0.2.8", optional = true, features = ["alpn"] } webpki-roots = { version = "0.26", optional = true } -tokio-rustls = { version = "0.25", optional = true } +tokio-rustls = { version = "0.26", optional = true, default-features = false, features = [ + "logging", + "tls12", + "ring", +] } rustls-native-certs = { version = "0.7", optional = true } async-trait = "0.1" diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/sys/unix/bsd_pf.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/sys/unix/bsd_pf.rs index f4c3fbbcee..b08ad3ac4c 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/sys/unix/bsd_pf.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/sys/unix/bsd_pf.rs @@ -13,9 +13,9 @@ use nix::ioctl_readwrite; use once_cell::sync::Lazy; use socket2::{Protocol, SockAddr}; -use super::pfvar::{in6_addr, in_addr, pfioc_natlook, pfioc_states, sockaddr_in, sockaddr_in6, PF_OUT}; +use super::pfvar::{in6_addr, in_addr, pfioc_natlook, sockaddr_in, sockaddr_in6, PF_OUT}; #[cfg(any(target_os = "macos", target_os = "ios"))] -use super::pfvar::{pf_addr, pfsync_state}; +use super::pfvar::{pf_addr, pfioc_states, pfsync_state}; ioctl_readwrite!(ioc_natlook, 'D', 23, pfioc_natlook); #[cfg(any(target_os = "macos", target_os = "ios"))] diff --git a/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/bsd.rs b/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/bsd.rs index aae4f58f7c..a7932561ca 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/bsd.rs +++ b/shadowsocks-rust/crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/bsd.rs @@ -77,8 +77,10 @@ impl UdpRedirSocket { if is_dual_stack_addr(&addr) { // set IP_ORIGDSTADDR before bind() - set_ip_origdstaddr(libc::IPPROTO_IP, &socket)?; - set_disable_ip_fragmentation(libc::IPPROTO_IP, &socket)?; + // NOTE: FreeBSD doesn't allow setting IPPROTO_IP level on an IPv6 socket + // + // set_ip_origdstaddr(libc::IPPROTO_IP, &socket)?; + // set_disable_ip_fragmentation(libc::IPPROTO_IP, &socket)?; match set_ipv6_only(&socket, false) { Ok(..) => { diff --git a/sing-box/experimental/libbox/command_client.go b/sing-box/experimental/libbox/command_client.go index 199dce0d18..b3bbc5a687 100644 --- a/sing-box/experimental/libbox/command_client.go +++ b/sing-box/experimental/libbox/command_client.go @@ -26,7 +26,7 @@ type CommandClientHandler interface { Connected() Disconnected(message string) ClearLog() - WriteLog(message string) + WriteLog(messageList StringIterator) WriteStatus(message *StatusMessage) WriteGroups(message OutboundGroupIterator) InitializeClashMode(modeList StringIterator, currentMode string) @@ -84,6 +84,10 @@ func (c *CommandClient) Connect() error { } switch c.options.Command { case CommandLog: + err = binary.Write(conn, binary.BigEndian, c.options.StatusInterval) + if err != nil { + return E.Cause(err, "write interval") + } c.handler.Connected() go c.handleLogConn(conn) case CommandStatus: diff --git a/sing-box/experimental/libbox/command_log.go b/sing-box/experimental/libbox/command_log.go index ce72010dd0..d2f3fbf2c1 100644 --- a/sing-box/experimental/libbox/command_log.go +++ b/sing-box/experimental/libbox/command_log.go @@ -1,10 +1,14 @@ package libbox import ( + "bufio" "context" - "encoding/binary" "io" "net" + "time" + + "github.com/sagernet/sing/common/binary" + E "github.com/sagernet/sing/common/exceptions" ) func (s *CommandServer) WriteMessage(message string) { @@ -17,43 +21,39 @@ func (s *CommandServer) WriteMessage(message string) { s.access.Unlock() } -func readLog(reader io.Reader) ([]byte, error) { - var messageLength uint16 - err := binary.Read(reader, binary.BigEndian, &messageLength) - if err != nil { - return nil, err - } - if messageLength == 0 { - return nil, nil - } - data := make([]byte, messageLength) - _, err = io.ReadFull(reader, data) - if err != nil { - return nil, err - } - return data, nil -} - -func writeLog(writer io.Writer, message []byte) error { +func writeLog(writer *bufio.Writer, messages []string) error { err := binary.Write(writer, binary.BigEndian, uint8(0)) if err != nil { return err } - err = binary.Write(writer, binary.BigEndian, uint16(len(message))) + err = binary.WriteData(writer, binary.BigEndian, messages) if err != nil { return err } - if len(message) > 0 { - _, err = writer.Write(message) - } - return err + return writer.Flush() } -func writeClearLog(writer io.Writer) error { - return binary.Write(writer, binary.BigEndian, uint8(1)) +func writeClearLog(writer *bufio.Writer) error { + err := binary.Write(writer, binary.BigEndian, uint8(1)) + if err != nil { + return err + } + return writer.Flush() } func (s *CommandServer) handleLogConn(conn net.Conn) error { + var ( + interval int64 + timer *time.Timer + ) + err := binary.Read(conn, binary.BigEndian, &interval) + if err != nil { + return E.Cause(err, "read interval") + } + timer = time.NewTimer(time.Duration(interval)) + if !timer.Stop() { + <-timer.C + } var savedLines []string s.access.Lock() savedLines = make([]string, 0, s.savedLines.Len()) @@ -66,50 +66,65 @@ func (s *CommandServer) handleLogConn(conn net.Conn) error { return err } defer s.observer.UnSubscribe(subscription) - for _, line := range savedLines { - err = writeLog(conn, []byte(line)) + writer := bufio.NewWriter(conn) + if len(savedLines) > 0 { + err = writeLog(writer, savedLines) if err != nil { return err } } ctx := connKeepAlive(conn) + var logLines []string for { select { case <-ctx.Done(): return ctx.Err() - case message := <-subscription: - err = writeLog(conn, []byte(message)) - if err != nil { - return err - } case <-s.logReset: - err = writeClearLog(conn) + err = writeClearLog(writer) if err != nil { return err } case <-done: return nil + case logLine := <-subscription: + logLines = logLines[:0] + logLines = append(logLines, logLine) + timer.Reset(time.Duration(interval)) + loopLogs: + for { + select { + case logLine = <-subscription: + logLines = append(logLines, logLine) + case <-timer.C: + break loopLogs + } + } + err = writeLog(writer, logLines) + if err != nil { + return err + } } } } func (c *CommandClient) handleLogConn(conn net.Conn) { + reader := bufio.NewReader(conn) for { var messageType uint8 - err := binary.Read(conn, binary.BigEndian, &messageType) + err := binary.Read(reader, binary.BigEndian, &messageType) if err != nil { c.handler.Disconnected(err.Error()) return } - var message []byte + var messages []string switch messageType { case 0: - message, err = readLog(conn) + err = binary.ReadData(reader, binary.BigEndian, &messages) if err != nil { c.handler.Disconnected(err.Error()) return } - c.handler.WriteLog(string(message)) + c.handler.WriteLog(newIterator(messages)) case 1: c.handler.ClearLog() } @@ -120,7 +135,7 @@ func connKeepAlive(reader io.Reader) context.Context { ctx, cancel := context.WithCancelCause(context.Background()) go func() { for { - _, err := readLog(reader) + _, err := reader.Read(make([]byte, 1)) if err != nil { cancel(err) return diff --git a/sing-box/experimental/libbox/iterator.go b/sing-box/experimental/libbox/iterator.go index 530a7e43bd..50d7385b36 100644 --- a/sing-box/experimental/libbox/iterator.go +++ b/sing-box/experimental/libbox/iterator.go @@ -3,8 +3,9 @@ package libbox import "github.com/sagernet/sing/common" type StringIterator interface { - Next() string + Len() int32 HasNext() bool + Next() string } var _ StringIterator = (*iterator[string])(nil) @@ -21,6 +22,14 @@ func newPtrIterator[T any](values []T) *iterator[*T] { return &iterator[*T]{common.Map(values, func(value T) *T { return &value })} } +func (i *iterator[T]) Len() int32 { + return int32(len(i.values)) +} + +func (i *iterator[T]) HasNext() bool { + return len(i.values) > 0 +} + func (i *iterator[T]) Next() T { if len(i.values) == 0 { return common.DefaultValue[T]() @@ -30,10 +39,6 @@ func (i *iterator[T]) Next() T { return nextValue } -func (i *iterator[T]) HasNext() bool { - return len(i.values) > 0 -} - type abstractIterator[T any] interface { Next() T HasNext() bool diff --git a/sing-box/inbound/tun.go b/sing-box/inbound/tun.go index 239691a976..b18adc803d 100644 --- a/sing-box/inbound/tun.go +++ b/sing-box/inbound/tun.go @@ -5,6 +5,7 @@ import ( "net" "net/netip" "os" + "runtime" "strconv" "strings" "time" @@ -206,30 +207,32 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger if err != nil { return nil, E.Cause(err, "initialize auto-redirect") } - var markMode bool - for _, routeAddressSet := range options.RouteAddressSet { - ruleSet, loaded := router.RuleSet(routeAddressSet) - if !loaded { - return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet) + if runtime.GOOS != "android" { + var markMode bool + for _, routeAddressSet := range options.RouteAddressSet { + ruleSet, loaded := router.RuleSet(routeAddressSet) + if !loaded { + return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet) + } + ruleSet.IncRef() + inbound.routeRuleSet = append(inbound.routeRuleSet, ruleSet) + markMode = true } - ruleSet.IncRef() - inbound.routeRuleSet = append(inbound.routeRuleSet, ruleSet) - markMode = true - } - for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet { - ruleSet, loaded := router.RuleSet(routeExcludeAddressSet) - if !loaded { - return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet) + for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet { + ruleSet, loaded := router.RuleSet(routeExcludeAddressSet) + if !loaded { + return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet) + } + ruleSet.IncRef() + inbound.routeExcludeRuleSet = append(inbound.routeExcludeRuleSet, ruleSet) + markMode = true } - ruleSet.IncRef() - inbound.routeExcludeRuleSet = append(inbound.routeExcludeRuleSet, ruleSet) - markMode = true - } - if markMode { - inbound.tunOptions.AutoRedirectMarkMode = true - err = router.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark) - if err != nil { - return nil, err + if markMode { + inbound.tunOptions.AutoRedirectMarkMode = true + err = router.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark) + if err != nil { + return nil, err + } } } } @@ -337,7 +340,21 @@ func (t *Tun) PostStart() error { monitor := taskmonitor.New(t.logger, C.StartTimeout) if t.autoRedirect != nil { t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet) + for _, routeRuleSet := range t.routeRuleSet { + ipSets := routeRuleSet.ExtractIPSet() + if len(ipSets) == 0 { + t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name()) + } + t.routeAddressSet = append(t.routeAddressSet, ipSets...) + } t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet) + for _, routeExcludeRuleSet := range t.routeExcludeRuleSet { + ipSets := routeExcludeRuleSet.ExtractIPSet() + if len(ipSets) == 0 { + t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name()) + } + t.routeExcludeAddressSet = append(t.routeExcludeAddressSet, ipSets...) + } monitor.Start("initiating auto-redirect") err := t.autoRedirect.Start() monitor.Finish() diff --git a/small/xray-core/Makefile b/small/xray-core/Makefile index 5757fad8d3..a07a1876c2 100644 --- a/small/xray-core/Makefile +++ b/small/xray-core/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=xray-core -PKG_VERSION:=1.8.13 +PKG_VERSION:=1.8.15 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/XTLS/Xray-core/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=9e63fbeb4667c19e286389c370d30e9e904f4421784adcbe6cf4d6e172a2ac29 +PKG_HASH:=4e0ac5170668033fd55544688a1d56938de91bc00c5ebc7d8c5211fd97cbca65 PKG_MAINTAINER:=Tianling Shen PKG_LICENSE:=MPL-2.0 diff --git a/small/xray-plugin/Makefile b/small/xray-plugin/Makefile index 402ec8c987..d52e6b3243 100644 --- a/small/xray-plugin/Makefile +++ b/small/xray-plugin/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=xray-plugin -PKG_VERSION:=1.8.12 +PKG_VERSION:=1.8.15 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/teddysun/xray-plugin/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=dddc552e1d3616a93bd93082439f042c048833307eb009a4df97f336deac3346 +PKG_HASH:=0079b964dedfa1e5823cc8e8c75c0589875466d91aa1e13cb3683ba5cee0fae5 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE diff --git a/v2raya/.github/workflows/release_main.yml b/v2raya/.github/workflows/release_main.yml index 9406765de9..5d72cabe1f 100644 --- a/v2raya/.github/workflows/release_main.yml +++ b/v2raya/.github/workflows/release_main.yml @@ -760,11 +760,20 @@ jobs: uses: docker/setup-qemu-action@v3.0.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.0.0 + - name: Login to GitHub container registry + uses: docker/login-action@v3.0.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Login to DockerHub uses: docker/login-action@v3.0.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Convert repository owner to lowercase + run: | + echo "LOWERCASE_REPOSITORY_OWNER=${GITHUB_REPOSITORY_OWNER@L}" >>${GITHUB_ENV} - name: Build and push uses: docker/build-push-action@v5.0.0 with: @@ -776,6 +785,8 @@ jobs: tags: | ${{ steps.prep.outputs.image }}:${{ steps.prep.outputs.tag }} ${{ steps.prep.outputs.image }}:latest + ghcr.io/${{ env.LOWERCASE_REPOSITORY_OWNER }}/v2raya:${{ steps.prep.outputs.tag }} + ghcr.io/${{ env.LOWERCASE_REPOSITORY_OWNER }}/v2raya:latest cache-from: type=gha cache-to: type=gha,mode=max Release_v2rayA_GUI_to_Docker: @@ -805,11 +816,20 @@ jobs: uses: docker/setup-qemu-action@v3.0.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.0.0 + - name: Login to GitHub container registry + uses: docker/login-action@v3.0.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Login to DockerHub uses: docker/login-action@v3.0.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Convert repository owner to lowercase + run: | + echo "LOWERCASE_REPOSITORY_OWNER=${GITHUB_REPOSITORY_OWNER@L}" >>${GITHUB_ENV} - name: Build and push uses: docker/build-push-action@v5.0.0 with: @@ -818,7 +838,9 @@ jobs: file: install/docker/Dockerfile.GUI.Action platforms: linux/arm,linux/arm64,linux/amd64 push: true - tags: mzz2017/v2raya-gui:latest + tags: | + mzz2017/v2raya-gui:latest + ghcr.io/${{ env.LOWERCASE_REPOSITORY_OWNER }}/v2raya-gui:latest cache-from: type=gha cache-to: type=gha,mode=max Submit_to_Microsoft_winget: diff --git a/v2raya/Dockerfile b/v2raya/Dockerfile index 9bda944016..a15da0d053 100644 --- a/v2raya/Dockerfile +++ b/v2raya/Dockerfile @@ -23,6 +23,7 @@ FROM v2fly/v2fly-core COPY --from=builder /build/service/v2raya /usr/bin/ RUN wget -O /usr/local/share/v2ray/LoyalsoldierSite.dat https://raw.githubusercontent.com/mzz2017/dist-v2ray-rules-dat/master/geosite.dat RUN apk add --no-cache iptables ip6tables tzdata +LABEL org.opencontainers.image.source=https://github.com/v2rayA/v2rayA EXPOSE 2017 VOLUME /etc/v2raya ENTRYPOINT ["v2raya"] diff --git a/v2raya/Dockerfile.gui b/v2raya/Dockerfile.gui index 1a493969fa..441e74ed43 100644 --- a/v2raya/Dockerfile.gui +++ b/v2raya/Dockerfile.gui @@ -5,4 +5,5 @@ RUN yarn && yarn build FROM nginx:stable-alpine COPY --from=builder /web /usr/share/nginx/html +LABEL org.opencontainers.image.source=https://github.com/v2rayA/v2rayA EXPOSE 80 diff --git a/xray-core/.github/workflows/docker.yml b/xray-core/.github/workflows/docker.yml index b839d9863a..e577b6bb36 100644 --- a/xray-core/.github/workflows/docker.yml +++ b/xray-core/.github/workflows/docker.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . platforms: linux/amd64,linux/arm64 diff --git a/xray-core/core/core.go b/xray-core/core/core.go index 1bf02996a1..0cccfd77c4 100644 --- a/xray-core/core/core.go +++ b/xray-core/core/core.go @@ -21,7 +21,7 @@ import ( var ( Version_x byte = 1 Version_y byte = 8 - Version_z byte = 13 + Version_z byte = 15 ) var ( diff --git a/xray-core/infra/conf/transport.go b/xray-core/infra/conf/transport.go index b7969e471f..1e0e70de89 100644 --- a/xray-core/infra/conf/transport.go +++ b/xray-core/infra/conf/transport.go @@ -16,6 +16,7 @@ type TransportConfig struct { GRPCConfig *GRPCConfig `json:"grpcSettings"` GUNConfig *GRPCConfig `json:"gunSettings"` HTTPUPGRADEConfig *HttpUpgradeConfig `json:"httpupgradeSettings"` + SplitHTTPConfig *SplitHTTPConfig `json:"splithttpSettings"` } // Build implements Buildable. @@ -113,5 +114,16 @@ func (c *TransportConfig) Build() (*global.Config, error) { }) } + if c.SplitHTTPConfig != nil { + shs, err := c.SplitHTTPConfig.Build() + if err != nil { + return nil, newError("failed to build SplitHTTP config").Base(err) + } + config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ + ProtocolName: "splithttp", + Settings: serial.ToTypedMessage(shs), + }) + } + return config, nil } diff --git a/xray-core/infra/conf/transport_internet.go b/xray-core/infra/conf/transport_internet.go index 3ebb532667..12ed419702 100644 --- a/xray-core/infra/conf/transport_internet.go +++ b/xray-core/infra/conf/transport_internet.go @@ -23,6 +23,7 @@ import ( "github.com/xtls/xray-core/transport/internet/kcp" "github.com/xtls/xray-core/transport/internet/quic" "github.com/xtls/xray-core/transport/internet/reality" + "github.com/xtls/xray-core/transport/internet/splithttp" "github.com/xtls/xray-core/transport/internet/tcp" "github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/websocket" @@ -223,6 +224,34 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) { return config, nil } +type SplitHTTPConfig struct { + Host string `json:"host"` + Path string `json:"path"` + Headers map[string]string `json:"headers"` + MaxConcurrentUploads int32 `json:"maxConcurrentUploads"` + MaxUploadSize int32 `json:"maxUploadSize"` +} + +// Build implements Buildable. +func (c *SplitHTTPConfig) Build() (proto.Message, error) { + // If http host is not set in the Host field, but in headers field, we add it to Host Field here. + // If we don't do that, http host will be overwritten as address. + // Host priority: Host field > headers field > address. + if c.Host == "" && c.Headers["host"] != "" { + c.Host = c.Headers["host"] + } else if c.Host == "" && c.Headers["Host"] != "" { + c.Host = c.Headers["Host"] + } + config := &splithttp.Config{ + Path: c.Path, + Host: c.Host, + Header: c.Headers, + MaxConcurrentUploads: c.MaxConcurrentUploads, + MaxUploadSize: c.MaxUploadSize, + } + return config, nil +} + type HTTPConfig struct { Host *StringList `json:"host"` Path string `json:"path"` @@ -648,6 +677,8 @@ func (p TransportProtocol) Build() (string, error) { return "grpc", nil case "httpupgrade": return "httpupgrade", nil + case "splithttp": + return "splithttp", nil default: return "", newError("Config: unknown transport protocol: ", p) } @@ -762,6 +793,7 @@ type StreamConfig struct { GRPCConfig *GRPCConfig `json:"grpcSettings"` GUNConfig *GRPCConfig `json:"gunSettings"` HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"` + SplitHTTPSettings *SplitHTTPConfig `json:"splithttpSettings"` } // Build implements Buildable. @@ -892,6 +924,16 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) { Settings: serial.ToTypedMessage(hs), }) } + if c.SplitHTTPSettings != nil { + hs, err := c.SplitHTTPSettings.Build() + if err != nil { + return nil, newError("Failed to build SplitHTTP config.").Base(err) + } + config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ + ProtocolName: "splithttp", + Settings: serial.ToTypedMessage(hs), + }) + } if c.SocketSettings != nil { ss, err := c.SocketSettings.Build() if err != nil { diff --git a/xray-core/infra/conf/xray.go b/xray-core/infra/conf/xray.go index e48e04b21b..5e1adcbc6e 100644 --- a/xray-core/infra/conf/xray.go +++ b/xray-core/infra/conf/xray.go @@ -557,6 +557,9 @@ func applyTransportConfig(s *StreamConfig, t *TransportConfig) { if s.HTTPUPGRADESettings == nil { s.HTTPUPGRADESettings = t.HTTPUPGRADEConfig } + if s.SplitHTTPSettings == nil { + s.SplitHTTPSettings = t.SplitHTTPConfig + } } // Build implements Buildable. diff --git a/xray-core/main/distro/all/all.go b/xray-core/main/distro/all/all.go index 0f0397f594..ae71765388 100644 --- a/xray-core/main/distro/all/all.go +++ b/xray-core/main/distro/all/all.go @@ -57,6 +57,7 @@ import ( _ "github.com/xtls/xray-core/transport/internet/kcp" _ "github.com/xtls/xray-core/transport/internet/quic" _ "github.com/xtls/xray-core/transport/internet/reality" + _ "github.com/xtls/xray-core/transport/internet/splithttp" _ "github.com/xtls/xray-core/transport/internet/tcp" _ "github.com/xtls/xray-core/transport/internet/tls" _ "github.com/xtls/xray-core/transport/internet/udp" diff --git a/xray-core/transport/internet/config.pb.go b/xray-core/transport/internet/config.pb.go index e262a1a81b..55010f0089 100644 --- a/xray-core/transport/internet/config.pb.go +++ b/xray-core/transport/internet/config.pb.go @@ -31,6 +31,7 @@ const ( TransportProtocol_HTTP TransportProtocol = 4 TransportProtocol_DomainSocket TransportProtocol = 5 TransportProtocol_HTTPUpgrade TransportProtocol = 6 + TransportProtocol_SplitHTTP TransportProtocol = 7 ) // Enum value maps for TransportProtocol. @@ -43,6 +44,7 @@ var ( 4: "HTTP", 5: "DomainSocket", 6: "HTTPUpgrade", + 7: "SplitHTTP", } TransportProtocol_value = map[string]int32{ "TCP": 0, @@ -52,6 +54,7 @@ var ( "HTTP": 4, "DomainSocket": 5, "HTTPUpgrade": 6, + "SplitHTTP": 7, } ) @@ -728,31 +731,32 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x4d, 0x70, 0x74, 0x63, 0x70, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x6b, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, + 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x7a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x10, 0x06, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, - 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, - 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, - 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, - 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, - 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, - 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, - 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, - 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, - 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, - 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, - 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, - 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, - 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, - 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x48, 0x54, 0x54, 0x50, + 0x10, 0x07, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, + 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, + 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, + 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, + 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, + 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, + 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, + 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, + 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, + 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, + 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x67, + 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, + 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, + 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, + 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/xray-core/transport/internet/config.proto b/xray-core/transport/internet/config.proto index 22277b428b..207cdff364 100644 --- a/xray-core/transport/internet/config.proto +++ b/xray-core/transport/internet/config.proto @@ -16,6 +16,7 @@ enum TransportProtocol { HTTP = 4; DomainSocket = 5; HTTPUpgrade = 6; + SplitHTTP = 7; } enum DomainStrategy { diff --git a/xray-core/transport/internet/splithttp/config.go b/xray-core/transport/internet/splithttp/config.go new file mode 100644 index 0000000000..4c44e3613e --- /dev/null +++ b/xray-core/transport/internet/splithttp/config.go @@ -0,0 +1,52 @@ +package splithttp + +import ( + "net/http" + + "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/transport/internet" +) + +func (c *Config) GetNormalizedPath() string { + path := c.Path + if path == "" { + path = "/" + } + if path[0] != '/' { + path = "/" + path + } + if path[len(path)-1] != '/' { + path = path + "/" + } + return path +} + +func (c *Config) GetRequestHeader() http.Header { + header := http.Header{} + for k, v := range c.Header { + header.Add(k, v) + } + return header +} + +func (c *Config) GetNormalizedMaxConcurrentUploads() int32 { + if c.MaxConcurrentUploads == 0 { + return 10 + } + + return c.MaxConcurrentUploads +} + +func (c *Config) GetNormalizedMaxUploadSize() int32 { + if c.MaxUploadSize == 0 { + return 1000000 + } + + return c.MaxUploadSize +} + +func init() { + common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} { + return new(Config) + })) +} diff --git a/xray-core/transport/internet/splithttp/config.pb.go b/xray-core/transport/internet/splithttp/config.pb.go new file mode 100644 index 0000000000..3975b9f6ec --- /dev/null +++ b/xray-core/transport/internet/splithttp/config.pb.go @@ -0,0 +1,202 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.1 +// protoc v5.27.0 +// source: transport/internet/splithttp/config.proto + +package splithttp + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + Header map[string]string `protobuf:"bytes,3,rep,name=header,proto3" json:"header,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + MaxConcurrentUploads int32 `protobuf:"varint,4,opt,name=maxConcurrentUploads,proto3" json:"maxConcurrentUploads,omitempty"` + MaxUploadSize int32 `protobuf:"varint,5,opt,name=maxUploadSize,proto3" json:"maxUploadSize,omitempty"` +} + +func (x *Config) Reset() { + *x = Config{} + if protoimpl.UnsafeEnabled { + mi := &file_transport_internet_splithttp_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config) ProtoMessage() {} + +func (x *Config) ProtoReflect() protoreflect.Message { + mi := &file_transport_internet_splithttp_config_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config.ProtoReflect.Descriptor instead. +func (*Config) Descriptor() ([]byte, []int) { + return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{0} +} + +func (x *Config) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (x *Config) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *Config) GetHeader() map[string]string { + if x != nil { + return x.Header + } + return nil +} + +func (x *Config) GetMaxConcurrentUploads() int32 { + if x != nil { + return x.MaxConcurrentUploads + } + return 0 +} + +func (x *Config) GetMaxUploadSize() int32 { + if x != nil { + return x.MaxUploadSize + } + return 0 +} + +var File_transport_internet_splithttp_config_proto protoreflect.FileDescriptor + +var file_transport_internet_splithttp_config_proto_rawDesc = []byte{ + 0x0a, 0x29, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x78, 0x72, 0x61, + 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x22, 0x94, + 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x12, 0x4d, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, + 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x32, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, + 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, + 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x85, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, + 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x50, + 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, + 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, + 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0xaa, 0x02, 0x21, 0x58, 0x72, 0x61, 0x79, + 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x48, 0x74, 0x74, 0x70, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_transport_internet_splithttp_config_proto_rawDescOnce sync.Once + file_transport_internet_splithttp_config_proto_rawDescData = file_transport_internet_splithttp_config_proto_rawDesc +) + +func file_transport_internet_splithttp_config_proto_rawDescGZIP() []byte { + file_transport_internet_splithttp_config_proto_rawDescOnce.Do(func() { + file_transport_internet_splithttp_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_splithttp_config_proto_rawDescData) + }) + return file_transport_internet_splithttp_config_proto_rawDescData +} + +var file_transport_internet_splithttp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_transport_internet_splithttp_config_proto_goTypes = []interface{}{ + (*Config)(nil), // 0: xray.transport.internet.splithttp.Config + nil, // 1: xray.transport.internet.splithttp.Config.HeaderEntry +} +var file_transport_internet_splithttp_config_proto_depIdxs = []int32{ + 1, // 0: xray.transport.internet.splithttp.Config.header:type_name -> xray.transport.internet.splithttp.Config.HeaderEntry + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_transport_internet_splithttp_config_proto_init() } +func file_transport_internet_splithttp_config_proto_init() { + if File_transport_internet_splithttp_config_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_transport_internet_splithttp_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_transport_internet_splithttp_config_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_transport_internet_splithttp_config_proto_goTypes, + DependencyIndexes: file_transport_internet_splithttp_config_proto_depIdxs, + MessageInfos: file_transport_internet_splithttp_config_proto_msgTypes, + }.Build() + File_transport_internet_splithttp_config_proto = out.File + file_transport_internet_splithttp_config_proto_rawDesc = nil + file_transport_internet_splithttp_config_proto_goTypes = nil + file_transport_internet_splithttp_config_proto_depIdxs = nil +} diff --git a/xray-core/transport/internet/splithttp/config.proto b/xray-core/transport/internet/splithttp/config.proto new file mode 100644 index 0000000000..43cecee204 --- /dev/null +++ b/xray-core/transport/internet/splithttp/config.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package xray.transport.internet.splithttp; +option csharp_namespace = "Xray.Transport.Internet.SplitHttp"; +option go_package = "github.com/xtls/xray-core/transport/internet/splithttp"; +option java_package = "com.xray.transport.internet.splithttp"; +option java_multiple_files = true; + +message Config { + string host = 1; + string path = 2; + map header = 3; + int32 maxConcurrentUploads = 4; + int32 maxUploadSize = 5; +} diff --git a/xray-core/transport/internet/splithttp/connection.go b/xray-core/transport/internet/splithttp/connection.go new file mode 100644 index 0000000000..697381d425 --- /dev/null +++ b/xray-core/transport/internet/splithttp/connection.go @@ -0,0 +1,59 @@ +package splithttp + +import ( + "io" + "net" + "time" +) + +type splitConn struct { + writer io.WriteCloser + reader io.ReadCloser + remoteAddr net.Addr + localAddr net.Addr +} + +func (c *splitConn) Write(b []byte) (int, error) { + return c.writer.Write(b) +} + +func (c *splitConn) Read(b []byte) (int, error) { + return c.reader.Read(b) +} + +func (c *splitConn) Close() error { + err := c.writer.Close() + err2 := c.reader.Close() + if err != nil { + return err + } + + if err2 != nil { + return err + } + + return nil +} + +func (c *splitConn) LocalAddr() net.Addr { + return c.localAddr +} + +func (c *splitConn) RemoteAddr() net.Addr { + return c.remoteAddr +} + +func (c *splitConn) SetDeadline(t time.Time) error { + // TODO cannot do anything useful + return nil +} + +func (c *splitConn) SetReadDeadline(t time.Time) error { + // TODO cannot do anything useful + return nil +} + +func (c *splitConn) SetWriteDeadline(t time.Time) error { + // TODO cannot do anything useful + return nil +} diff --git a/xray-core/transport/internet/splithttp/dialer.go b/xray-core/transport/internet/splithttp/dialer.go new file mode 100644 index 0000000000..43dccf8523 --- /dev/null +++ b/xray-core/transport/internet/splithttp/dialer.go @@ -0,0 +1,316 @@ +package splithttp + +import ( + "context" + gotls "crypto/tls" + "io" + gonet "net" + "net/http" + "net/http/httptrace" + "net/url" + "strconv" + "sync" + "time" + + "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/buf" + "github.com/xtls/xray-core/common/net" + "github.com/xtls/xray-core/common/session" + "github.com/xtls/xray-core/common/signal/semaphore" + "github.com/xtls/xray-core/common/uuid" + "github.com/xtls/xray-core/transport/internet" + "github.com/xtls/xray-core/transport/internet/stat" + "github.com/xtls/xray-core/transport/internet/tls" + "github.com/xtls/xray-core/transport/pipe" + "golang.org/x/net/http2" +) + +type dialerConf struct { + net.Destination + *internet.MemoryStreamConfig +} + +type reusedClient struct { + download *http.Client + upload *http.Client + isH2 bool + // pool of net.Conn, created using dialUploadConn + uploadRawPool *sync.Pool + dialUploadConn func(ctxInner context.Context) (net.Conn, error) +} + +var ( + globalDialerMap map[dialerConf]reusedClient + globalDialerAccess sync.Mutex +) + +func destroyHTTPClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) { + globalDialerAccess.Lock() + defer globalDialerAccess.Unlock() + + if globalDialerMap == nil { + globalDialerMap = make(map[dialerConf]reusedClient) + } + + delete(globalDialerMap, dialerConf{dest, streamSettings}) + +} + +func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) reusedClient { + globalDialerAccess.Lock() + defer globalDialerAccess.Unlock() + + if globalDialerMap == nil { + globalDialerMap = make(map[dialerConf]reusedClient) + } + + if client, found := globalDialerMap[dialerConf{dest, streamSettings}]; found { + return client + } + + tlsConfig := tls.ConfigFromStreamSettings(streamSettings) + + var gotlsConfig *gotls.Config + + if tlsConfig != nil { + gotlsConfig = tlsConfig.GetTLSConfig(tls.WithDestination(dest)) + } + + dialContext := func(ctxInner context.Context) (net.Conn, error) { + conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings) + if err != nil { + return nil, err + } + + if gotlsConfig != nil { + if fingerprint := tls.GetFingerprint(tlsConfig.Fingerprint); fingerprint != nil { + conn = tls.UClient(conn, gotlsConfig, fingerprint) + if err := conn.(*tls.UConn).HandshakeContext(ctx); err != nil { + return nil, err + } + } else { + conn = tls.Client(conn, gotlsConfig) + } + } + + return conn, nil + } + + var uploadTransport http.RoundTripper + var downloadTransport http.RoundTripper + + if tlsConfig != nil { + downloadTransport = &http2.Transport{ + DialTLSContext: func(ctxInner context.Context, network string, addr string, cfg *gotls.Config) (net.Conn, error) { + return dialContext(ctxInner) + }, + IdleConnTimeout: 90 * time.Second, + } + uploadTransport = downloadTransport + } else { + httpDialContext := func(ctxInner context.Context, network string, addr string) (net.Conn, error) { + return dialContext(ctxInner) + } + + downloadTransport = &http.Transport{ + DialTLSContext: httpDialContext, + DialContext: httpDialContext, + IdleConnTimeout: 90 * time.Second, + // chunked transfer download with keepalives is buggy with + // http.Client and our custom dial context. + DisableKeepAlives: true, + } + + // we use uploadRawPool for that + uploadTransport = nil + } + + client := reusedClient{ + download: &http.Client{ + Transport: downloadTransport, + }, + upload: &http.Client{ + Transport: uploadTransport, + }, + isH2: tlsConfig != nil, + uploadRawPool: &sync.Pool{}, + dialUploadConn: dialContext, + } + + globalDialerMap[dialerConf{dest, streamSettings}] = client + return client +} + +func init() { + common.Must(internet.RegisterTransportDialer(protocolName, Dial)) +} + +func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) { + newError("dialing splithttp to ", dest).WriteToLog(session.ExportIDToError(ctx)) + + var requestURL url.URL + + transportConfiguration := streamSettings.ProtocolSettings.(*Config) + tlsConfig := tls.ConfigFromStreamSettings(streamSettings) + + maxConcurrentUploads := transportConfiguration.GetNormalizedMaxConcurrentUploads() + maxUploadSize := transportConfiguration.GetNormalizedMaxUploadSize() + + if tlsConfig != nil { + requestURL.Scheme = "https" + } else { + requestURL.Scheme = "http" + } + requestURL.Host = transportConfiguration.Host + if requestURL.Host == "" { + requestURL.Host = dest.NetAddr() + } + requestURL.Path = transportConfiguration.GetNormalizedPath() + + httpClient := getHTTPClient(ctx, dest, streamSettings) + + var remoteAddr gonet.Addr + var localAddr gonet.Addr + + trace := &httptrace.ClientTrace{ + GotConn: func(connInfo httptrace.GotConnInfo) { + remoteAddr = connInfo.Conn.RemoteAddr() + localAddr = connInfo.Conn.LocalAddr() + }, + } + + sessionIdUuid := uuid.New() + sessionId := sessionIdUuid.String() + + req, err := http.NewRequestWithContext( + httptrace.WithClientTrace(ctx, trace), + "GET", + requestURL.String()+"?session="+sessionId, + nil, + ) + if err != nil { + return nil, err + } + + req.Header = transportConfiguration.GetRequestHeader() + + downResponse, err := httpClient.download.Do(req) + if err != nil { + // workaround for various connection pool related issues, mostly around + // HTTP/1.1. if the http client ever fails to send a request, we simply + // delete it entirely. + // in HTTP/1.1, it was observed that pool connections would immediately + // fail with "context canceled" if the previous http response body was + // not explicitly BOTH drained and closed. at the same time, sometimes + // the draining itself takes forever and causes more problems. + // see also https://github.com/golang/go/issues/60240 + destroyHTTPClient(ctx, dest, streamSettings) + return nil, newError("failed to send download http request, destroying client").Base(err) + } + + if downResponse.StatusCode != 200 { + downResponse.Body.Close() + return nil, newError("invalid status code on download:", downResponse.Status) + } + + uploadUrl := requestURL.String() + "?session=" + sessionId + "&seq=" + + uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(maxUploadSize)) + + go func() { + requestsLimiter := semaphore.New(int(maxConcurrentUploads)) + var requestCounter int64 + + // by offloading the uploads into a buffered pipe, multiple conn.Write + // calls get automatically batched together into larger POST requests. + // without batching, bandwidth is extremely limited. + for { + chunk, err := uploadPipeReader.ReadMultiBuffer() + if err != nil { + break + } + + <-requestsLimiter.Wait() + + url := uploadUrl + strconv.FormatInt(requestCounter, 10) + requestCounter += 1 + + go func() { + defer requestsLimiter.Signal() + req, err := http.NewRequest("POST", url, &buf.MultiBufferContainer{MultiBuffer: chunk}) + if err != nil { + newError("failed to send upload").Base(err).WriteToLog() + uploadPipeReader.Interrupt() + return + } + + req.Header = transportConfiguration.GetRequestHeader() + + if httpClient.isH2 { + resp, err := httpClient.upload.Do(req) + if err != nil { + newError("failed to send upload").Base(err).WriteToLog() + uploadPipeReader.Interrupt() + return + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + newError("failed to send upload, bad status code:", resp.Status).WriteToLog() + uploadPipeReader.Interrupt() + return + } + } else { + var err error + var uploadConn any + for i := 0; i < 5; i++ { + uploadConn = httpClient.uploadRawPool.Get() + if uploadConn == nil { + uploadConn, err = httpClient.dialUploadConn(ctx) + if err != nil { + newError("failed to connect upload").Base(err).WriteToLog() + uploadPipeReader.Interrupt() + return + } + } + + err = req.Write(uploadConn.(net.Conn)) + if err == nil { + break + } + } + + if err != nil { + newError("failed to send upload").Base(err).WriteToLog() + uploadPipeReader.Interrupt() + return + } + + httpClient.uploadRawPool.Put(uploadConn) + } + }() + + } + }() + + // skip "ok" response + trashHeader := []byte{0, 0} + _, err = io.ReadFull(downResponse.Body, trashHeader) + if err != nil { + downResponse.Body.Close() + return nil, newError("failed to read initial response") + } + + // necessary in order to send larger chunks in upload + bufferedUploadPipeWriter := buf.NewBufferedWriter(uploadPipeWriter) + bufferedUploadPipeWriter.SetBuffered(false) + + conn := splitConn{ + writer: bufferedUploadPipeWriter, + reader: downResponse.Body, + remoteAddr: remoteAddr, + localAddr: localAddr, + } + + return stat.Connection(&conn), nil +} diff --git a/xray-core/transport/internet/splithttp/errors.generated.go b/xray-core/transport/internet/splithttp/errors.generated.go new file mode 100644 index 0000000000..30fca9f6b4 --- /dev/null +++ b/xray-core/transport/internet/splithttp/errors.generated.go @@ -0,0 +1,9 @@ +package splithttp + +import "github.com/xtls/xray-core/common/errors" + +type errPathObjHolder struct{} + +func newError(values ...interface{}) *errors.Error { + return errors.New(values...).WithPathObj(errPathObjHolder{}) +} diff --git a/xray-core/transport/internet/splithttp/hub.go b/xray-core/transport/internet/splithttp/hub.go new file mode 100644 index 0000000000..1883bf237b --- /dev/null +++ b/xray-core/transport/internet/splithttp/hub.go @@ -0,0 +1,262 @@ +package splithttp + +import ( + "context" + "crypto/tls" + "io" + gonet "net" + "net/http" + "strconv" + "sync" + "time" + + "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/net" + http_proto "github.com/xtls/xray-core/common/protocol/http" + "github.com/xtls/xray-core/common/session" + "github.com/xtls/xray-core/common/signal/done" + "github.com/xtls/xray-core/transport/internet" + "github.com/xtls/xray-core/transport/internet/stat" + v2tls "github.com/xtls/xray-core/transport/internet/tls" +) + +type requestHandler struct { + host string + path string + ln *Listener + sessions sync.Map + localAddr gonet.TCPAddr +} + +func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { + if len(h.host) > 0 && request.Host != h.host { + newError("failed to validate host, request:", request.Host, ", config:", h.host).WriteToLog() + writer.WriteHeader(http.StatusNotFound) + return + } + if request.URL.Path != h.path { + newError("failed to validate path, request:", request.URL.Path, ", config:", h.path).WriteToLog() + writer.WriteHeader(http.StatusNotFound) + return + } + + queryString := request.URL.Query() + sessionId := queryString.Get("session") + if sessionId == "" { + newError("no sessionid on request:", request.URL.Path).WriteToLog() + writer.WriteHeader(http.StatusBadRequest) + return + } + + forwardedAddrs := http_proto.ParseXForwardedFor(request.Header) + remoteAddr, err := gonet.ResolveTCPAddr("tcp", request.RemoteAddr) + if err != nil { + remoteAddr = &gonet.TCPAddr{} + } + if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() { + remoteAddr = &net.TCPAddr{ + IP: forwardedAddrs[0].IP(), + Port: int(0), + } + } + + if request.Method == "POST" { + uploadQueue, ok := h.sessions.Load(sessionId) + if !ok { + newError("sessionid does not exist").WriteToLog() + writer.WriteHeader(http.StatusBadRequest) + return + } + + seq := queryString.Get("seq") + if seq == "" { + newError("no seq on request:", request.URL.Path).WriteToLog() + writer.WriteHeader(http.StatusBadRequest) + return + } + + payload, err := io.ReadAll(request.Body) + if err != nil { + newError("failed to upload").Base(err).WriteToLog() + writer.WriteHeader(http.StatusInternalServerError) + return + } + + seqInt, err := strconv.ParseUint(seq, 10, 64) + if err != nil { + newError("failed to upload").Base(err).WriteToLog() + writer.WriteHeader(http.StatusInternalServerError) + return + } + + err = uploadQueue.(*UploadQueue).Push(Packet{ + Payload: payload, + Seq: seqInt, + }) + + if err != nil { + newError("failed to upload").Base(err).WriteToLog() + writer.WriteHeader(http.StatusInternalServerError) + return + } + + writer.WriteHeader(http.StatusOK) + } else if request.Method == "GET" { + responseFlusher, ok := writer.(http.Flusher) + if !ok { + panic("expected http.ResponseWriter to be an http.Flusher") + } + + uploadQueue := NewUploadQueue(int(2 * h.ln.config.GetNormalizedMaxConcurrentUploads())) + + h.sessions.Store(sessionId, uploadQueue) + // the connection is finished, clean up map + defer h.sessions.Delete(sessionId) + + // magic header instructs nginx + apache to not buffer response body + writer.Header().Set("X-Accel-Buffering", "no") + writer.WriteHeader(http.StatusOK) + // send a chunk immediately to enable CDN streaming. + // many CDN buffer the response headers until the origin starts sending + // the body, with no way to turn it off. + writer.Write([]byte("ok")) + responseFlusher.Flush() + + downloadDone := done.New() + + conn := splitConn{ + writer: &httpResponseBodyWriter{ + responseWriter: writer, + downloadDone: downloadDone, + responseFlusher: responseFlusher, + }, + reader: uploadQueue, + remoteAddr: remoteAddr, + } + + h.ln.addConn(stat.Connection(&conn)) + + // "A ResponseWriter may not be used after [Handler.ServeHTTP] has returned." + <-downloadDone.Wait() + + } else { + writer.WriteHeader(http.StatusMethodNotAllowed) + } +} + +type httpResponseBodyWriter struct { + sync.Mutex + responseWriter http.ResponseWriter + responseFlusher http.Flusher + downloadDone *done.Instance +} + +func (c *httpResponseBodyWriter) Write(b []byte) (int, error) { + c.Lock() + defer c.Unlock() + if c.downloadDone.Done() { + return 0, io.ErrClosedPipe + } + n, err := c.responseWriter.Write(b) + if err == nil { + c.responseFlusher.Flush() + } + return n, err +} + +func (c *httpResponseBodyWriter) Close() error { + c.Lock() + defer c.Unlock() + c.downloadDone.Close() + return nil +} + +type Listener struct { + sync.Mutex + server http.Server + listener net.Listener + config *Config + addConn internet.ConnHandler +} + +func ListenSH(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, addConn internet.ConnHandler) (internet.Listener, error) { + l := &Listener{ + addConn: addConn, + } + shSettings := streamSettings.ProtocolSettings.(*Config) + l.config = shSettings + if l.config != nil { + if streamSettings.SocketSettings == nil { + streamSettings.SocketSettings = &internet.SocketConfig{} + } + } + var listener net.Listener + var err error + var localAddr = gonet.TCPAddr{} + + if port == net.Port(0) { // unix + listener, err = internet.ListenSystem(ctx, &net.UnixAddr{ + Name: address.Domain(), + Net: "unix", + }, streamSettings.SocketSettings) + if err != nil { + return nil, newError("failed to listen unix domain socket(for SH) on ", address).Base(err) + } + newError("listening unix domain socket(for SH) on ", address).WriteToLog(session.ExportIDToError(ctx)) + } else { // tcp + localAddr = gonet.TCPAddr{ + IP: address.IP(), + Port: int(port), + } + listener, err = internet.ListenSystem(ctx, &net.TCPAddr{ + IP: address.IP(), + Port: int(port), + }, streamSettings.SocketSettings) + if err != nil { + return nil, newError("failed to listen TCP(for SH) on ", address, ":", port).Base(err) + } + newError("listening TCP(for SH) on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx)) + } + + if config := v2tls.ConfigFromStreamSettings(streamSettings); config != nil { + if tlsConfig := config.GetTLSConfig(); tlsConfig != nil { + listener = tls.NewListener(listener, tlsConfig) + } + } + + l.listener = listener + + l.server = http.Server{ + Handler: &requestHandler{ + host: shSettings.Host, + path: shSettings.GetNormalizedPath(), + ln: l, + sessions: sync.Map{}, + localAddr: localAddr, + }, + ReadHeaderTimeout: time.Second * 4, + MaxHeaderBytes: 8192, + } + + go func() { + if err := l.server.Serve(l.listener); err != nil { + newError("failed to serve http for splithttp").Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx)) + } + }() + + return l, err +} + +// Addr implements net.Listener.Addr(). +func (ln *Listener) Addr() net.Addr { + return ln.listener.Addr() +} + +// Close implements net.Listener.Close(). +func (ln *Listener) Close() error { + return ln.listener.Close() +} + +func init() { + common.Must(internet.RegisterTransportListener(protocolName, ListenSH)) +} diff --git a/xray-core/transport/internet/splithttp/splithttp.go b/xray-core/transport/internet/splithttp/splithttp.go new file mode 100644 index 0000000000..55d230dfef --- /dev/null +++ b/xray-core/transport/internet/splithttp/splithttp.go @@ -0,0 +1,17 @@ +package splithttp + +import ( + "context" + + "github.com/xtls/xray-core/common" +) + +//go:generate go run github.com/xtls/xray-core/common/errors/errorgen + +const protocolName = "splithttp" + +func init() { + common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return nil, newError("splithttp is a transport protocol.") + })) +} diff --git a/xray-core/transport/internet/splithttp/splithttp_test.go b/xray-core/transport/internet/splithttp/splithttp_test.go new file mode 100644 index 0000000000..3d3d387c95 --- /dev/null +++ b/xray-core/transport/internet/splithttp/splithttp_test.go @@ -0,0 +1,154 @@ +package splithttp_test + +import ( + "context" + "fmt" + "runtime" + "testing" + "time" + + "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/net" + "github.com/xtls/xray-core/common/protocol/tls/cert" + "github.com/xtls/xray-core/testing/servers/tcp" + "github.com/xtls/xray-core/transport/internet" + . "github.com/xtls/xray-core/transport/internet/splithttp" + "github.com/xtls/xray-core/transport/internet/stat" + "github.com/xtls/xray-core/transport/internet/tls" +) + +func Test_listenSHAndDial(t *testing.T) { + listenPort := tcp.PickPort() + listen, err := ListenSH(context.Background(), net.LocalHostIP, listenPort, &internet.MemoryStreamConfig{ + ProtocolName: "splithttp", + ProtocolSettings: &Config{ + Path: "/sh", + }, + }, func(conn stat.Connection) { + go func(c stat.Connection) { + defer c.Close() + + var b [1024]byte + _, err := c.Read(b[:]) + if err != nil { + return + } + + common.Must2(c.Write([]byte("Response"))) + }(conn) + }) + common.Must(err) + ctx := context.Background() + streamSettings := &internet.MemoryStreamConfig{ + ProtocolName: "splithttp", + ProtocolSettings: &Config{Path: "sh"}, + } + conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), listenPort), streamSettings) + + common.Must(err) + _, err = conn.Write([]byte("Test connection 1")) + common.Must(err) + + var b [1024]byte + fmt.Println("test2") + n, _ := conn.Read(b[:]) + fmt.Println("string is", n) + if string(b[:n]) != "Response" { + t.Error("response: ", string(b[:n])) + } + + common.Must(conn.Close()) + <-time.After(time.Second * 5) + conn, err = Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), listenPort), streamSettings) + common.Must(err) + _, err = conn.Write([]byte("Test connection 2")) + common.Must(err) + n, _ = conn.Read(b[:]) + common.Must(err) + if string(b[:n]) != "Response" { + t.Error("response: ", string(b[:n])) + } + common.Must(conn.Close()) + + common.Must(listen.Close()) +} + +func TestDialWithRemoteAddr(t *testing.T) { + listenPort := tcp.PickPort() + listen, err := ListenSH(context.Background(), net.LocalHostIP, listenPort, &internet.MemoryStreamConfig{ + ProtocolName: "splithttp", + ProtocolSettings: &Config{ + Path: "sh", + }, + }, func(conn stat.Connection) { + go func(c stat.Connection) { + defer c.Close() + + var b [1024]byte + _, err := c.Read(b[:]) + // common.Must(err) + if err != nil { + return + } + + _, err = c.Write([]byte("Response")) + common.Must(err) + }(conn) + }) + common.Must(err) + + conn, err := Dial(context.Background(), net.TCPDestination(net.DomainAddress("localhost"), listenPort), &internet.MemoryStreamConfig{ + ProtocolName: "splithttp", + ProtocolSettings: &Config{Path: "sh", Header: map[string]string{"X-Forwarded-For": "1.1.1.1"}}, + }) + + common.Must(err) + _, err = conn.Write([]byte("Test connection 1")) + common.Must(err) + + var b [1024]byte + n, _ := conn.Read(b[:]) + if string(b[:n]) != "Response" { + t.Error("response: ", string(b[:n])) + } + + common.Must(listen.Close()) +} + +func Test_listenSHAndDial_TLS(t *testing.T) { + if runtime.GOARCH == "arm64" { + return + } + + listenPort := tcp.PickPort() + + start := time.Now() + + streamSettings := &internet.MemoryStreamConfig{ + ProtocolName: "splithttp", + ProtocolSettings: &Config{ + Path: "shs", + }, + SecurityType: "tls", + SecuritySettings: &tls.Config{ + AllowInsecure: true, + Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil, cert.CommonName("localhost")))}, + }, + } + listen, err := ListenSH(context.Background(), net.LocalHostIP, listenPort, streamSettings, func(conn stat.Connection) { + go func() { + _ = conn.Close() + }() + }) + common.Must(err) + defer listen.Close() + + conn, err := Dial(context.Background(), net.TCPDestination(net.DomainAddress("localhost"), listenPort), streamSettings) + common.Must(err) + _ = conn.Close() + + end := time.Now() + if !end.Before(start.Add(time.Second * 5)) { + t.Error("end: ", end, " start: ", start) + } +} diff --git a/xray-core/transport/internet/splithttp/upload_queue.go b/xray-core/transport/internet/splithttp/upload_queue.go new file mode 100644 index 0000000000..8b2c8f3632 --- /dev/null +++ b/xray-core/transport/internet/splithttp/upload_queue.go @@ -0,0 +1,120 @@ +package splithttp + +// upload_queue is a specialized priorityqueue + channel to reorder generic +// packets by a sequence number + +import ( + "container/heap" + "io" +) + +type Packet struct { + Payload []byte + Seq uint64 +} + +type UploadQueue struct { + pushedPackets chan Packet + heap uploadHeap + nextSeq uint64 + closed bool + maxPackets int +} + +func NewUploadQueue(maxPackets int) *UploadQueue { + return &UploadQueue{ + pushedPackets: make(chan Packet, maxPackets), + heap: uploadHeap{}, + nextSeq: 0, + closed: false, + maxPackets: maxPackets, + } +} + +func (h *UploadQueue) Push(p Packet) error { + if h.closed { + return newError("splithttp packet queue closed") + } + + h.pushedPackets <- p + return nil +} + +func (h *UploadQueue) Close() error { + h.closed = true + close(h.pushedPackets) + return nil +} + +func (h *UploadQueue) Read(b []byte) (int, error) { + if h.closed && len(h.heap) == 0 && len(h.pushedPackets) == 0 { + return 0, io.EOF + } + + needMorePackets := false + + if len(h.heap) > 0 { + packet := heap.Pop(&h.heap).(Packet) + n := 0 + + if packet.Seq == h.nextSeq { + copy(b, packet.Payload) + n = min(len(b), len(packet.Payload)) + + if n < len(packet.Payload) { + // partial read + packet.Payload = packet.Payload[n:] + heap.Push(&h.heap, packet) + } else { + h.nextSeq = packet.Seq + 1 + } + + return n, nil + } + + // misordered packet + if packet.Seq > h.nextSeq { + if len(h.heap) > h.maxPackets { + // the "reassembly buffer" is too large, and we want to + // constrain memory usage somehow. let's tear down the + // connection, and hope the application retries. + return 0, newError("packet queue is too large") + } + heap.Push(&h.heap, packet) + needMorePackets = true + } + } else { + needMorePackets = true + } + + if needMorePackets { + packet, more := <-h.pushedPackets + if !more { + return 0, io.EOF + } + heap.Push(&h.heap, packet) + } + + return 0, nil +} + +// heap code directly taken from https://pkg.go.dev/container/heap +type uploadHeap []Packet + +func (h uploadHeap) Len() int { return len(h) } +func (h uploadHeap) Less(i, j int) bool { return h[i].Seq < h[j].Seq } +func (h uploadHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } + +func (h *uploadHeap) Push(x any) { + // Push and Pop use pointer receivers because they modify the slice's length, + // not just its contents. + *h = append(*h, x.(Packet)) +} + +func (h *uploadHeap) Pop() any { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} diff --git a/yass/.github/workflows/releases-rpm.yml b/yass/.github/workflows/releases-rpm.yml index 4dd7a35c29..8742f92773 100644 --- a/yass/.github/workflows/releases-rpm.yml +++ b/yass/.github/workflows/releases-rpm.yml @@ -269,9 +269,9 @@ jobs: rm -f *.tar.gz - name: Build TGZ packages run: | - ./tools/build --arch ${{ matrix.arch }} --system linux --subsystem musl \ - --sysroot "${{ env.SDK_ROOT }}" \ - -build-test --cmake-build-type MinSizeRel + ./tools/build --variant cli --arch ${{ matrix.arch }} --system linux --subsystem musl --sysroot "${{ env.SDK_ROOT }}" -build-test --cmake-build-type MinSizeRel -nc + ./tools/build --variant server --arch ${{ matrix.arch }} --system linux --subsystem musl --sysroot "${{ env.SDK_ROOT }}" -build-test --cmake-build-type MinSizeRel -nc + ./tools/build --variant gui --arch ${{ matrix.arch }} --system linux --subsystem musl --sysroot "${{ env.SDK_ROOT }}" -build-test --cmake-build-type MinSizeRel -nc - name: Run tests run: | bwrap --die-with-parent --bind "${{ env.SDK_ROOT }}" / \ diff --git a/yass/CMakeLists.txt b/yass/CMakeLists.txt index b9f41edb58..bf59956210 100644 --- a/yass/CMakeLists.txt +++ b/yass/CMakeLists.txt @@ -2357,6 +2357,8 @@ endif() set(ABSL_PROPAGATE_CXX_STD "ON" CACHE STRING "") # override abseil-cpp options include_directories(third_party/abseil-cpp-override) +# override system's abseil-cpp +include_directories(third_party/abseil-cpp) # force win32 thread model for libc++ usage if (MINGW AND USE_LIBCXX) # force non-inline emulated-tls diff --git a/yass/README.md b/yass/README.md index 219cbda439..68be1c1609 100644 --- a/yass/README.md +++ b/yass/README.md @@ -1,84 +1,72 @@ # Yet Another Shadow Socket +yass is an efficient forward proxy client supporting http/socks4/socks4a/socks5/socks5h protocol running on PC and mobile devices. + +## License [![License](https://img.shields.io/github/license/Chilledheart/yass)][license-link] + +## Releases + +[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Chilledheart/yass)](https://github.com/Chilledheart/yass/releases) [![Language: C++](https://img.shields.io/github/languages/top/Chilledheart/yass.svg)](https://github.com/Chilledheart/yass/search?l=cpp) [![GitHub release (latest by SemVer)](https://img.shields.io/github/downloads/Chilledheart/yass/latest/total)](https://github.com/Chilledheart/yass/releases/latest) -[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Chilledheart/yass)](https://github.com/Chilledheart/yass/releases) -[![homebrew cask](https://img.shields.io/homebrew/cask/v/yass)](https://formulae.brew.sh/cask/yass) +More details are at [Latest Release Page](https://github.com/Chilledheart/yass/releases/tag/1.11.2) + +### Prebuilt binaries (Linux) +- GTK3 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk3.el7.x86_64.1.11.2.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk3-ubuntu-16.04-xenial_amd64.1.11.2.deb) (require glibc >= 2.16) +- Qt5 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-qt5.el7.x86_64.1.11.2.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-qt5-ubuntu-16.04-xenial_amd64.1.11.2.deb) (require glibc >= 2.16) +- GTK4 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk4.el9.x86_64.1.11.2.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk4-ubuntu-22.04-jammy_amd64.1.11.2.deb) (require glibc >= 2.34) +- Qt6 download rpm or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-qt6-ubuntu-22.04-jammy_amd64.1.11.2.deb) (require glibc >= 2.36) -[![aur yass-proxy](https://img.shields.io/aur/version/yass-proxy)](https://aur.archlinux.org/packages/yass-proxy) [![aur yass-proxy-gtk3](https://img.shields.io/aur/version/yass-proxy-gtk3)](https://aur.archlinux.org/packages/yass-proxy-gtk3) +[![aur yass-proxy-qt5](https://img.shields.io/aur/version/yass-proxy-qt5)](https://aur.archlinux.org/packages/yass-proxy-qt5) +[![aur yass-proxy](https://img.shields.io/aur/version/yass-proxy)](https://aur.archlinux.org/packages/yass-proxy) [![aur yass-proxy-qt6](https://img.shields.io/aur/version/yass-proxy-qt6)](https://aur.archlinux.org/packages/yass-proxy-qt6) + +See [Status of Package Store](https://github.com/Chilledheart/yass/wiki/Status-of-Package-Store) for more. + +- CLI [download tgz for amd64](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-release-amd64-1.11.1.tgz) or [download tgz for i386](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-release-amd64-1.11.1.tgz) or [download tgz for arm64](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-release-arm64-1.11.1.tgz) (require glibc >= 2.25) +- CLI [download tgz for loongarch64](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-release-loongarch64-1.11.1.tgz) (require glibc >= 2.38, require new world) +- CLI [download tgz for riscv64](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-release-riscv64-1.11.1.tgz) or [download tgz for riscv32](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-release-riscv32-1.11.1.tgz) (require glibc >= 2.36) +- CLI(openwrt) [download tgz for amd64](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-openwrt-release-x86_64-1.11.1.tgz) or [download tgz for i386](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-openwrt-release-i486-1.11.1.tgz) or [download tgz for aarch64 generic](https://github.com/Chilledheart/yass/releases/download/1.11.1/yass_cli-linux-openwrt-release-aarch64-1.11.1.tgz) (require openwrt >= 23.05.3) +- CLI(musl) download tgz for amd64 or download tgz for i386 (require musl >= 1.2.5) + [![aur yass-proxy-cli](https://img.shields.io/aur/version/yass-proxy-cli)](https://aur.archlinux.org/packages/yass-proxy-cli) -yass is an efficient forward proxy client supporting http/socks4/socks4a/socks5 protocol running on PC and mobile devices. +### Prebuilt binaries (Other platforms) +- Android [download apk](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-android-release-arm64-1.11.2.apk) or [download 32-bit apk](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-android-release-arm-1.11.2.apk) +- iOS [Join via TestFlight](https://testflight.apple.com/join/6AkiEq09) +- Windows [download installer](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-mingw-win7-release-x86_64-1.11.2-system-installer.exe) [(require KB2999226 below windows 10)][KB2999226] or [download 32-bit installer](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-mingw-winxp-release-i686-1.11.2-system-installer.exe) [(require vc 2010 runtime)][vs2010_x86] or [download woa arm64 installer](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-mingw-release-aarch64-1.11.2-system-installer.exe) +- macOS [download intel dmg](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-macos-release-x64-1.11.2.dmg) or [download apple silicon dmg](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-macos-release-arm64-1.11.2.dmg) +> via homebrew: `brew install --cask yass` -## License -[GPLv2-only][license-link] - -## Features - -### Android/iOS/macOS (M1/M2/M3 only) comes with VPN Service support -Mobile users including macOS (M1/M2/M3) machines use YASS as VPN Service more than Global Proxy. +[![homebrew cask](https://img.shields.io/homebrew/cask/v/yass)](https://formulae.brew.sh/cask/yass) See [Supporteded Operating System](https://github.com/Chilledheart/yass/wiki/Supported-Operating-System) for more. -See [Status of Package Store](https://github.com/Chilledheart/yass/wiki/Status-of-Package-Store) for more. + +### Build from Source +Take a look at [build instructions](BUILDING.md) and [packaging instructions](PACKAGING.md). + +## Highlight Features ### Post Quantum Kyber Support Post Quantum Kyber Support (not enabled by default) is added on all of supported Platforms. See [Protecting Chrome Traffic with Hybrid Kyber KEM](https://blog.chromium.org/2023/08/protecting-chrome-traffic-with-hybrid.html) for more. -### Prebuilt binaries -- Android [download apk](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-android-release-arm64-1.11.2.apk) or [download 32-bit apk](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-android-release-arm-1.11.2.apk) -- iOS [join via TestFlight](https://testflight.apple.com/join/6AkiEq09) -- Windows [download installer](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-mingw-win7-release-x86_64-1.11.2-system-installer.exe) [(require KB2999226 below windows 10)][KB2999226] or [download 32-bit installer](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-mingw-winxp-release-i686-1.11.2-system-installer.exe) [(require vc 2010 runtime)][vs2010_x86] or [download woa arm64 installer](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-mingw-release-aarch64-1.11.2-system-installer.exe) -- macOS [download intel dmg](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-macos-release-x64-1.11.2.dmg) or [download apple silicon dmg](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-macos-release-arm64-1.11.2.dmg) -> via homebrew: `brew install --cask yass` -- Linux/GTK3 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk3.el7.x86_64.1.11.2.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk3-ubuntu-16.04-xenial_amd64.1.11.2.deb) (require glibc >= 2.16) -- Linux/Qt5 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-qt5.el7.x86_64.1.11.2.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-qt5-ubuntu-16.04-xenial_amd64.1.11.2.deb) (require glibc >= 2.16) -- Linux/GTK4 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk4.el9.x86_64.1.11.2.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-gtk4-ubuntu-22.04-jammy_amd64.1.11.2.deb) (require glibc >= 2.34) -- Linux/Qt6 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-qt6.fc39.x86_64.1.11.2.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.2/yass-qt6-ubuntu-22.04-jammy_amd64.1.11.2.deb) (require glibc >= 2.36) - -View more at [Release Page](https://github.com/Chilledheart/yass/releases/tag/1.11.2) - ### NaïveProxy-Compatible Protocol Support Cipher http2 and https are NaïveProxy-compatible. See [NaïveProxy](https://github.com/klzgrad/naiveproxy)'s project homepage for support. -## Usages +### Android/iOS/macOS (M1/M2/M3 only) comes with VPN Service support +Mobile users including macOS (M1/M2/M3) machines can use yass as VPN Service more than just Global Proxy. + +### More Usages Visit wiki's [Usages](https://github.com/Chilledheart/yass/wiki/Usage). -## Build from Source -Take a look at [instructions](BUILDING.md). - -## Sponsor Me -Please visit [the pages site](https://letshack.info). - -## Build Status - -[![Compiler Compatibility](https://github.com/Chilledheart/yass/actions/workflows/compiler.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/compiler.yml) -[![CircleCI](https://img.shields.io/circleci/build/github/Chilledheart/yass/develop?logo=circleci&&label=Sanitizers%20and%20Ubuntu%20arm)](https://circleci.com/gh/Chilledheart/yass/?branch=develop) -[![Cirrus CI](https://img.shields.io/cirrus/github/Chilledheart/yass/develop?logo=cirrusci&&label=FreeBSD%20and%20macOS)](https://cirrus-ci.com/github/Chilledheart/yass/develop) - -[![MinGW Build](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw-new.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw-new.yml) -[![Linux Build](https://github.com/Chilledheart/yass/actions/workflows/releases-linux-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-linux-binary.yml) -[![macOS Build](https://github.com/Chilledheart/yass/actions/workflows/releases-macos.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-macos.yml) - -[![Android Build](https://github.com/Chilledheart/yass/actions/workflows/releases-android-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-android-binary.yml) -[![iOS Build](https://github.com/Chilledheart/yass/actions/workflows/releases-ios.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-ios.yml) - -[![OpenWRT Build](https://github.com/Chilledheart/yass/actions/workflows/releases-openwrt-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-openwrt-binary.yml) -[![FreeBSD Build](https://github.com/Chilledheart/yass/actions/workflows/releases-freebsd-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-freebsd-binary.yml) -[![RPM Build](https://github.com/Chilledheart/yass/actions/workflows/releases-rpm.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-rpm.yml) -[![DEB Build](https://github.com/Chilledheart/yass/actions/workflows/releases-deb.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-deb.yml) - -[![MSVC Build](https://github.com/Chilledheart/yass/actions/workflows/releases-windows.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-windows.yml) -[![Old MinGW Build](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw.yml) - -## Additional Features +## Extra Features (Limited) ### SOCKS cipher Support Experimental socks4/socks4a/socks5/socks5h cipher support is added for both of CLI and GUI. @@ -112,6 +100,30 @@ See more at manpage _yass_server(1)_ See [Server Usage](https://github.com/Chilledheart/yass/wiki/Usage:-server-setup) for more. +## Sponsor Me +Please visit [the pages site](https://letshack.info). + +## Build Status + +[![Compiler Compatibility](https://github.com/Chilledheart/yass/actions/workflows/compiler.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/compiler.yml) +[![CircleCI](https://img.shields.io/circleci/build/github/Chilledheart/yass/develop?logo=circleci&&label=Sanitizers%20and%20Ubuntu%20arm)](https://circleci.com/gh/Chilledheart/yass/?branch=develop) +[![Cirrus CI](https://img.shields.io/cirrus/github/Chilledheart/yass/develop?logo=cirrusci&&label=FreeBSD%20and%20macOS)](https://cirrus-ci.com/github/Chilledheart/yass/develop) + +[![MinGW Build](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw-new.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw-new.yml) +[![Linux Build](https://github.com/Chilledheart/yass/actions/workflows/releases-linux-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-linux-binary.yml) +[![macOS Build](https://github.com/Chilledheart/yass/actions/workflows/releases-macos.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-macos.yml) + +[![Android Build](https://github.com/Chilledheart/yass/actions/workflows/releases-android-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-android-binary.yml) +[![iOS Build](https://github.com/Chilledheart/yass/actions/workflows/releases-ios.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-ios.yml) + +[![OpenWRT Build](https://github.com/Chilledheart/yass/actions/workflows/releases-openwrt-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-openwrt-binary.yml) +[![FreeBSD Build](https://github.com/Chilledheart/yass/actions/workflows/releases-freebsd-binary.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-freebsd-binary.yml) +[![RPM Build](https://github.com/Chilledheart/yass/actions/workflows/releases-rpm.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-rpm.yml) +[![DEB Build](https://github.com/Chilledheart/yass/actions/workflows/releases-deb.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-deb.yml) + +[![MSVC Build](https://github.com/Chilledheart/yass/actions/workflows/releases-windows.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-windows.yml) +[![Old MinGW Build](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw.yml/badge.svg)](https://github.com/Chilledheart/yass/actions/workflows/releases-mingw.yml) + [license-link]: LICENSE [KB2999226]: https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c [vs2010_x86]: https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe diff --git a/yass/cmake/platforms/FreeBSD.cmake b/yass/cmake/platforms/FreeBSD.cmake index e7723e038a..9f76926c7e 100644 --- a/yass/cmake/platforms/FreeBSD.cmake +++ b/yass/cmake/platforms/FreeBSD.cmake @@ -11,9 +11,9 @@ set(CMAKE_CXX_COMPILER_RANLIB "${LLVM_SYSROOT}/bin/llvm-ranlib" CACHE FILEPATH " set(CMAKE_SYSROOT "${GCC_SYSROOT}" CACHE STRING "") -set(CMAKE_MODULE_LINKER_FLAGS "-Wl,-L${CMAKE_SOURCE_DIR}/third_party/libc++/freebsd") -set(CMAKE_EXE_LINKER_FLAGS "-Wl,-L${CMAKE_SOURCE_DIR}/third_party/libc++/freebsd") -set(CMAKE_REQUIRED_LINK_OPTIONS -Wl,-L${CMAKE_SOURCE_DIR}/third_party/libc++/freebsd) +set(CMAKE_MODULE_LINKER_FLAGS "-Wl,-L${CMAKE_SOURCE_DIR}/third_party/libc++/freebsd -fuse-ld=lld") +set(CMAKE_EXE_LINKER_FLAGS "-Wl,-L${CMAKE_SOURCE_DIR}/third_party/libc++/freebsd -fuse-ld=lld") +set(CMAKE_REQUIRED_LINK_OPTIONS -Wl,-L${CMAKE_SOURCE_DIR}/third_party/libc++/freebsd -fuse-ld=lld) # target environment on the build host system set(CMAKE_FIND_ROOT_PATH "${GCC_SYSROOT}") diff --git a/yass/debian/control b/yass/debian/control index 7338d1a2c1..8fa6c746f1 100644 --- a/yass/debian/control +++ b/yass/debian/control @@ -11,9 +11,9 @@ Build-Depends: golang:native, ninja-build:native, debhelper (>= 9), - ca-certificates, pkg-config, zlib1g-dev, + libcurl4-openssl-dev , libglib2.0-dev , libgtk-3-dev , libglib2.0-dev , @@ -29,9 +29,12 @@ Package: yass Architecture: any Pre-Depends: ${misc:Pre-Depends} Build-Profiles: -Recommends: ca-certificates +Recommends: + libappindicator3-1 , + libayatana-appindicator3-1 Depends: lsb-base (>= 3.0-6), + ca-certificates, ${misc:Depends}, ${shlibs:Depends} Description: lightweight and secure http/socks4/socks5 proxy @@ -53,6 +56,7 @@ Architecture: any Pre-Depends: ${misc:Pre-Depends} Depends: lsb-base (>= 3.0-6), + ca-certificates, ${misc:Depends}, ${shlibs:Depends} Recommends: ca-certificates @@ -74,6 +78,7 @@ Architecture: any Pre-Depends: ${misc:Pre-Depends} Depends: lsb-base (>= 3.0-6), + ca-certificates, ${misc:Depends}, ${shlibs:Depends} Recommends: ca-certificates diff --git a/yass/src/gtk/app-indicator-override.c b/yass/src/gtk/app-indicator-override.c index 86c9cbcb94..c9c6e3dd20 100644 --- a/yass/src/gtk/app-indicator-override.c +++ b/yass/src/gtk/app-indicator-override.c @@ -6,6 +6,7 @@ #include extern int app_indicator_init(void); +extern void app_indicator_uninit(void); extern int app_indicator_get_type(void); extern void* app_indicator_new(const char*, const char*, int); @@ -27,7 +28,10 @@ int app_indicator_init(void) { if (app_indicator_lib != NULL) { return 0; } - app_indicator_lib = dlopen("libappindicator3.so.1", RTLD_LAZY); + app_indicator_lib = dlopen("libayatana-appindicator3.so.1", RTLD_LAZY); + if (app_indicator_lib == NULL) { + app_indicator_lib = dlopen("libappindicator3.so.1", RTLD_LAZY); + } if (app_indicator_lib != NULL) { o_app_indicator_get_type = dlsym(app_indicator_lib, "app_indicator_get_type"); o_app_indicator_new = dlsym(app_indicator_lib, "app_indicator_new"); @@ -39,19 +43,25 @@ int app_indicator_init(void) { if (o_app_indicator_get_type == NULL || o_app_indicator_new == NULL || o_app_indicator_new_with_path == NULL || o_app_indicator_set_status == NULL || o_app_indicator_set_menu == NULL || o_app_indicator_set_secondary_activate_target == NULL) { - o_app_indicator_get_type = NULL; - o_app_indicator_new = NULL; - o_app_indicator_new_with_path = NULL; - o_app_indicator_set_status = NULL; - o_app_indicator_set_menu = NULL; - o_app_indicator_set_secondary_activate_target = NULL; - dlclose(app_indicator_lib); - app_indicator_lib = NULL; + app_indicator_uninit(); } } return app_indicator_lib == NULL ? -1 : 0; } +void app_indicator_uninit(void) { + if (app_indicator_lib != NULL) { + o_app_indicator_get_type = NULL; + o_app_indicator_new = NULL; + o_app_indicator_new_with_path = NULL; + o_app_indicator_set_status = NULL; + o_app_indicator_set_menu = NULL; + o_app_indicator_set_secondary_activate_target = NULL; + dlclose(app_indicator_lib); + app_indicator_lib = NULL; + } +} + int app_indicator_get_type(void) { assert(o_app_indicator_get_type && "app_indicator_init is required to call first"); diff --git a/yass/src/gtk/yass_window.cpp b/yass/src/gtk/yass_window.cpp index fffce95d89..4ff6fbeeb0 100644 --- a/yass/src/gtk/yass_window.cpp +++ b/yass/src/gtk/yass_window.cpp @@ -19,6 +19,7 @@ #ifdef HAVE_APP_INDICATOR extern "C" int app_indicator_init(); +extern "C" void app_indicator_uninit(); #include "third_party/libappindicator/app-indicator.h" #endif @@ -259,6 +260,12 @@ YASSWindow::~YASSWindow() { if (tray_icon_) { g_object_unref(G_OBJECT(tray_icon_)); } +#ifdef HAVE_APP_INDICATOR + if (tray_indicator_) { + g_object_unref(G_OBJECT(tray_indicator_)); + } + app_indicator_uninit(); +#endif } void YASSWindow::CreateStatusIcon() { diff --git a/yass/src/gtk/yass_window.hpp b/yass/src/gtk/yass_window.hpp index e03a75b9da..5ad74f25c9 100644 --- a/yass/src/gtk/yass_window.hpp +++ b/yass/src/gtk/yass_window.hpp @@ -62,7 +62,7 @@ class YASSWindow { G_GNUC_END_IGNORE_DEPRECATIONS #ifdef HAVE_APP_INDICATOR - GObject* tray_indicator_; + GObject* tray_indicator_ = nullptr; #endif public: