Update On Mon Oct 7 20:33:43 CEST 2024

This commit is contained in:
github-action[bot]
2024-10-07 20:33:44 +02:00
parent d52a909dcb
commit fd37c3e1de
1173 changed files with 17994 additions and 11185 deletions

1
.github/update.log vendored
View File

@@ -786,3 +786,4 @@ Update On Thu Oct 3 20:36:48 CEST 2024
Update On Fri Oct 4 20:35:09 CEST 2024
Update On Sat Oct 5 20:31:49 CEST 2024
Update On Sun Oct 6 20:31:42 CEST 2024
Update On Mon Oct 7 20:33:33 CEST 2024

View File

@@ -53,7 +53,7 @@
"@csstools/normalize.css": "12.1.1",
"@emotion/babel-plugin": "11.12.0",
"@emotion/react": "11.13.3",
"@iconify/json": "2.2.256",
"@iconify/json": "2.2.257",
"@monaco-editor/react": "4.6.0",
"@tanstack/react-router": "1.62.1",
"@tanstack/router-devtools": "1.62.1",
@@ -76,7 +76,7 @@
"monaco-yaml": "5.2.2",
"nanoid": "5.0.7",
"sass": "1.79.4",
"shiki": "1.21.1",
"shiki": "1.22.0",
"tailwindcss-textshadow": "2.1.3",
"unplugin-auto-import": "0.18.3",
"unplugin-icons": "0.19.3",

View File

@@ -2,7 +2,7 @@
"manifest_version": 1,
"latest": {
"mihomo": "v1.18.9",
"mihomo_alpha": "alpha-8e6eb70",
"mihomo_alpha": "alpha-9fd63fe",
"clash_rs": "v0.5.0",
"clash_premium": "2023-09-05-gdcc8d87",
"clash_rs_alpha": "0.5.0-alpha+sha.801972b"
@@ -69,5 +69,5 @@
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
}
},
"updated_at": "2024-10-05T22:20:52.009Z"
"updated_at": "2024-10-06T22:20:32.722Z"
}

View File

@@ -82,7 +82,7 @@
"eslint-plugin-react": "7.37.0",
"eslint-plugin-react-compiler": "0.0.0-experimental-f444e11-20240926",
"eslint-plugin-react-hooks": "4.6.2",
"knip": "5.31.0",
"knip": "5.32.0",
"lint-staged": "15.2.10",
"npm-run-all2": "6.2.3",
"postcss": "8.4.47",

View File

@@ -96,8 +96,8 @@ importers:
specifier: 4.6.2
version: 4.6.2(eslint@8.57.1)
knip:
specifier: 5.31.0
version: 5.31.0(@types/node@22.7.4)(typescript@5.6.2)
specifier: 5.32.0
version: 5.32.0(@types/node@22.7.4)(typescript@5.6.2)
lint-staged:
specifier: 15.2.10
version: 15.2.10
@@ -308,8 +308,8 @@ importers:
specifier: 11.13.3
version: 11.13.3(react@19.0.0-rc-1460d67c-20241003)(types-react@19.0.0-rc.1)
'@iconify/json':
specifier: 2.2.256
version: 2.2.256
specifier: 2.2.257
version: 2.2.257
'@monaco-editor/react':
specifier: 4.6.0
version: 4.6.0(monaco-editor@0.52.0)(react-dom@19.0.0-rc-1460d67c-20241003(react@19.0.0-rc-1460d67c-20241003))(react@19.0.0-rc-1460d67c-20241003)
@@ -377,8 +377,8 @@ importers:
specifier: 1.79.4
version: 1.79.4
shiki:
specifier: 1.21.1
version: 1.21.1
specifier: 1.22.0
version: 1.22.0
tailwindcss-textshadow:
specifier: 2.1.3
version: 2.1.3
@@ -1372,8 +1372,8 @@ packages:
'@vue/compiler-sfc':
optional: true
'@iconify/json@2.2.256':
resolution: {integrity: sha512-u2RwfBUuDE3A8qx3vnXdcJMtirHc9QrRRULfGY6Il6/K76Odfrm4yVqS/fYIh+wXwWl/fZdAZEozqxpZftfnIQ==}
'@iconify/json@2.2.257':
resolution: {integrity: sha512-IqjXD7BrtORxEK1eRq77550zMztRnwTn8Qyid+WuGspYP+wn5PUEoNPvF3bOJkWiq14QqPphi339nEKuomgR2A==}
'@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -2107,17 +2107,17 @@ packages:
'@rushstack/ts-command-line@4.22.6':
resolution: {integrity: sha512-QSRqHT/IfoC5nk9zn6+fgyqOPXHME0BfchII9EUPR19pocsNp/xSbeBCbD3PIR2Lg+Q5qk7OFqk1VhWPMdKHJg==}
'@shikijs/core@1.21.1':
resolution: {integrity: sha512-scBQo4V4O4WZLEDg11e75UPmXoCMq4Ya2A16U6efi/aTiR4o7T/GMNWZs2rq1U8dEvFKGxJZxiUy+tXgmr/4vw==}
'@shikijs/core@1.22.0':
resolution: {integrity: sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==}
'@shikijs/engine-javascript@1.21.1':
resolution: {integrity: sha512-29EG4KYKlAona8yikEx8uoKbK7N2YoXUO26LS1GOIxpMMIAlQS9UFONg95lkGmIfp1rRcvCvSpYYIJ/blsQxvg==}
'@shikijs/engine-javascript@1.22.0':
resolution: {integrity: sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==}
'@shikijs/engine-oniguruma@1.21.1':
resolution: {integrity: sha512-PvfEtXCDbQZc9ud0SC0bPiuMbul44Cv0Ky2go4SsvVkYAAKYJsMe/Hx7nxThW8yS0r+w8USa0WfOtQKsD9DU9A==}
'@shikijs/engine-oniguruma@1.22.0':
resolution: {integrity: sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==}
'@shikijs/types@1.21.1':
resolution: {integrity: sha512-yLuTJTCHmYznerJ0nxF+f2rBKHQf2FMAd08QL/3du2xNBy/7yQ8CjuKN4Zc+Pk0vfIFzdBoxdzvEXE4JtXoR4Q==}
'@shikijs/types@1.22.0':
resolution: {integrity: sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==}
'@shikijs/vscode-textmate@9.3.0':
resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==}
@@ -4746,8 +4746,8 @@ packages:
resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==}
hasBin: true
jiti@2.1.2:
resolution: {integrity: sha512-cYNjJus5X9J4jLzTaI8rYoIq1k6YySiA1lK4wxSnOrBRXkbVyreZfhoboJhsUmwgU82lpPjj1IoU7Ggrau8r3g==}
jiti@2.3.1:
resolution: {integrity: sha512-xPZ6pPzUifI8XDBBxIL4OB1w1ZKmBpmNEeKwNt2d0Spn8XisAIZhWrlOHq5seBrFGTxVx9PbrWvEMyrk4IO5bA==}
hasBin: true
jju@1.4.0:
@@ -4853,8 +4853,8 @@ packages:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
knip@5.31.0:
resolution: {integrity: sha512-4hR+qHx/id7mniCWWUqA4MXwGjYFN75xv3qLmEkl9Hm6eCKAhv0wGP0CyrXKUYxVyDplJQsqQaAlsjuRKYsdPA==}
knip@5.32.0:
resolution: {integrity: sha512-2M4qnAu1rjg17DEC1oXNmdb3gPqsEclTQasnAYPYr9wuGSRQLkb2X3VrqMpBHAcvboyB/gF8iE3FFdFhIjFwww==}
engines: {node: '>=18.6.0'}
hasBin: true
peerDependencies:
@@ -6337,8 +6337,8 @@ packages:
shell-quote@1.8.1:
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
shiki@1.21.1:
resolution: {integrity: sha512-jSOKRHyQJxGOW3kJflmwzHJbp/kjg6hP8LYuVbCPw5oyX+fSNNoCywvcCD3w9eHbj2rvNljt7YMa5BP5Xi+nHg==}
shiki@1.22.0:
resolution: {integrity: sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==}
side-channel@1.0.6:
resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
@@ -8156,7 +8156,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@iconify/json@2.2.256':
'@iconify/json@2.2.257':
dependencies:
'@iconify/types': 2.0.0
pathe: 1.1.2
@@ -8895,27 +8895,27 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
'@shikijs/core@1.21.1':
'@shikijs/core@1.22.0':
dependencies:
'@shikijs/engine-javascript': 1.21.1
'@shikijs/engine-oniguruma': 1.21.1
'@shikijs/types': 1.21.1
'@shikijs/engine-javascript': 1.22.0
'@shikijs/engine-oniguruma': 1.22.0
'@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0
'@types/hast': 3.0.4
hast-util-to-html: 9.0.3
'@shikijs/engine-javascript@1.21.1':
'@shikijs/engine-javascript@1.22.0':
dependencies:
'@shikijs/types': 1.21.1
'@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0
oniguruma-to-js: 0.4.3
'@shikijs/engine-oniguruma@1.21.1':
'@shikijs/engine-oniguruma@1.22.0':
dependencies:
'@shikijs/types': 1.21.1
'@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0
'@shikijs/types@1.21.1':
'@shikijs/types@1.22.0':
dependencies:
'@shikijs/vscode-textmate': 9.3.0
'@types/hast': 3.0.4
@@ -11831,7 +11831,7 @@ snapshots:
jiti@1.21.6: {}
jiti@2.1.2: {}
jiti@2.3.1: {}
jju@1.4.0: {}
@@ -11908,7 +11908,7 @@ snapshots:
kind-of@6.0.3: {}
knip@5.31.0(@types/node@22.7.4)(typescript@5.6.2):
knip@5.32.0(@types/node@22.7.4)(typescript@5.6.2):
dependencies:
'@nodelib/fs.walk': 1.2.8
'@snyk/github-codeowners': 1.1.0
@@ -11916,7 +11916,7 @@ snapshots:
easy-table: 1.2.0
enhanced-resolve: 5.17.1
fast-glob: 3.3.2
jiti: 2.1.2
jiti: 2.3.1
js-yaml: 4.1.0
minimist: 1.2.8
picocolors: 1.1.0
@@ -13469,12 +13469,12 @@ snapshots:
shell-quote@1.8.1: {}
shiki@1.21.1:
shiki@1.22.0:
dependencies:
'@shikijs/core': 1.21.1
'@shikijs/engine-javascript': 1.21.1
'@shikijs/engine-oniguruma': 1.21.1
'@shikijs/types': 1.21.1
'@shikijs/core': 1.22.0
'@shikijs/engine-javascript': 1.22.0
'@shikijs/engine-oniguruma': 1.22.0
'@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0
'@types/hast': 3.0.4

View File

@@ -32,7 +32,7 @@ PROJECT_NAME=$(shell basename "${ROOT}")
# - pkg/version/current.go
#
# Use `tools/bump_version.sh` script to change all those files at one shot.
VERSION="3.5.1"
VERSION="3.6.0"
# Build binaries and installation packages.
.PHONY: build
@@ -353,6 +353,7 @@ test-binary:
CGO_ENABLED=0 go build -ldflags="-X 'github.com/enfein/mieru/pkg/log.LogPrefix=S'" -o mita cmd/mita/mita.go
CGO_ENABLED=1 go build -race -ldflags="-X 'github.com/enfein/mieru/pkg/log.LogPrefix=C2'" -o mieru2 cmd/mieru/mieru.go
CGO_ENABLED=1 go build -race -ldflags="-X 'github.com/enfein/mieru/pkg/log.LogPrefix=S2'" -o mita2 cmd/mita/mita.go
CGO_ENABLED=0 go build test/cmd/exampleapiclient/exampleapiclient.go
CGO_ENABLED=0 go build test/cmd/httpserver/httpserver.go
CGO_ENABLED=0 go build test/cmd/sockshttpclient/sockshttpclient.go
CGO_ENABLED=0 go build test/cmd/socksudpclient/socksudpclient.go
@@ -365,14 +366,14 @@ test-container: test-binary
docker build -t mieru_httptest:${SHORT_SHA} -f test/deploy/httptest/Dockerfile .;\
docker build -t mieru_proxychain:${SHORT_SHA} -f test/deploy/proxychain/Dockerfile .;\
fi
rm -f mieru mieru2 mita mita2 httpserver sockshttpclient socksudpclient udpserver
rm -f exampleapiclient mieru mieru2 mita mita2 httpserver sockshttpclient socksudpclient udpserver
# Run docker integration tests.
.PHONY: run-container-test
run-container-test: test-container
if [ ! -z $$(command -v docker) ]; then\
docker run mieru_proxychain:${SHORT_SHA};\
docker run mieru_httptest:${SHORT_SHA};\
docker run mieru_proxychain:${SHORT_SHA};\
fi
# Format source code.

View File

@@ -19,14 +19,12 @@ For an explanation of the mieru protocol, see [mieru Proxy Protocol](./docs/prot
## Features
1. mieru uses a high-strength XChaCha20-Poly1305 encryption algorithm that generates encryption keys based on username, password and system time.
1. mieru implements complete encryption of all transmitted content between the client and the proxy server, without transmitting any plaintext information.
1. When mieru sends a packet, it is padded with random bytes at the end. Even when the same content is transmitted, the packet size varies.
1. When using the UDP transport protocol, mieru does not require a handshake between client and server.
1. When the server can not decrypt the data sent by the client, no content is returned. it is difficult for GFW to discover the mieru service through active probing.
1. mieru supports multiple users sharing a single proxy server.
1. mieru supports IPv4 and IPv6.
1. mieru provides socks5, HTTP and HTTPS proxy.
1. Provides socks5, HTTP, and HTTPS proxy interfaces.
1. Does not use TLS protocol. No need to register a domain name or set up a fake website.
1. Uses the high-strength XChaCha20-Poly1305 encryption algorithm that generates encryption keys based on username, password and system time.
1. Utilizes random padding and replay attack detection to prevent GFW from detecting the mieru service.
1. Supports multiple users sharing a single proxy server.
1. Supports both IPv4 and IPv6.
1. The server software supports socks5 outbound (proxy chain).
1. The client software supports Windows, Mac OS, Linux and Android. Android clients include
- [NekoBox](https://github.com/MatsuriDayo/NekoBoxForAndroid) version 1.3.1 or above, with [mieru plugin](https://github.com/enfein/NekoBoxPlugins).

View File

@@ -17,14 +17,12 @@ mieru 的翻墙原理与 shadowsocks / v2ray 等软件类似,在客户端和
## 特性
1. 提供 socks5, HTTP 和 HTTPS 代理接口。
1. 不使用 TLS 协议,无需注册域名和架设伪装站点。
1. 使用高强度的 XChaCha20-Poly1305 加密算法,基于用户名、密码和系统时间生成密钥。
1. mieru 实现了客户端和代理服务器之间所有传输内容的完整加密,不传输任何明文信息
1. 当 mieru 发送数据包时,会在尾部填充随机信息。即便是传输相同的内容,数据包大小也不相同
1. 在使用 UDP 传输协议时mieru 不需要客户端和服务器进行握手,即可直接发送数据
1. 当服务器无法解密客户端发送的数据时不会返回任何内容。GFW 很难通过主动探测发现 mieru 服务。
1. mieru 支持多个用户共享代理服务器。
1. mieru 支持 IPv4 和 IPv6。
1. mieru 提供 socks5, HTTP 和 HTTPS 代理。
1. 使用随机填充与重放攻击检测阻止 GFW 探测 mieru 服务
1. 支持多个用户共享代理服务器
1. 支持 IPv4 和 IPv6
1. 服务器软件支持 socks5 出站(链式代理)。
1. 客户端软件支持 Windows, Mac OS, Linux 和 Android 系统。Android 客户端包括
- [NekoBox](https://github.com/MatsuriDayo/NekoBoxForAndroid) 1.3.1 及以上版本,并安装 [mieru 插件](https://github.com/enfein/NekoBoxPlugins)。

View File

@@ -25,9 +25,10 @@ import (
)
var (
ErrNoClientConfig = errors.New("no client config")
ErrInvalidConfigConfig = errors.New("invalid client config")
ErrClientIsNotRunning = errors.New("client is not running")
ErrNoClientConfig = errors.New("no client config")
ErrInvalidConfigConfig = errors.New("invalid client config")
ErrClientIsNotRunning = errors.New("client is not running")
ErrStoreClientConfigAfterStart = errors.New("can't store client config after start")
)
// Client contains methods supported by a mieru client.
@@ -44,7 +45,7 @@ type ClientConfigurationService interface {
Load() (*ClientConfig, error)
// Store saves the client config.
// It returns wrapped ErrInvalidConfigConfig if client config is invalid.
// It returns wrapped ErrInvalidConfigConfig if the provided client config is invalid.
Store(*ClientConfig) error
}
@@ -64,16 +65,19 @@ type ClientLifecycleService interface {
IsRunning() bool
}
// ClientNetworkService contains methods to establish proxy connections.
// ClientNetworkService contains methods to establish connections to proxy server.
type ClientNetworkService interface {
// DialContext returns a new mieru connection to reach proxy server.
// DialContext returns a new proxy connection to reach proxy server.
// It returns an error if the client has not been started,
// or has been stopped.
DialContext(context.Context) (net.Conn, error)
// HandshakeWithConnect completes the socks5 CONNECT request with proxy server.
// After this, the mieru connection is able to send and receive user payload.
// The mieru connection is NOT terminated when an error is returned.
// HandshakeWithConnect completes the socks5 CONNECT request with proxy server
// in the given proxy connection.
// You may need to send a response back to the application that initiated
// the proxy connection.
// After that, the proxy connection is able to send and receive user payload.
// The proxy connection is NOT terminated when an error is returned.
HandshakeWithConnect(context.Context, net.Conn, model.AddrSpec) error
}
@@ -82,7 +86,7 @@ type ClientConfig struct {
Profile *appctlpb.ClientProfile
}
// NewClient returns a blank mieru client.
// NewClient creates a blank mieru client with no client config.
func NewClient() Client {
mc := &mieruClient{}
mc.initOnce()

View File

@@ -75,6 +75,9 @@ func (mc *mieruClient) Store(config *ClientConfig) error {
if config.Profile == nil {
return fmt.Errorf("%w: client config profile is nil", ErrInvalidConfigConfig)
}
if mc.running {
return ErrStoreClientConfigAfterStart
}
if err := appctl.ValidateClientConfigSingleProfile(config.Profile); err != nil {
return fmt.Errorf("%w: %s", ErrInvalidConfigConfig, err.Error())
}
@@ -120,7 +123,7 @@ func (mc *mieruClient) Start() error {
}
mc.mux = mc.mux.SetClientMultiplexFactor(multiplexFactor)
// Set endpoints.
// Set server endpoints.
mtu := util.DefaultMTU
if activeProfile.GetMtu() != 0 {
mtu = int(activeProfile.GetMtu())

View File

@@ -33,3 +33,15 @@ const (
Socks5FQDNAddress byte = 3
Socks5IPv6Address byte = 4
)
// socks5 authentication options.
const (
Socks5NoAuth byte = 0
Socks5UserPassAuth byte = 2
Socks5NoAcceptableAuth byte = 255
Socks5UserPassAuthVersion byte = 1
Socks5AuthSuccess byte = 0
Socks5AuthFailure byte = 1
)

View File

@@ -1,5 +1,5 @@
Package: mieru
Version: 3.5.1
Version: 3.6.0
Section: net
Priority: optional
Architecture: amd64

View File

@@ -1,5 +1,5 @@
Name: mieru
Version: 3.5.1
Version: 3.6.0
Release: 1%{?dist}
Summary: Mieru proxy client
License: GPLv3+

View File

@@ -1,5 +1,5 @@
Package: mieru
Version: 3.5.1
Version: 3.6.0
Section: net
Priority: optional
Architecture: arm64

View File

@@ -1,5 +1,5 @@
Name: mieru
Version: 3.5.1
Version: 3.6.0
Release: 1%{?dist}
Summary: Mieru proxy client
License: GPLv3+

View File

@@ -1,5 +1,5 @@
Package: mita
Version: 3.5.1
Version: 3.6.0
Section: net
Priority: optional
Architecture: amd64

View File

@@ -1,5 +1,5 @@
Name: mita
Version: 3.5.1
Version: 3.6.0
Release: 1%{?dist}
Summary: Mieru proxy server
License: GPLv3+

View File

@@ -1,5 +1,5 @@
Package: mita
Version: 3.5.1
Version: 3.6.0
Section: net
Priority: optional
Architecture: arm64

View File

@@ -1,5 +1,5 @@
Name: mita
Version: 3.5.1
Version: 3.6.0
Release: 1%{?dist}
Summary: Mieru proxy server
License: GPLv3+

View File

@@ -8,32 +8,32 @@ Before installation and configuration, connect to the server via SSH and then ex
```sh
# Debian / Ubuntu - X86_64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita_3.5.1_amd64.deb
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita_3.6.0_amd64.deb
# Debian / Ubuntu - ARM 64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita_3.5.1_arm64.deb
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita_3.6.0_arm64.deb
# RedHat / CentOS / Rocky Linux - X86_64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita-3.5.1-1.x86_64.rpm
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita-3.6.0-1.x86_64.rpm
# RedHat / CentOS / Rocky Linux - ARM 64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita-3.5.1-1.aarch64.rpm
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita-3.6.0-1.aarch64.rpm
```
## Install mita package
```sh
# Debian / Ubuntu - X86_64
sudo dpkg -i mita_3.5.1_amd64.deb
sudo dpkg -i mita_3.6.0_amd64.deb
# Debian / Ubuntu - ARM 64
sudo dpkg -i mita_3.5.1_arm64.deb
sudo dpkg -i mita_3.6.0_arm64.deb
# RedHat / CentOS / Rocky Linux - X86_64
sudo rpm -Uvh --force mita-3.5.1-1.x86_64.rpm
sudo rpm -Uvh --force mita-3.6.0-1.x86_64.rpm
# RedHat / CentOS / Rocky Linux - ARM 64
sudo rpm -Uvh --force mita-3.5.1-1.aarch64.rpm
sudo rpm -Uvh --force mita-3.6.0-1.aarch64.rpm
```
Those instructions can also be used to upgrade the version of mita software package.

View File

@@ -8,32 +8,32 @@
```sh
# Debian / Ubuntu - X86_64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita_3.5.1_amd64.deb
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita_3.6.0_amd64.deb
# Debian / Ubuntu - ARM 64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita_3.5.1_arm64.deb
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita_3.6.0_arm64.deb
# RedHat / CentOS / Rocky Linux - X86_64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita-3.5.1-1.x86_64.rpm
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita-3.6.0-1.x86_64.rpm
# RedHat / CentOS / Rocky Linux - ARM 64
curl -LSO https://github.com/enfein/mieru/releases/download/v3.5.1/mita-3.5.1-1.aarch64.rpm
curl -LSO https://github.com/enfein/mieru/releases/download/v3.6.0/mita-3.6.0-1.aarch64.rpm
```
## 安装 mita 软件包
```sh
# Debian / Ubuntu - X86_64
sudo dpkg -i mita_3.5.1_amd64.deb
sudo dpkg -i mita_3.6.0_amd64.deb
# Debian / Ubuntu - ARM 64
sudo dpkg -i mita_3.5.1_arm64.deb
sudo dpkg -i mita_3.6.0_arm64.deb
# RedHat / CentOS / Rocky Linux - X86_64
sudo rpm -Uvh --force mita-3.5.1-1.x86_64.rpm
sudo rpm -Uvh --force mita-3.6.0-1.x86_64.rpm
# RedHat / CentOS / Rocky Linux - ARM 64
sudo rpm -Uvh --force mita-3.5.1-1.aarch64.rpm
sudo rpm -Uvh --force mita-3.6.0-1.aarch64.rpm
```
上述指令也可以用来升级 mita 软件包的版本。

View File

@@ -25,17 +25,6 @@ import (
"github.com/enfein/mieru/v3/pkg/util"
)
const (
noAuth byte = 0
userPassAuth byte = 2
noAcceptableAuth byte = 255
userPassAuthVersion byte = 1
authSuccess byte = 0
authFailure byte = 1
)
// Auth provide authentication settings to socks5 server.
type Auth struct {
// Do socks5 authentication at proxy client side.
@@ -93,17 +82,17 @@ func (s *Server) handleAuthentication(conn net.Conn) error {
return fmt.Errorf("get authentication method failed: %w", err)
}
for _, method := range authMethods {
if method == noAuth {
if method == constant.Socks5NoAuth {
requestNoAuth = true
}
if method == userPassAuth {
if method == constant.Socks5UserPassAuth {
requestUserPassAuth = true
}
}
if !requestNoAuth && !requestUserPassAuth {
HandshakeErrors.Add(1)
if _, err := conn.Write([]byte{constant.Socks5Version, noAcceptableAuth}); err != nil {
if _, err := conn.Write([]byte{constant.Socks5Version, constant.Socks5NoAcceptableAuth}); err != nil {
return fmt.Errorf("write authentication response (no acceptable methods) failed: %w", err)
}
return fmt.Errorf("socks5 client provided authentication is not supported by socks5 server")
@@ -114,7 +103,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error {
HandshakeErrors.Add(1)
return fmt.Errorf("socks5 client requested no authentication, but user and password are required by socks5 server")
}
if _, err := conn.Write([]byte{constant.Socks5Version, noAuth}); err != nil {
if _, err := conn.Write([]byte{constant.Socks5Version, constant.Socks5NoAuth}); err != nil {
HandshakeErrors.Add(1)
return fmt.Errorf("write authentication response (no authentication required) failed: %w", err)
}
@@ -126,7 +115,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error {
}
// Tell the client to use user password authentication.
if _, err := conn.Write([]byte{constant.Socks5Version, userPassAuth}); err != nil {
if _, err := conn.Write([]byte{constant.Socks5Version, constant.Socks5UserPassAuth}); err != nil {
HandshakeErrors.Add(1)
return fmt.Errorf("write user password authentication request failed: %w", err)
}
@@ -136,7 +125,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error {
if _, err := io.ReadFull(conn, header); err != nil {
return fmt.Errorf("get user password authentication version failed: %w", err)
}
if header[0] != userPassAuthVersion {
if header[0] != constant.Socks5UserPassAuthVersion {
return fmt.Errorf("user password authentication version %d is not supported by socks5 server", header[0])
}
@@ -163,7 +152,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error {
passwordStr := string(password)
for _, c := range s.config.AuthOpts.IngressCredentials {
if c.User == userStr && c.Password == passwordStr {
if _, err := conn.Write([]byte{userPassAuthVersion, authSuccess}); err != nil {
if _, err := conn.Write([]byte{constant.Socks5UserPassAuthVersion, constant.Socks5AuthSuccess}); err != nil {
HandshakeErrors.Add(1)
return fmt.Errorf("write user password authentication success response failed: %w", err)
}
@@ -171,7 +160,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error {
}
}
HandshakeErrors.Add(1)
if _, err := conn.Write([]byte{userPassAuthVersion, authFailure}); err != nil {
if _, err := conn.Write([]byte{constant.Socks5UserPassAuthVersion, constant.Socks5AuthFailure}); err != nil {
return fmt.Errorf("write user password authentication failure response failed: %w", err)
}
return fmt.Errorf("user password authentication failed: invalid user or password")
@@ -187,7 +176,7 @@ func (s *Server) dialWithAuthentication(proxyConn net.Conn, auth *appctlpb.Auth)
if auth == nil || auth.GetUser() == "" || auth.GetPassword() == "" {
// No authentication required.
if _, err := proxyConn.Write([]byte{constant.Socks5Version, 1, noAuth}); err != nil {
if _, err := proxyConn.Write([]byte{constant.Socks5Version, 1, constant.Socks5NoAuth}); err != nil {
HandshakeErrors.Add(1)
proxyConn.Close()
return fmt.Errorf("failed to write socks5 authentication header to egress proxy: %w", err)
@@ -199,14 +188,14 @@ func (s *Server) dialWithAuthentication(proxyConn net.Conn, auth *appctlpb.Auth)
proxyConn.Close()
return fmt.Errorf("failed to read socks5 authentication response from egress proxy: %w", err)
}
if resp[0] != constant.Socks5Version || resp[1] != noAuth {
if resp[0] != constant.Socks5Version || resp[1] != constant.Socks5NoAuth {
HandshakeErrors.Add(1)
proxyConn.Close()
return fmt.Errorf("got unexpected socks5 authentication response from egress proxy: %v", resp)
}
} else {
// User password authentication.
if _, err := proxyConn.Write([]byte{constant.Socks5Version, 1, userPassAuth}); err != nil {
if _, err := proxyConn.Write([]byte{constant.Socks5Version, 1, constant.Socks5UserPassAuth}); err != nil {
HandshakeErrors.Add(1)
proxyConn.Close()
return fmt.Errorf("failed to write socks5 authentication header to egress proxy: %w", err)
@@ -218,14 +207,14 @@ func (s *Server) dialWithAuthentication(proxyConn net.Conn, auth *appctlpb.Auth)
proxyConn.Close()
return fmt.Errorf("failed to read socks5 authentication response from egress proxy: %w", err)
}
if resp[0] != constant.Socks5Version || resp[1] != userPassAuth {
if resp[0] != constant.Socks5Version || resp[1] != constant.Socks5UserPassAuth {
HandshakeErrors.Add(1)
proxyConn.Close()
return fmt.Errorf("got unexpected socks5 authentication response from egress proxy: %v", resp)
}
// Send socks5 credential.
credential := []byte{userPassAuthVersion}
credential := []byte{constant.Socks5UserPassAuthVersion}
credential = append(credential, byte(len(auth.GetUser())))
credential = append(credential, []byte(auth.GetUser())...)
credential = append(credential, byte(len(auth.GetPassword())))
@@ -241,12 +230,12 @@ func (s *Server) dialWithAuthentication(proxyConn net.Conn, auth *appctlpb.Auth)
proxyConn.Close()
return fmt.Errorf("failed to read socks5 authentication response from egress proxy: %w", err)
}
if resp[0] != userPassAuthVersion {
if resp[0] != constant.Socks5UserPassAuthVersion {
HandshakeErrors.Add(1)
proxyConn.Close()
return fmt.Errorf("got unexpected socks5 user password authentication version from egress proxy: %v", resp[0])
}
if resp[1] != authSuccess {
if resp[1] != constant.Socks5AuthSuccess {
HandshakeErrors.Add(1)
proxyConn.Close()
return fmt.Errorf("socks5 authentication with user password failed from egress proxy")

View File

@@ -135,9 +135,9 @@ func (c *Client) dialSocks5Long(targetAddr string) (conn net.Conn, udpConn *net.
// Prepare the first request.
var req bytes.Buffer
version := byte(constant.Socks5Version)
method := byte(noAuth)
method := byte(constant.Socks5NoAuth)
if c.Credential != nil {
method = userPassAuth
method = constant.Socks5UserPassAuth
}
req.Write([]byte{
version,
@@ -158,7 +158,7 @@ func (c *Client) dialSocks5Long(targetAddr string) (conn net.Conn, udpConn *net.
return nil, nil, nil, fmt.Errorf("socks method negotiation failed")
}
if c.Credential != nil {
version := byte(userPassAuthVersion)
version := byte(constant.Socks5UserPassAuthVersion)
req.Reset()
req.Write([]byte{version})
req.Write([]byte{byte(len(c.Credential.User))})
@@ -173,7 +173,7 @@ func (c *Client) dialSocks5Long(targetAddr string) (conn net.Conn, udpConn *net.
return nil, nil, nil, fmt.Errorf("server does not respond properly")
} else if resp[0] != version {
return nil, nil, nil, fmt.Errorf("server does not support user/password version 1")
} else if resp[1] != authSuccess {
} else if resp[1] != constant.Socks5AuthSuccess {
return nil, nil, nil, fmt.Errorf("user/password login failed")
}
}

View File

@@ -73,9 +73,8 @@ func TestSocks5Connect(t *testing.T) {
}
req := bytes.NewBuffer(nil)
req.Write([]byte{5})
req.Write([]byte{1, noAuth})
req.Write([]byte{5, 1, 0, 1, 127, 0, 0, 1})
req.Write([]byte{constant.Socks5Version, 1, constant.Socks5NoAuth})
req.Write([]byte{constant.Socks5Version, constant.Socks5ConnectCmd, 0, constant.Socks5IPv4Address, 127, 0, 0, 1})
port := []byte{0, 0}
binary.BigEndian.PutUint16(port, uint16(lAddr.Port))
req.Write(port)
@@ -88,8 +87,8 @@ func TestSocks5Connect(t *testing.T) {
// Verify response from socks server.
want := []byte{
constant.Socks5Version, noAuth,
constant.Socks5Version, 0, 0, 1,
constant.Socks5Version, constant.Socks5NoAuth,
constant.Socks5Version, 0, 0, constant.Socks5IPv4Address,
127, 0, 0, 1,
0, 0,
'p', 'o', 'n', 'g',
@@ -182,9 +181,8 @@ func TestSocks5UDPAssociation(t *testing.T) {
}
req := bytes.NewBuffer(nil)
req.Write([]byte{5})
req.Write([]byte{1, noAuth})
req.Write([]byte{5, 3, 0, 1, 127, 0, 0, 1, 0, 0})
req.Write([]byte{constant.Socks5Version, 1, constant.Socks5NoAuth})
req.Write([]byte{constant.Socks5Version, constant.Socks5UDPAssociateCmd, 0, constant.Socks5IPv4Address, 127, 0, 0, 1, 0, 0})
// Send initial UDP association request.
if _, err := conn.Write(req.Bytes()); err != nil {
@@ -193,8 +191,8 @@ func TestSocks5UDPAssociation(t *testing.T) {
// Verify response from socks server.
want := []byte{
constant.Socks5Version, noAuth,
constant.Socks5Version, 0, 0, 1,
constant.Socks5Version, constant.Socks5NoAuth,
constant.Socks5Version, 0, 0, constant.Socks5IPv4Address,
0, 0, 0, 0,
0, 0,
}

View File

@@ -16,5 +16,5 @@
package version
const (
AppVersion = "3.5.1"
AppVersion = "3.6.0"
)

View File

@@ -0,0 +1,178 @@
// Copyright (C) 2024 mieru authors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"bytes"
"context"
"flag"
"fmt"
"io"
"net"
"github.com/enfein/mieru/v3/apis/client"
"github.com/enfein/mieru/v3/apis/constant"
"github.com/enfein/mieru/v3/apis/model"
"github.com/enfein/mieru/v3/pkg/appctl/appctlpb"
"github.com/enfein/mieru/v3/pkg/util"
"google.golang.org/protobuf/proto"
)
var (
port = flag.Int("port", 0, "mieru API client socks5 port")
username = flag.String("username", "", "mieru username")
password = flag.String("password", "", "mieru password")
serverIP = flag.String("server_ip", "", "IP address of mieru proxy server")
serverPort = flag.Int("server_port", 0, "Port number of mieru proxy server")
serverProtocol = flag.String("server_protocol", "", "Transport protocol: TCP or UDP")
)
func main() {
flag.Parse()
if *port < 1 || *port > 65535 {
panic(fmt.Sprintf("port %d is invalid", *port))
}
if *username == "" {
panic("username is not set")
}
if *password == "" {
panic("password is not set")
}
if *serverIP == "" {
panic("server_ip is not set")
}
if net.ParseIP(*serverIP) == nil {
panic(fmt.Sprintf("Failed to parse server_ip %q", *serverIP))
}
if *serverPort < 1 || *serverPort > 65535 {
panic(fmt.Sprintf("server_port %d is invalid", *serverPort))
}
var transportProtocol *appctlpb.TransportProtocol
switch *serverProtocol {
case "TCP":
transportProtocol = appctlpb.TransportProtocol_TCP.Enum()
case "UDP":
transportProtocol = appctlpb.TransportProtocol_UDP.Enum()
default:
panic(fmt.Sprintf("Transport protocol %q is invalid", *serverProtocol))
}
c := client.NewClient()
if err := c.Store(&client.ClientConfig{
Profile: &appctlpb.ClientProfile{
ProfileName: proto.String("api"),
User: &appctlpb.User{
Name: username,
Password: password,
},
Servers: []*appctlpb.ServerEndpoint{
{
IpAddress: serverIP,
PortBindings: []*appctlpb.PortBinding{
{
Port: proto.Int32(int32(*serverPort)),
Protocol: transportProtocol,
},
},
},
},
Mtu: proto.Int32(1400),
},
}); err != nil {
panic(err)
}
if _, err := c.Load(); err != nil {
panic(err)
}
if err := c.Start(); err != nil {
panic(err)
}
if !c.IsRunning() {
panic("client is not running after start")
}
l, err := net.ListenTCP("tcp", &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: *port})
if err != nil {
panic(err)
}
for {
conn, err := l.Accept()
if err != nil {
panic(err)
}
go handleOneSocks5Conn(c, conn)
}
}
func handleOneSocks5Conn(c client.Client, conn net.Conn) {
defer conn.Close()
// Handle socks5 authentication.
if err := socks5ClientHandshake(conn); err != nil {
panic(fmt.Sprintf("socks5ClientHandshake() failed: %v", err))
}
// Find destination.
socks5Header := make([]byte, 3)
if _, err := io.ReadFull(conn, socks5Header); err != nil {
panic(fmt.Sprintf("Read socks5 header failed: %v", err))
}
addr := model.AddrSpec{}
if err := addr.ReadFromSocks5(conn); err != nil {
panic(fmt.Sprintf("ReadFromSocks5() failed: %v", err))
}
// Dial to proxy server and do handshake.
ctx := context.Background()
proxyConn, err := c.DialContext(ctx)
if err != nil {
panic(fmt.Sprintf("DialContext() failed: %v", err))
}
defer proxyConn.Close()
if err := c.HandshakeWithConnect(ctx, proxyConn, addr); err != nil {
panic(fmt.Sprintf("HandshakeWithConnect() failed: %v", err))
}
// Send the connect response back to the application.
var resp bytes.Buffer
resp.Write([]byte{constant.Socks5Version, 0, 0})
if err := addr.WriteToSocks5(&resp); err != nil {
panic(fmt.Sprintf("WriteToSocks5() failed: %v", err))
}
if _, err := conn.Write(resp.Bytes()); err != nil {
panic(fmt.Sprintf("Write socks5 response failed: %v", err))
}
// Exchange payload.
util.BidiCopy(conn, proxyConn)
}
func socks5ClientHandshake(conn net.Conn) error {
// Only accept socks5 with no authentication.
socks5Header := make([]byte, 3)
if _, err := io.ReadFull(conn, socks5Header); err != nil {
return err
}
wantHeader := []byte{constant.Socks5Version, 1, constant.Socks5NoAuth}
if !bytes.Equal(socks5Header, wantHeader) {
return fmt.Errorf("got socks5 header %v, want %v", socks5Header, wantHeader)
}
if _, err := conn.Write([]byte{constant.Socks5Version, constant.Socks5AuthSuccess}); err != nil {
return err
}
return nil
}

View File

@@ -44,4 +44,5 @@ echo "========== BEGIN OF TCP TEST =========="
echo "========== END OF TCP TEST =========="
echo "Test is successful."
sleep 1
exit 0

View File

@@ -20,7 +20,7 @@ FROM ubuntu:24.04
WORKDIR /test
# Copy binaries, data and test script into the container.
COPY mieru mita httpserver sockshttpclient socksudpclient udpserver \
COPY exampleapiclient mieru mita httpserver sockshttpclient socksudpclient udpserver \
test/deploy/httptest/client_mix.json test/deploy/httptest/server_mix.json \
test/deploy/httptest/client_tcp.json test/deploy/httptest/server_tcp.json \
test/deploy/httptest/client_udp.json test/deploy/httptest/server_udp.json \

View File

@@ -35,11 +35,6 @@ sleep 1
./mita run &
sleep 1
# Run UDP associate test.
echo "========== BEGIN OF UDP ASSOCIATE TEST =========="
./test_mix_udp_associate.sh
echo "========== END OF UDP ASSOCIATE TEST =========="
# Run TCP test.
echo "========== BEGIN OF TCP TEST =========="
./test_tcp.sh
@@ -50,5 +45,11 @@ echo "========== BEGIN OF UDP TEST =========="
./test_udp.sh
echo "========== END OF UDP TEST =========="
# Run UDP associate test.
echo "========== BEGIN OF UDP ASSOCIATE TEST =========="
./test_mix_udp_associate.sh
echo "========== END OF UDP ASSOCIATE TEST =========="
echo "Test is successful."
sleep 1
exit 0

View File

@@ -55,6 +55,10 @@ if [[ "$?" -ne 0 ]]; then
fi
./mieru profile cpu start /test/mieru.tcp.cpu.gz
# Start mieru API client.
./exampleapiclient -port=1081 -username=baozi -password=manlianpenfen \
-server_ip=127.0.0.1 -server_port=8964 -server_protocol=TCP &
# Start testing.
sleep 2
echo ">>> socks5 - new connections - TCP <<<"
@@ -69,6 +73,16 @@ if [ "$?" -ne "0" ]; then
exit 1
fi
sleep 1
echo ">>> socks5 - new connections with API client - TCP <<<"
./sockshttpclient -dst_host=127.0.0.1 -dst_port=8080 \
-local_proxy_host=127.0.0.1 -local_proxy_port=1081 \
-test_case=new_conn -num_request=3000
if [ "$?" -ne "0" ]; then
echo "TCP - test socks5 new_conn with API client failed."
exit 1
fi
sleep 1
echo ">>> http - new connections - TCP <<<"
./sockshttpclient -proxy_mode=http -dst_host=127.0.0.1 -dst_port=8080 \

View File

@@ -55,6 +55,10 @@ if [[ "$?" -ne 0 ]]; then
fi
./mieru profile cpu start /test/mieru.udp.cpu.gz
# Start mieru API client.
./exampleapiclient -port=1082 -username=baozi -password=manlianpenfen \
-server_ip=127.0.0.1 -server_port=8964 -server_protocol=UDP &
# Start testing.
sleep 2
echo ">>> socks5 - new connections - UDP <<<"
@@ -69,6 +73,16 @@ if [ "$?" -ne "0" ]; then
exit 1
fi
sleep 1
echo ">>> socks5 - new connections with API client - UDP <<<"
./sockshttpclient -dst_host=127.0.0.1 -dst_port=8080 \
-local_proxy_host=127.0.0.1 -local_proxy_port=1082 \
-test_case=new_conn -num_request=3000
if [ "$?" -ne "0" ]; then
echo "UDP - test socks5 new_conn with API client failed."
exit 1
fi
sleep 1
echo ">>> http - new connections - UDP <<<"
./sockshttpclient -proxy_mode=http -dst_host=127.0.0.1 -dst_port=8080 \

View File

@@ -90,4 +90,5 @@ iptables -D INPUT -p tcp --sport 8964 -m statistic --mode random --probability 0
iptables -D INPUT -p udp --sport 8964 -m statistic --mode random --probability 0.001 -j DROP
echo "Test is successful."
sleep 1
exit 0

View File

@@ -78,4 +78,5 @@ if [ "$?" -ne "0" ]; then
fi
echo "Test is successful."
sleep 1
exit 0

View File

@@ -375,40 +375,6 @@ jobs:
run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }}.tar.xz --clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ios:
needs: cache-toolchains-mac
runs-on: macos-13
strategy:
fail-fast: false
matrix:
arch: [arm64]
env:
EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}" target_os="ios" ios_enable_code_signing=false'
BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}
steps:
- uses: actions/checkout@v4
- name: Cache toolchains and PGO
uses: actions/cache@v4
with:
path: |
src/third_party/llvm-build/Release+Asserts/
src/chrome/build/pgo_profiles/chrome-mac-*
src/gn/
key: toolchains-pgo-mac-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
- id: ccache-timestamp
run: echo "CCACHE_TIMESTAMP=$(date +%s)" >>$GITHUB_OUTPUT
- name: Cache ccache files
uses: actions/cache@v4
with:
path: ~/Library/Caches/ccache
key: ccache-ios-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-${{ steps.ccache-timestamp.outputs.CCACHE_TIMESTAMP }}
restore-keys: ccache-ios-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-
- run: brew install ninja ccache
- run: pip install setuptools
- run: ./get-clang.sh
- run: ccache -z
- run: ./build.sh
- run: ccache -s
openwrt:
needs: cache-toolchains-posix
runs-on: ubuntu-22.04

View File

@@ -82,7 +82,7 @@ Or `quic://user:pass@example.com`, if it works better. See also [parameter usage
* [v2rayN](https://github.com/2dust/v2rayN), GUI client, Windows
* [NekoBox for Android](https://github.com/MatsuriDayo/NekoBoxForAndroid), Proxy toolchain, Android
* [NekoRay / NekoBox For PC](https://github.com/MatsuriDayo/nekoray), Qt based GUI, Windows, Linux
* [Yet Another Shadow Socket](https://github.com/Chilledheart/yass), NaïveProxy-compatible forward proxy, Android, iOS, Windows, macOS, Linux, FreeBSD
* [Yet Another Shadow Socket](https://github.com/Chilledheart/yass), NaïveProxy-compatible forward proxy, Android, iOS, Windows, macOS, Linux, FreeBSD
## Notes for downstream
@@ -114,7 +114,7 @@ Further reads and writes after `kFirstPaddings` are unpadded to avoid performanc
### H2 RST_STREAM frame padding
In experiments, NaïveProxy tends to send too many RST_STREAM frames per session, an uncommon behavior from regular browsers. To solve this, an END_STREAM DATA frame padded with total length distributed in [48, 72] is prepended to the RST_STREAM frame so it looks like a HEADERS frame. The server often replies to this with a WINDOW_UPDATE because padding is accounted in flow control. Whether this results in a new uncommon behavior is still unclear.
In experiments, NaïveProxy tends to send too many RST_STREAM frames per session, an uncommon behavior from regular browsers. To solve this, an END_STREAM DATA frame padded with total length distributed in [48, 72] is prepended to the RST_STREAM frame so it looks like a HEADERS frame. The server often replies to this with a WINDOW_UPDATE because padding is accounted in flow control. Whether this results in a new uncommon behavior is still unclear.
### H2 HEADERS frame padding

View File

@@ -1153,15 +1153,12 @@ component("base") {
"android/build_info_stub.cc",
"android/content_uri_utils.h",
"android/content_uri_utils_stub.cc",
"android/jni_android.h",
"android/library_loader/anchor_functions.h",
"android/library_loader/library_loader_hooks.h",
"android/path_utils.h",
"android/scoped_hardware_buffer_fence_sync.cc",
"android/scoped_hardware_buffer_fence_sync.h",
"android/scoped_hardware_buffer_handle.cc",
"android/scoped_hardware_buffer_handle.h",
"android/scoped_java_ref.h",
"android/sys_utils.h",
"debug/stack_trace_android.cc",
"files/file_util_android.cc",
@@ -1196,7 +1193,6 @@ component("base") {
deps += [
"//third_party/ashmem",
"//third_party/cpu_features:ndk_compat",
"//third_party/jni_zero:jni_zero",
]
# Needs to be a public config so that dependent targets link against it as
@@ -1276,6 +1272,8 @@ component("base") {
"android/unguessable_token_android.h",
]
deps += [ "//build:robolectric_buildflags" ]
}
if (is_android || is_robolectric) {
public_deps += [ "//third_party/jni_zero:jni_zero" ]
} # is_android || is_robolectric

View File

@@ -125,10 +125,6 @@ class BASE_EXPORT StackTrace {
// prefix string prepended to each line.
void OutputToStreamWithPrefix(std::ostream* os,
cstring_view prefix_string) const;
#else
void OutputToStream(std::ostream* os) const;
void OutputToStreamWithPrefix(std::ostream* os,
cstring_view prefix_string) const;
#endif
// Resolves backtrace to symbols and returns as string.
@@ -152,9 +148,6 @@ class BASE_EXPORT StackTrace {
#if !defined(__UCLIBC__) && !defined(_AIX)
void OutputToStreamWithPrefixImpl(std::ostream* os,
cstring_view prefix_string) const;
#else
void OutputToStreamWithPrefixImpl(std::ostream* os,
cstring_view prefix_string) const {}
#endif
// Returns true if generation of symbolized stack traces is to be suppressed.

View File

@@ -1075,6 +1075,10 @@ void StackTrace::OutputToStreamWithPrefixImpl(
StreamBacktraceOutputHandler handler(os);
ProcessBacktrace(addresses(), prefix_string, &handler);
}
#else
void StackTrace::OutputToStreamWithPrefixImpl(
std::ostream*, cstring_view) const {
}
#endif
namespace internal {

View File

@@ -9,7 +9,6 @@
#include "base/files/file_path.h"
#include <iostream>
#include <string.h>
#include <algorithm>

View File

@@ -10,7 +10,7 @@
#include "base/tracing_buildflags.h"
#if 1
#if BUILDFLAG(ENABLE_BASE_TRACING)
#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h" // nogncheck
#else

View File

@@ -5,8 +5,6 @@
#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
#include "base/trace_event/trace_event_stub.h"
#if 0
#include <stdint.h>
#include <iosfwd>
@@ -161,5 +159,4 @@ void BASE_EXPORT PrintTo(const MemoryAllocatorDump::Entry&, std::ostream*);
} // namespace trace_event
} // namespace base
#endif
#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_

View File

@@ -5,8 +5,6 @@
#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
#include "base/trace_event/trace_event_stub.h"
#if 0
#include <stdint.h>
#include <map>
@@ -279,5 +277,4 @@ class BASE_EXPORT MemoryDumpManager {
} // namespace trace_event
} // namespace base
#endif
#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_

View File

@@ -5,8 +5,6 @@
#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
#include "base/trace_event/trace_event_stub.h"
#if 0
#include "base/base_export.h"
#include "base/process/process_handle.h"
#include "base/trace_event/memory_dump_request_args.h"
@@ -50,5 +48,4 @@ class BASE_EXPORT MemoryDumpProvider {
} // namespace trace_event
} // namespace base
#endif
#endif // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_

View File

@@ -5,8 +5,6 @@
#ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
#define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
#include "base/trace_event/trace_event_stub.h"
#if 0
#include <stddef.h>
#include <map>
@@ -297,5 +295,4 @@ class BASE_EXPORT ProcessMemoryDump {
} // namespace trace_event
} // namespace base
#endif
#endif // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_

View File

@@ -5,8 +5,6 @@
#ifndef BASE_TRACE_EVENT_TRACE_EVENT_H_
#define BASE_TRACE_EVENT_TRACE_EVENT_H_
#include "base/trace_event/trace_event_stub.h"
#if 0
// This header file defines implementation details of how the trace macros in
// trace_event_common.h collect and store trace events. Anything not
// implementation-specific should go in trace_event_common.h instead of here.
@@ -467,5 +465,4 @@ class TraceScopedTrackableObject {
} // namespace trace_event
} // namespace base
#endif
#endif // BASE_TRACE_EVENT_TRACE_EVENT_H_

View File

@@ -13,7 +13,6 @@
#include <string_view>
#include "base/base_export.h"
#include "base/check.h"
#include "base/trace_event/common/trace_event_common.h"
#include "base/trace_event/memory_allocator_dump_guid.h"
#include "base/values.h"
@@ -373,41 +372,6 @@ class BASE_EXPORT MemoryDumpProvider {
MemoryDumpProvider() = default;
};
class BASE_EXPORT MemoryAllocatorDump {
public:
static constexpr char* kNameSize = nullptr;
static constexpr char* kNameObjectCount = nullptr;
static constexpr char* kUnitsBytes = nullptr;
static constexpr char* kUnitsObjects = nullptr;
static constexpr char* kTypeScalar = nullptr;
static constexpr char* kTypeString = nullptr;
void AddScalar(const char* name, const char* units, uint64_t value) {}
void AddString(const char* name,
const char* units,
const std::string& value) {}
const std::string& absolute_name() const { return absolute_name_; }
const MemoryAllocatorDumpGuid& guid() const { return guid_; }
private:
const std::string absolute_name_;
MemoryAllocatorDumpGuid guid_;
};
class BASE_EXPORT ProcessMemoryDump {
public:
MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name) {
CHECK(false);
return nullptr;
}
MemoryAllocatorDump* GetAllocatorDump(
const std::string& absolute_name) const {
CHECK(false);
return nullptr;
}
void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source,
const MemoryAllocatorDumpGuid& target) {}
};
class BASE_EXPORT MemoryDumpManager {
public:
static constexpr const char* const kTraceCategory =
@@ -430,19 +394,19 @@ class TracedArray;
class TracedDictionary;
class EventContext;
class BASE_EXPORT StaticString {
class StaticString {
public:
template <typename T>
StaticString(T) {}
};
class BASE_EXPORT DynamicString {
class DynamicString {
public:
template <typename T>
explicit DynamicString(T) {}
};
class BASE_EXPORT TracedValue {
class TracedValue {
public:
void WriteInt64(int64_t) && {}
void WriteUInt64(uint64_t) && {}
@@ -457,7 +421,7 @@ class BASE_EXPORT TracedValue {
TracedArray WriteArray() &&;
};
class BASE_EXPORT TracedDictionary {
class TracedDictionary {
public:
TracedValue AddItem(StaticString) { return TracedValue(); }
TracedValue AddItem(DynamicString) { return TracedValue(); }
@@ -473,7 +437,7 @@ class BASE_EXPORT TracedDictionary {
TracedArray AddArray(DynamicString);
};
class BASE_EXPORT TracedArray {
class TracedArray {
public:
TracedValue AppendItem() { return TracedValue(); }
@@ -485,7 +449,7 @@ class BASE_EXPORT TracedArray {
};
template <class T>
BASE_EXPORT void WriteIntoTracedValue(TracedValue, T&&) {}
void WriteIntoTracedValue(TracedValue, T&&) {}
struct Track {
explicit Track(uint64_t id) {}

View File

@@ -11,10 +11,8 @@
// Needed not for this file, but for every user of the TRACE_EVENT macros for
// the lambda definition. So included here for convenience.
#if 0
#include "base/tracing/protos/chrome_track_event.pbzero.h"
#include "third_party/perfetto/include/perfetto/tracing/event_context.h"
#include "third_party/perfetto/include/perfetto/tracing/string_helpers.h"
#endif
#endif // BASE_TRACE_EVENT_TYPED_MACROS_H_

View File

@@ -50,6 +50,9 @@ flags="$flags"'
fatal_linker_warnings=false
treat_warnings_as_errors=false
is_cronet_build=true
chrome_pgo_phase=2
enable_base_tracing=false
use_udev=false
use_aura=false
@@ -58,16 +61,17 @@ flags="$flags"'
use_gtk=false
use_platform_icu_alternatives=true
use_glib=false
enable_js_protobuf=false
disable_file_support=true
enable_websockets=false
use_kerberos=false
disable_file_support=true
disable_zstd_filter=false
enable_mdns=false
enable_reporting=false
include_transport_security_state_preload_list=false
use_nss_certs=false
enable_device_bound_sessions=false
use_nss_certs=false
enable_backup_ref_ptr_support=false
enable_dangling_raw_ptr_checks=false

View File

@@ -27,7 +27,7 @@ config("compiler") {
defines = [
"_LIBCPP_HAS_MUSL_LIBC",
"__UCLIBC__",
#"__UCLIBC__",
"__MUSL__",
]

View File

@@ -461,6 +461,7 @@ def cleanup_jail_symlinks(install_root: str) -> None:
os.remove(full_path)
os.symlink(relative_path, full_path)
def verify_library_deps(install_root: str) -> None:
"""
Verifies if all required libraries are present in the sysroot environment.
@@ -487,7 +488,6 @@ def verify_library_deps(install_root: str) -> None:
output = subprocess.check_output(cmd_readelf).decode()
for line in output.split("\n"):
if "NEEDED" in line:
print(file, line)
needed_libs.add(line.split("[")[1].split("]")[0])
missing_libs = needed_libs - shared_libs

View File

@@ -1,5 +1,5 @@
{
"listen": "socks://127.0.0.1:1080",
"listen": ["socks://127.0.0.1:1080", "http://127.0.0.1:8080"],
"proxy": "https://user:pass@domain.example",
"log": ""
}

View File

@@ -683,6 +683,8 @@ component("net") {
"log/net_log_values.h",
"log/net_log_with_source.cc",
"log/net_log_with_source.h",
"log/trace_net_log_observer.cc",
"log/trace_net_log_observer.h",
"nqe/cached_network_quality.cc",
"nqe/cached_network_quality.h",
"nqe/effective_connection_type.cc",
@@ -1654,7 +1656,7 @@ component("net") {
configs += [ "//build/config/compiler:optimize_max" ]
}
if (false) {
if (!is_cronet_build) {
deps += [ "//mojo/public/cpp/bindings:default_construct_tag" ]
}
}

View File

@@ -12,9 +12,9 @@
#ifndef NET_BASE_TRACE_EVENT_STUB_H_
#define NET_BASE_TRACE_EVENT_STUB_H_
#import "base/base_export.h"
#import "base/memory/weak_ptr.h"
#import "base/trace_event/trace_event_stub.h"
#include "base/base_export.h"
#include "base/memory/weak_ptr.h"
#include "base/trace_event/trace_event_stub.h"
namespace base::trace_event {

View File

@@ -8,7 +8,7 @@
#include "build/build_config.h"
#include "net/base/cronet_buildflags.h"
#if BUILDFLAG(CRONET_BUILD) && !BUILDFLAG(IS_APPLE)
#if BUILDFLAG(CRONET_BUILD)
#include "net/base/trace_event_stub.h" // IWYU pragma: export
#endif // BUILDFLAG(CRONET_BUILD) && !BUILDFLAG(IS_APPLE)

View File

@@ -16,7 +16,7 @@
#include "net/cookies/cookie_util.h"
#include "net/cookies/site_for_cookies.h"
#if 0
#if !BUILDFLAG(CRONET_BUILD)
#include "mojo/public/cpp/bindings/default_construct_tag.h"
#endif
@@ -60,7 +60,7 @@ std::string CookiePartitionKey::SerializedCookiePartitionKey::GetDebugString()
return out;
}
#if 0
#if !BUILDFLAG(CRONET_BUILD)
CookiePartitionKey::CookiePartitionKey(mojo::DefaultConstruct::Tag) {}
#endif
bool CookiePartitionKey::SerializedCookiePartitionKey::has_cross_site_ancestor()

View File

@@ -16,7 +16,7 @@
#include "net/base/schemeful_site.h"
#include "url/gurl.h"
#if 0
#if !BUILDFLAG(CRONET_BUILD)
#include "mojo/public/cpp/bindings/default_construct_tag.h"
#endif
@@ -60,7 +60,7 @@ class NET_EXPORT CookiePartitionKey {
static AncestorChainBit BoolToAncestorChainBit(bool val);
CookiePartitionKey() = delete;
#if 0
#if !BUILDFLAG(CRONET_BUILD)
explicit CookiePartitionKey(mojo::DefaultConstruct::Tag);
#endif
CookiePartitionKey(const CookiePartitionKey& other);

View File

@@ -257,12 +257,12 @@
#if __has_cpp_attribute(clang::musttail) && !defined(__arm__) && \
!defined(_ARCH_PPC) && !defined(__wasm__) && \
!(defined(_MSC_VER) && defined(_M_IX86)) && \
!(defined(__NDK_MAJOR__) && __NDK_MAJOR__ <= 24) && !defined(__mips__)
!(defined(__NDK_MAJOR__) && __NDK_MAJOR__ <= 24)
# ifndef PROTO2_OPENSOURCE
// Compilation fails on ARM32: b/195943306
// Compilation fails on powerpc64le: b/187985113
// Compilation fails on X86 Windows:
// 1
// https://github.com/llvm/llvm-project/issues/53271
# endif
#define PROTOBUF_MUSTTAIL [[clang::musttail]]
#define PROTOBUF_TAILCALL true

View File

@@ -69,6 +69,24 @@ component("url") {
configs += [ "//build/config/compiler:wexit_time_destructors" ]
if (is_android || is_robolectric) {
#deps += [ ":url_jni_headers" ]
if (!is_cronet_build) {
sources += [
"android/gurl_android.cc",
"android/gurl_android.h",
"android/origin_android.cc",
"android/parsed_android.cc",
"android/parsed_android.h",
]
}
}
if (is_robolectric) {
# Make jni.h available.
public_configs = [ "//third_party/jdk" ]
}
if (is_win) {
# Don't conflict with Windows' "url.dll".
output_name = "url_lib"

View File

@@ -154,10 +154,7 @@ CanonHostInfo::Family DoIPv4AddressToNumber(const CHAR* spec,
while (true) {
// If this is not the first character of a component, go to the next
// component.
// XXX: On mips64el, using
// `current_position != host.begin && spec[current_position - 1] != '.'`
// would have current_position going to the negative.
if (current_position > host.begin && spec[current_position - 1] != '.') {
if (current_position != host.begin && spec[current_position - 1] != '.') {
--current_position;
continue;
}

View File

@@ -49,10 +49,19 @@ nfpms:
- src: release/config/config.json
dst: /etc/sing-box/config.json
type: config
- src: release/config/sing-box.service
dst: /usr/lib/systemd/system/sing-box.service
- src: release/config/sing-box@.service
dst: /usr/lib/systemd/system/sing-box@.service
- src: release/completions/sing-box.bash
dst: /usr/share/bash-completion/completions/sing-box.bash
- src: release/completions/sing-box.fish
dst: /usr/share/fish/vendor_completions.d/sing-box.fish
- src: release/completions/sing-box.zsh
dst: /usr/share/zsh/site-functions/_sing-box
- src: LICENSE
dst: /usr/share/licenses/sing-box/LICENSE
deb:

View File

@@ -122,7 +122,7 @@ nfpms:
- deb
- rpm
- archlinux
- apk
# - apk
# - ipk
priority: extra
contents:

View File

@@ -68,7 +68,6 @@ release:
dist/*.zip \
dist/*.deb \
dist/*.rpm \
dist/*.apk \
dist/*_amd64.pkg.tar.zst \
dist/*_arm64.pkg.tar.zst \
dist/release

View File

@@ -188,7 +188,7 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
fastClose, cancel := common.ContextWithCancelCause(ctx)
timeout := canceler.New(fastClose, cancel, C.DNSTimeout)
var group task.Group
group.Append0(func(ctx context.Context) error {
group.Append0(func(_ context.Context) error {
for {
var (
message mDNS.Msg

View File

@@ -1,6 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.8.4
PKG_VERSION:=1.8.5
LUCI_TITLE:=LuCI Support for mihomo
LUCI_DEPENDS:=+luci-base +mihomo

View File

@@ -252,7 +252,7 @@ return view.extend({
s.tab('general', _('General Config'));
o = s.taboption('general', form.ListValue, 'log_level', _('Log Level'));
o = s.taboption('general', form.ListValue, 'log_level', '*' + ' ' + _('Log Level'));
o.value('silent');
o.value('error');
o.value('warning');
@@ -269,11 +269,10 @@ return view.extend({
o.value('always', _('Enable'));
o.value('off', _('Disable'));
o = s.taboption('general', widgets.NetworkSelect, 'outbound_interface', _('Outbound Interface'));
o = s.taboption('general', widgets.NetworkSelect, 'outbound_interface', '*' + ' ' + _('Outbound Interface'));
o.optional = true;
o.rmempty = false;
o = s.taboption('general', form.Flag, 'ipv6', _('IPv6'));
o = s.taboption('general', form.Flag, 'ipv6', '*' + ' ' + _('IPv6'));
o.rmempty = false;
o = s.taboption('general', form.Value, 'tcp_keep_alive_idle', _('TCP Keep Alive Idle'));
@@ -286,20 +285,20 @@ return view.extend({
s.tab('external_control', _('External Control Config'));
o = s.taboption('external_control', form.Value, 'ui_name', _('UI Name'));
o = s.taboption('external_control', form.Value, 'ui_name', '*' + ' ' + _('UI Name'));
o.rmempty = false;
o = s.taboption('external_control', form.Value, 'ui_url', _('UI Url'));
o = s.taboption('external_control', form.Value, 'ui_url', '*' + ' ' + _('UI Url'));
o.rmempty = false;
o.value('https://mirror.ghproxy.com/https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip', 'MetaCubeXD')
o.value('https://mirror.ghproxy.com/https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip', 'YACD')
o.value('https://mirror.ghproxy.com/https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip', 'Razord')
o = s.taboption('external_control', form.Value, 'api_port', _('API Port'));
o = s.taboption('external_control', form.Value, 'api_port', '*' + ' ' + _('API Port'));
o.datatype = 'port';
o.placeholder = '9090';
o = s.taboption('external_control', form.Value, 'api_secret', _('API Secret'));
o = s.taboption('external_control', form.Value, 'api_secret', '*' + ' ' + _('API Secret'));
o.rmempty = false;
o = s.taboption('external_control', form.Flag, 'selection_cache', _('Save Proxy Selection'));
@@ -307,30 +306,30 @@ return view.extend({
s.tab('inbound', _('Inbound Config'));
o = s.taboption('inbound', form.Flag, 'allow_lan', _('Allow Lan'));
o = s.taboption('inbound', form.Flag, 'allow_lan', '*' + ' ' + _('Allow Lan'));
o.rmempty = false;
o = s.taboption('inbound', form.Value, 'http_port', _('HTTP Port'));
o = s.taboption('inbound', form.Value, 'http_port', '*' + ' ' + _('HTTP Port'));
o.datatype = 'port';
o.placeholder = '8080';
o = s.taboption('inbound', form.Value, 'socks_port', _('SOCKS Port'));
o = s.taboption('inbound', form.Value, 'socks_port', '*' + ' ' + _('SOCKS Port'));
o.datatype = 'port';
o.placeholder = '1080';
o = s.taboption('inbound', form.Value, 'mixed_port', _('Mixed Port'));
o = s.taboption('inbound', form.Value, 'mixed_port', '*' + ' ' + _('Mixed Port'));
o.datatype = 'port';
o.placeholder = '7890';
o = s.taboption('inbound', form.Value, 'redir_port', _('Redirect Port'));
o = s.taboption('inbound', form.Value, 'redir_port', '*' + ' ' + _('Redirect Port'));
o.datatype = 'port';
o.placeholder = '7891';
o = s.taboption('inbound', form.Value, 'tproxy_port', _('TPROXY Port'));
o = s.taboption('inbound', form.Value, 'tproxy_port', '*' + ' ' + _('TPROXY Port'));
o.datatype = 'port';
o.placeholder = '7892';
o = s.taboption('inbound', form.Flag, 'authentication', _('Authentication'));
o = s.taboption('inbound', form.Flag, 'authentication', '*' + ' ' + _('Overwrite Authentication'));
o.rmempty = false;
o = s.taboption('inbound', form.SectionValue, '_authentications', form.TableSection, 'authentication', _('Edit Authentications'));
@@ -351,27 +350,27 @@ return view.extend({
s.tab('tun', _('TUN Config'));
o = s.taboption('tun', form.ListValue, 'tun_stack', _('Stack'));
o = s.taboption('tun', form.ListValue, 'tun_stack', '*' + ' ' + _('Stack'));
o.value('system', 'System');
o.value('gvisor', 'gVisor');
o.value('mixed', 'Mixed');
o = s.taboption('tun', form.Value, 'tun_mtu', _('MTU'));
o = s.taboption('tun', form.Value, 'tun_mtu', '*' + ' ' + _('MTU'));
o.placeholder = '9000';
o = s.taboption('tun', form.Flag, 'tun_gso', _('GSO'));
o = s.taboption('tun', form.Flag, 'tun_gso', '*' + ' ' + _('GSO'));
o.rmempty = false;
o = s.taboption('tun', form.Value, 'tun_gso_max_size', _('GSO Max Size'));
o = s.taboption('tun', form.Value, 'tun_gso_max_size', '*' + ' ' + _('GSO Max Size'));
o.placeholder = '65536';
o.depends('tun_gso', '1');
o = s.taboption('tun', form.Flag, 'tun_endpoint_independent_nat', _('Endpoint Independent NAT'));
o = s.taboption('tun', form.Flag, 'tun_endpoint_independent_nat', '*' + ' ' + _('Endpoint Independent NAT'));
o.rmempty = false;
s.tab('dns', _('DNS Config'));
o = s.taboption('dns', form.Value, 'dns_port', _('DNS Port'));
o = s.taboption('dns', form.Value, 'dns_port', '*' + ' ' + _('DNS Port'));
o.datatype = 'port';
o.placeholder = '1053';

View File

@@ -244,8 +244,8 @@ msgstr "Redirect 端口"
msgid "TPROXY Port"
msgstr "TPROXY 端口"
msgid "Authentication"
msgid "身份验证"
msgid "Overwrite Authentication"
msgstr "覆盖身份验证"
msgid "Edit Authentications"
msgstr "编辑身份验证"

View File

@@ -146,13 +146,13 @@ start_service() {
# do mixin
log_level="$log_level" ipv6="$ipv6" \
ui_path="ui" ui_name="$ui_name" ui_url="$ui_url" api_listen="0.0.0.0:$api_port" api_secret="$api_secret" \
http_port="$http_port" socks_port="$socks_port" mixed_port="$mixed_port" redir_port="$redir_port" tproxy_port="$tproxy_port" \
allow_lan="$allow_lan" http_port="$http_port" socks_port="$socks_port" mixed_port="$mixed_port" redir_port="$redir_port" tproxy_port="$tproxy_port" \
tun_enable="$tun_enable" tun_stack="$tun_stack" tun_device="$TUN_DEVICE" tun_mtu="$tun_mtu" tun_gso="$tun_gso" tun_gso_max_size="$tun_gso_max_size" tun_endpoint_independent_nat="$tun_endpoint_independent_nat" \
dns_enable="true" dns_listen="0.0.0.0:$dns_port" \
yq -M -i '
.log-level = env(log_level) | .ipv6 = env(ipv6) == 1 |
.external-ui = env(ui_path) | .external-ui-name = env(ui_name) | .external-ui-url = env(ui_url) | .external-controller = env(api_listen) | .secret = env(api_secret) |
.port = env(http_port) | .socks-port = env(socks_port) | .mixed-port = env(mixed_port) | .redir-port = env(redir_port) | .tproxy-port = env(tproxy_port) |
.allow-lan = env(allow_lan) == 1 | .port = env(http_port) | .socks-port = env(socks_port) | .mixed-port = env(mixed_port) | .redir-port = env(redir_port) | .tproxy-port = env(tproxy_port) |
.tun.enable = env(tun_enable) == 1 | .tun.stack = env(tun_stack) | .tun.device = env(tun_device) | .tun.mtu = env(tun_mtu) | .tun.gso = env(tun_gso) == 1 | .tun.gso-max-size = env(tun_gso_max_size) | .tun.endpoint-independent-nat = env(tun_endpoint_independent_nat) == 1 |
.dns.enable = env(dns_enable) | .dns.listen = env(dns_listen)
' "$RUN_PROFILE_PATH"
@@ -178,10 +178,6 @@ start_service() {
.geo-auto-update = env(geox_auto_update) == 1 | .geo-update-interval = env(geox_update_interval)
' "$RUN_PROFILE_PATH"
if [ "$authentication" == 1 ]; then
yq -M -i 'del(.authentication)' "$RUN_PROFILE_PATH"
config_foreach mixin_authentications "authentication"
fi
if [ "$fake_ip_filter" == 1 ]; then
fake_ip_filter_mode="$fake_ip_filter_mode" \
yq -M -i 'del(.dns.fake-ip-filter) | .dns.fake-ip-filter-mode = env(fake_ip_filter_mode)' "$RUN_PROFILE_PATH"
@@ -205,9 +201,6 @@ start_service() {
fi
fi
yq -M -i 'del (.bind-address)' "$RUN_PROFILE_PATH"
if [ "$tun_enable" == 1 ]; then
yq -M -i '.tun.auto-route = false | .tun.auto-redirect = false | .tun.auto-detect-interface = false | .tun.dns-hijack = []' "$RUN_PROFILE_PATH"
fi
if [ -n "$outbound_interface" ]; then
local outbound_device
network_get_device outbound_device "$outbound_interface"
@@ -215,6 +208,13 @@ start_service() {
outbound_device="$outbound_device" yq -M -i '.interface-name = env(outbound_device)' "$RUN_PROFILE_PATH"
fi
fi
if [ "$authentication" == 1 ]; then
yq -M -i 'del(.authentication)' "$RUN_PROFILE_PATH"
config_foreach mixin_authentications "authentication"
fi
if [ "$tun_enable" == 1 ]; then
yq -M -i '.tun.auto-route = false | .tun.auto-redirect = false | .tun.auto-detect-interface = false | .tun.dns-hijack = []' "$RUN_PROFILE_PATH"
fi
# test profile
if [ "$test_profile" == 1 ]; then
log "Profile testing..."

View File

@@ -6,12 +6,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=sing-box
PKG_VERSION:=1.9.6
PKG_VERSION:=1.9.7
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=09412fcc7b3a56c325886af090fb88b2cd8a61984856da43e2d16ff203f3a267
PKG_HASH:=5b015352f3434bb780af01a6b1f6c0fe706166d6c44a69547e29892f0920b944
PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=LICENSE

View File

@@ -30,13 +30,13 @@ define Download/geosite
HASH:=aeefcd8b3e5b27c22e2e7dfb6ff5e8d0741fd540d96ab355fd00a0472f5884a7
endef
GEOSITE_IRAN_VER:=202409300035
GEOSITE_IRAN_VER:=202410070035
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
define Download/geosite-ir
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
URL_FILE:=iran.dat
FILE:=$(GEOSITE_IRAN_FILE)
HASH:=b10725db0a82d919cc72cd161dec4b14b6870c760322f6e503c55de3c1828f3d
HASH:=be31e14b61dc3e98c9ac518686bc932b45aa04dd2f9491d18456417ba28f3b70
endef
define Package/v2ray-geodata/template

View File

@@ -6,6 +6,5 @@ namespace ServiceLib.Base
{
protected static Config? _config;
protected Func<EViewAction, object?, Task<bool>>? _updateView;
protected NoticeHandler? _noticeHandler;
}
}

View File

@@ -36,7 +36,7 @@ namespace ServiceLib.Common
}
};
using var downloader = new DownloadService(downloadOpt);
using var downloader = new Downloader.DownloadService(downloadOpt);
downloader.DownloadFileCompleted += (sender, value) =>
{
if (value.Error != null)
@@ -76,7 +76,7 @@ namespace ServiceLib.Common
int totalSecond = 0;
var hasValue = false;
double maxSpeed = 0;
using var downloader = new DownloadService(downloadOpt);
using var downloader = new Downloader.DownloadService(downloadOpt);
//downloader.DownloadStarted += (sender, value) =>
//{
// if (progress != null)
@@ -145,7 +145,7 @@ namespace ServiceLib.Common
var progressPercentage = 0;
var hasValue = false;
using var downloader = new DownloadService(downloadOpt);
using var downloader = new Downloader.DownloadService(downloadOpt);
downloader.DownloadStarted += (sender, value) =>
{
progress?.Report(0);

View File

@@ -4,11 +4,14 @@
{
v2fly = 1,
Xray = 2,
//SagerNet = 3,
v2fly_v5 = 4,
//clash = 11,
//clash_meta = 12,
mihomo = 13,
hysteria = 21,
naiveproxy = 22,
tuic = 23,

View File

@@ -2,8 +2,9 @@
global using ServiceLib.Common;
global using ServiceLib.Enums;
global using ServiceLib.Handler;
global using ServiceLib.Handler.CoreConfig;
global using ServiceLib.Handler.Fmt;
global using ServiceLib.Handler.Statistics;
global using ServiceLib.Services;
global using ServiceLib.Services.Statistics;
global using ServiceLib.Services.CoreConfig;
global using ServiceLib.Models;
global using ServiceLib.Resx;

View File

@@ -1,13 +1,13 @@
namespace ServiceLib.Handler
{
public sealed class LazyConfig
public sealed class AppHandler
{
private static readonly Lazy<LazyConfig> _instance = new(() => new());
private static readonly Lazy<AppHandler> _instance = new(() => new());
private Config _config;
private int? _statePort;
private int? _statePort2;
public static LazyConfig Instance => _instance.Value;
private Job? _processJob;
public static AppHandler Instance => _instance.Value;
public Config Config => _config;
public int StatePort
@@ -28,21 +28,49 @@
}
}
private Job? _processJob;
#region Init
public LazyConfig()
public AppHandler()
{
}
public bool InitApp()
{
if (ConfigHandler.LoadConfig(ref _config) != 0)
{
return false;
}
Thread.CurrentThread.CurrentUICulture = new(_config.uiItem.currentLanguage);
//Under Win10
if (Utils.IsWindows() && Environment.OSVersion.Version.Major < 10)
{
Environment.SetEnvironmentVariable("DOTNET_EnableWriteXorExecute", "0", EnvironmentVariableTarget.User);
}
return true;
}
public bool InitComponents()
{
Logging.Setup();
Logging.LoggingEnabled(true);
Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}");
Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
Logging.ClearLogs();
SQLiteHelper.Instance.CreateTable<SubItem>();
SQLiteHelper.Instance.CreateTable<ProfileItem>();
SQLiteHelper.Instance.CreateTable<ServerStatItem>();
SQLiteHelper.Instance.CreateTable<RoutingItem>();
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
SQLiteHelper.Instance.CreateTable<DNSItem>();
return true;
}
#region Config
#endregion Init
public void SetConfig(Config config) => _config = config;
#region Config
public int GetLocalPort(EInboundProtocol protocol)
{

View File

@@ -76,7 +76,7 @@ namespace ServiceLib.Handler
return;
}
var urlBase = $"{GetApiUrl()}/proxies";
urlBase += @"/{0}/delay?timeout=10000&url=" + LazyConfig.Instance.Config.speedTestItem.speedPingTestUrl;
urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.speedTestItem.speedPingTestUrl;
List<Task> tasks = new List<Task>();
foreach (var it in lstProxy)
@@ -200,7 +200,7 @@ namespace ServiceLib.Handler
private string GetApiUrl()
{
return $"{Global.HttpProtocol}{Global.Loopback}:{LazyConfig.Instance.StatePort2}";
return $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort2}";
}
}
}

View File

@@ -364,7 +364,7 @@ namespace ServiceLib.Handler
public static int AddServer(Config config, ProfileItem profileItem)
{
var item = LazyConfig.Instance.GetProfileItem(profileItem.indexId);
var item = AppHandler.Instance.GetProfileItem(profileItem.indexId);
if (item is null)
{
item = profileItem;
@@ -476,7 +476,7 @@ namespace ServiceLib.Handler
{
foreach (var it in indexes)
{
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
var item = AppHandler.Instance.GetProfileItem(it.indexId);
if (item is null)
{
continue;
@@ -541,7 +541,7 @@ namespace ServiceLib.Handler
public static ProfileItem? GetDefaultServer(Config config)
{
var item = LazyConfig.Instance.GetProfileItem(config.indexId);
var item = AppHandler.Instance.GetProfileItem(config.indexId);
if (item is null)
{
var item2 = SQLiteHelper.Instance.Table<ProfileItem>().FirstOrDefault();
@@ -677,7 +677,7 @@ namespace ServiceLib.Handler
/// <returns></returns>
public static int EditCustomServer(Config config, ProfileItem profileItem)
{
var item = LazyConfig.Instance.GetProfileItem(profileItem.indexId);
var item = AppHandler.Instance.GetProfileItem(profileItem.indexId);
if (item is null)
{
item = profileItem;
@@ -717,7 +717,7 @@ namespace ServiceLib.Handler
profileItem.id = profileItem.id.TrimEx();
profileItem.security = profileItem.security.TrimEx();
if (!LazyConfig.Instance.GetShadowsocksSecurities(profileItem).Contains(profileItem.security))
if (!AppHandler.Instance.GetShadowsocksSecurities(profileItem).Contains(profileItem.security))
{
return -1;
}
@@ -894,7 +894,7 @@ namespace ServiceLib.Handler
public static int SortServers(Config config, string subId, string colName, bool asc)
{
var lstModel = LazyConfig.Instance.ProfileItems(subId, "");
var lstModel = AppHandler.Instance.ProfileItems(subId, "");
if (lstModel.Count <= 0)
{
return -1;
@@ -1026,7 +1026,7 @@ namespace ServiceLib.Handler
public static Tuple<int, int> DedupServerList(Config config, string subId)
{
var lstProfile = LazyConfig.Instance.ProfileItems(subId);
var lstProfile = AppHandler.Instance.ProfileItems(subId);
List<ProfileItem> lstKeep = new();
List<ProfileItem> lstRemove = new();
@@ -1126,7 +1126,7 @@ namespace ServiceLib.Handler
{
try
{
var item = LazyConfig.Instance.GetProfileItem(indexId);
var item = AppHandler.Instance.GetProfileItem(indexId);
if (item == null)
{
return 0;
@@ -1161,7 +1161,7 @@ namespace ServiceLib.Handler
return -1;
}
var profileItem = LazyConfig.Instance.GetProfileItem(indexId) ?? new();
var profileItem = AppHandler.Instance.GetProfileItem(indexId) ?? new();
profileItem.indexId = indexId;
profileItem.remarks = coreType == ECoreType.sing_box ? ResUI.menuSetDefaultMultipleServer : ResUI.menuSetDefaultLoadBalanceServer;
profileItem.address = Global.CoreMultipleLoadConfigFileName;
@@ -1196,7 +1196,7 @@ namespace ServiceLib.Handler
if (isSub && Utils.IsNotEmpty(subid))
{
RemoveServerViaSubid(config, subid, isSub);
subFilter = LazyConfig.Instance.GetSubItem(subid)?.filter ?? "";
subFilter = AppHandler.Instance.GetSubItem(subid)?.filter ?? "";
}
int countServers = 0;
@@ -1235,7 +1235,7 @@ namespace ServiceLib.Handler
//Check for duplicate indexId
if (lstDbIndexId is null)
{
lstDbIndexId = LazyConfig.Instance.ProfileItemIndexes("");
lstDbIndexId = AppHandler.Instance.ProfileItemIndexes("");
}
if (lstAdd.Any(t => t.indexId == existItem.indexId)
|| lstDbIndexId.Any(t => t == existItem.indexId))
@@ -1295,7 +1295,7 @@ namespace ServiceLib.Handler
return -1;
}
var subItem = LazyConfig.Instance.GetSubItem(subid);
var subItem = AppHandler.Instance.GetSubItem(subid);
var subRemarks = subItem?.remarks;
var preSocksPort = subItem?.preSocksPort;
@@ -1430,7 +1430,7 @@ namespace ServiceLib.Handler
List<ProfileItem>? lstOriSub = null;
if (isSub && Utils.IsNotEmpty(subid))
{
lstOriSub = LazyConfig.Instance.ProfileItems(subid);
lstOriSub = AppHandler.Instance.ProfileItems(subid);
}
var counter = 0;
@@ -1500,7 +1500,7 @@ namespace ServiceLib.Handler
public static int AddSubItem(Config config, SubItem subItem)
{
var item = LazyConfig.Instance.GetSubItem(subItem.id);
var item = AppHandler.Instance.GetSubItem(subItem.id);
if (item is null)
{
item = subItem;
@@ -1577,7 +1577,7 @@ namespace ServiceLib.Handler
public static int DeleteSubItem(Config config, string id)
{
var item = LazyConfig.Instance.GetSubItem(id);
var item = AppHandler.Instance.GetSubItem(id);
if (item is null)
{
return 0;
@@ -1752,7 +1752,7 @@ namespace ServiceLib.Handler
public static RoutingItem GetDefaultRouting(Config config)
{
var item = LazyConfig.Instance.GetRoutingItem(config.routingBasicItem.routingIndexId);
var item = AppHandler.Instance.GetRoutingItem(config.routingBasicItem.routingIndexId);
if (item is null)
{
var item2 = SQLiteHelper.Instance.Table<RoutingItem>().FirstOrDefault(t => t.locked == false);
@@ -1766,7 +1766,7 @@ namespace ServiceLib.Handler
public static int InitBuiltinRouting(Config config, bool blImportAdvancedRules = false)
{
var ver = "V3-";
var items = LazyConfig.Instance.RoutingItems();
var items = AppHandler.Instance.RoutingItems();
if (blImportAdvancedRules || items.Where(t => t.remarks.StartsWith(ver)).ToList().Count <= 0)
{
var maxSort = items.Count;
@@ -1832,7 +1832,7 @@ namespace ServiceLib.Handler
public static int InitBuiltinDNS(Config config)
{
var items = LazyConfig.Instance.DNSItems();
var items = AppHandler.Instance.DNSItems();
if (items.Count <= 0)
{
var item = new DNSItem()

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.CoreConfig
namespace ServiceLib.Handler
{
/// <summary>
/// Core configuration file processing class
@@ -15,19 +15,19 @@
msg = ResUI.CheckServerSettings;
return -1;
}
var config = LazyConfig.Instance.Config;
var config = AppHandler.Instance.Config;
msg = ResUI.InitialConfiguration;
if (node.configType == EConfigType.Custom)
{
if (node.coreType is ECoreType.mihomo)
if (node.coreType is ECoreType.mihomo)
{
var configGenClash = new CoreConfigClash(config);
var configGenClash = new CoreConfigClashService(config);
return configGenClash.GenerateClientCustomConfig(node, fileName, out msg);
}
if (node.coreType is ECoreType.sing_box)
{
var configGenSingbox = new CoreConfigSingbox(config);
var configGenSingbox = new CoreConfigSingboxService(config);
return configGenSingbox.GenerateClientCustomConfig(node, fileName, out msg);
}
else
@@ -35,9 +35,9 @@
return GenerateClientCustomConfig(node, fileName, out msg);
}
}
else if (LazyConfig.Instance.GetCoreType(node, node.configType) == ECoreType.sing_box)
else if (AppHandler.Instance.GetCoreType(node, node.configType) == ECoreType.sing_box)
{
var configGenSingbox = new CoreConfigSingbox(config);
var configGenSingbox = new CoreConfigSingboxService(config);
if (configGenSingbox.GenerateClientConfigContent(node, out SingboxConfig? singboxConfig, out msg) != 0)
{
return -1;
@@ -53,7 +53,7 @@
}
else
{
var coreConfigV2ray = new CoreConfigV2ray(config);
var coreConfigV2ray = new CoreConfigV2rayService(config);
if (coreConfigV2ray.GenerateClientConfigContent(node, out V2rayConfig? v2rayConfig, out msg) != 0)
{
return -1;
@@ -128,7 +128,7 @@
{
if (coreType == ECoreType.sing_box)
{
if (new CoreConfigSingbox(config).GenerateClientSpeedtestConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0)
if (new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0)
{
return -1;
}
@@ -136,7 +136,7 @@
}
else
{
if (new CoreConfigV2ray(config).GenerateClientSpeedtestConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0)
if (new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0)
{
return -1;
}
@@ -150,7 +150,7 @@
msg = ResUI.CheckServerSettings;
if (coreType == ECoreType.sing_box)
{
if (new CoreConfigSingbox(config).GenerateClientMultipleLoadConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0)
if (new CoreConfigSingboxService(config).GenerateClientMultipleLoadConfig(selecteds, out SingboxConfig? singboxConfig, out msg) != 0)
{
return -1;
}
@@ -158,7 +158,7 @@
}
else if (coreType == ECoreType.Xray)
{
if (new CoreConfigV2ray(config).GenerateClientMultipleLoadConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0)
if (new CoreConfigV2rayService(config).GenerateClientMultipleLoadConfig(selecteds, out V2rayConfig? v2rayConfig, out msg) != 0)
{
return -1;
}

View File

@@ -8,12 +8,14 @@ namespace ServiceLib.Handler
/// </summary>
public class CoreHandler
{
private static readonly Lazy<CoreHandler> _instance = new(() => new());
public static CoreHandler Instance => _instance.Value;
private Config _config;
private Process? _process;
private Process? _processPre;
private Action<bool, string> _updateFunc;
public CoreHandler(Config config, Action<bool, string> update)
public void Init(Config config, Action<bool, string> update)
{
_config = config;
_updateFunc = update;
@@ -106,17 +108,17 @@ namespace ServiceLib.Handler
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
foreach (var it in coreInfo)
{
if (it.coreType == ECoreType.v2rayN)
if (it.CoreType == ECoreType.v2rayN)
{
continue;
}
foreach (string vName in it.coreExes)
foreach (string vName in it.CoreExes)
{
var existing = Process.GetProcessesByName(vName);
foreach (Process p in existing)
{
string? path = p.MainModule?.FileName;
if (path == Utils.GetExeName(Utils.GetBinPath(vName, it.coreType.ToString())))
if (path == Utils.GetExeName(Utils.GetBinPath(vName, it.CoreType.ToString())))
{
KillProcess(p);
}
@@ -149,10 +151,10 @@ namespace ServiceLib.Handler
private string CoreFindExe(CoreInfo coreInfo)
{
string fileName = string.Empty;
foreach (string name in coreInfo.coreExes)
foreach (string name in coreInfo.CoreExes)
{
string vName = Utils.GetExeName(name);
vName = Utils.GetBinPath(vName, coreInfo.coreType.ToString());
vName = Utils.GetBinPath(vName, coreInfo.CoreType.ToString());
if (File.Exists(vName))
{
fileName = vName;
@@ -161,7 +163,7 @@ namespace ServiceLib.Handler
}
if (Utils.IsNullOrEmpty(fileName))
{
string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.coreType.ToString()), string.Join(", ", coreInfo.coreExes.ToArray()), coreInfo.coreUrl);
string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
Logging.SaveLog(msg);
ShowMsg(false, msg);
}
@@ -182,7 +184,7 @@ namespace ServiceLib.Handler
//{
// coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
//}
var coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
var coreType = AppHandler.Instance.GetCoreType(node, node.configType);
_config.runningCoreType = coreType;
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
@@ -207,7 +209,7 @@ namespace ServiceLib.Handler
configType = EConfigType.SOCKS,
address = Global.Loopback,
sni = node.address, //Tun2SocksAddress
port = LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks)
port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)
};
}
else if ((node.configType == EConfigType.Custom && node.preSocksPort > 0))
@@ -286,7 +288,7 @@ namespace ServiceLib.Handler
StartInfo = new()
{
FileName = fileName,
Arguments = string.Format(coreInfo.arguments, configPath),
Arguments = string.Format(coreInfo.Arguments, configPath),
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false,
RedirectStandardOutput = displayLog,
@@ -339,7 +341,7 @@ namespace ServiceLib.Handler
startUpSuccessful = true;
}
LazyConfig.Instance.AddProcess(proc.Handle);
AppHandler.Instance.AddProcess(proc.Handle);
return proc;
}
catch (Exception ex)

View File

@@ -19,7 +19,7 @@ namespace ServiceLib.Handler
{
InitCoreInfo();
}
return _coreInfo?.FirstOrDefault(t => t.coreType == coreType);
return _coreInfo?.FirstOrDefault(t => t.CoreType == coreType);
}
public List<CoreInfo> GetCoreInfo()
@@ -37,139 +37,135 @@ namespace ServiceLib.Handler
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.v2rayN,
coreUrl = Global.NUrl,
coreReleaseApiUrl = Global.NUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
coreDownloadUrl32 = Global.NUrl + "/download/{0}/v2rayN-32.zip",
coreDownloadUrl64 = Global.NUrl + "/download/{0}/v2rayN.zip",
coreDownloadUrlArm64 = Global.NUrl + "/download/{0}/v2rayN-arm64.zip",
coreDownloadUrlLinux32 = Global.NUrl + "/download/{0}/v2rayN-linux-32.zip",
coreDownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
coreDownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
CoreType = ECoreType.v2rayN,
Url = Global.NUrl,
ReleaseApiUrl = Global.NUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin32 = Global.NUrl + "/download/{0}/v2rayN-windows-32.zip",
DownloadUrlWin64 = Global.NUrl + "/download/{0}/v2rayN-windows-64.zip",
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip",
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.v2fly,
coreExes = new List<string> { "wv2ray", "v2ray" },
arguments = "",
coreUrl = Global.V2flyCoreUrl,
coreReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
match = "V2Ray",
versionArg = "-version",
redirectInfo = true,
CoreType = ECoreType.v2fly,
CoreExes = new List<string> { "wv2ray", "v2ray" },
Arguments = "",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "-version",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.v2fly_v5,
coreExes = new List<string> { "v2ray" },
arguments = "run -c config.json -format jsonv5",
coreUrl = Global.V2flyCoreUrl,
coreReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
match = "V2Ray",
versionArg = "version",
redirectInfo = true,
CoreType = ECoreType.v2fly_v5,
CoreExes = new List<string> { "v2ray" },
Arguments = "run -c config.json -format jsonv5",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "version",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.Xray,
coreExes = new List<string> { "xray", "wxray" },
arguments = "run {0}",
coreUrl = Global.XrayCoreUrl,
coreReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
coreDownloadUrl32 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-32.zip",
coreDownloadUrl64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
coreDownloadUrlArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
coreDownloadUrlLinux32 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-32.zip",
coreDownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
coreDownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
match = "Xray",
versionArg = "-version",
redirectInfo = true,
CoreType = ECoreType.Xray,
CoreExes = new List<string> { "xray", "wxray" },
Arguments = "run {0}",
Url = Global.XrayCoreUrl,
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin32 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-32.zip",
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
Match = "Xray",
VersionArg = "-version",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.mihomo,
coreExes = new List<string> { $"mihomo-windows-amd64{(Avx2.X64.IsSupported ? "" : "-compatible")}", "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-windows-386", "mihomo", "clash" },
arguments = "-f config.json" + PortableMode(),
coreUrl = Global.MihomoCoreUrl,
coreReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
coreDownloadUrl32 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-386-{0}.zip",
coreDownloadUrl64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
coreDownloadUrlArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
coreDownloadUrlLinux32 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-386-{0}.gz",
coreDownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
coreDownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
match = "Mihomo",
versionArg = "-v",
redirectInfo = true,
CoreType = ECoreType.mihomo,
CoreExes = new List<string> { $"mihomo-windows-amd64{(Avx2.X64.IsSupported ? "" : "-compatible")}", "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-windows-386", "mihomo", "clash" },
Arguments = "-f config.json" + PortableMode(),
Url = Global.MihomoCoreUrl,
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin32 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-386-{0}.zip",
DownloadUrlWin64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
Match = "Mihomo",
VersionArg = "-v",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.hysteria,
coreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
arguments = "",
coreUrl = Global.HysteriaCoreUrl,
coreReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
redirectInfo = true,
CoreType = ECoreType.hysteria,
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.naiveproxy,
coreExes = new List<string> { "naiveproxy", "naive" },
arguments = "config.json",
coreUrl = Global.NaiveproxyCoreUrl,
redirectInfo = false,
CoreType = ECoreType.naiveproxy,
CoreExes = new List<string> { "naiveproxy", "naive" },
Arguments = "config.json",
Url = Global.NaiveproxyCoreUrl,
RedirectInfo = false,
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.tuic,
coreExes = new List<string> { "tuic-client", "tuic" },
arguments = "-c config.json",
coreUrl = Global.TuicCoreUrl,
redirectInfo = true,
CoreType = ECoreType.tuic,
CoreExes = new List<string> { "tuic-client", "tuic" },
Arguments = "-c config.json",
Url = Global.TuicCoreUrl,
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.sing_box,
coreExes = new List<string> { "sing-box-client", "sing-box" },
arguments = "run {0} --disable-color",
coreUrl = Global.SingboxCoreUrl,
redirectInfo = true,
coreReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
coreDownloadUrl32 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-386.zip",
coreDownloadUrl64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-amd64.zip",
coreDownloadUrlArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
coreDownloadUrlLinux32 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-386.tar.gz",
coreDownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
coreDownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
match = "sing-box",
versionArg = "version",
CoreType = ECoreType.sing_box,
CoreExes = new List<string> { "sing-box-client", "sing-box" },
Arguments = "run {0} --disable-color",
Url = Global.SingboxCoreUrl,
RedirectInfo = true,
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin32 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-386.zip",
DownloadUrlWin64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-amd64.zip",
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
Match = "sing-box",
VersionArg = "version",
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.juicity,
coreExes = new List<string> { "juicity-client", "juicity" },
arguments = "run -c config.json",
coreUrl = Global.JuicityCoreUrl
CoreType = ECoreType.juicity,
CoreExes = new List<string> { "juicity-client", "juicity" },
Arguments = "run -c config.json",
Url = Global.JuicityCoreUrl
});
_coreInfo.Add(new CoreInfo
{
coreType = ECoreType.hysteria2,
coreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
arguments = "",
coreUrl = Global.HysteriaCoreUrl,
coreReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
redirectInfo = true,
CoreType = ECoreType.hysteria2,
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
});
}

View File

@@ -4,6 +4,9 @@ namespace ServiceLib.Handler
{
public class NoticeHandler
{
private static readonly Lazy<NoticeHandler> _instance = new(() => new());
public static NoticeHandler Instance => _instance.Value;
public void Enqueue(string? content)
{
if (content.IsNullOrEmpty())

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.Statistics
namespace ServiceLib.Handler
{
public class StatisticsHandler
{
@@ -9,8 +9,8 @@
private ServerStatItem? _serverStatItem;
private List<ServerStatItem> _lstServerStat;
private Action<ServerSpeedItem> _updateFunc;
private StatisticsV2ray? _statisticsV2Ray;
private StatisticsSingbox? _statisticsSingbox;
private StatisticsV2rayService? _statisticsV2Ray;
private StatisticsSingboxService? _statisticsSingbox;
public List<ServerStatItem> ServerStat => _lstServerStat;
@@ -25,8 +25,8 @@
InitData();
_statisticsV2Ray = new StatisticsV2ray(config, UpdateServerStat);
_statisticsSingbox = new StatisticsSingbox(config, UpdateServerStat);
_statisticsV2Ray = new StatisticsV2rayService(config, UpdateServerStat);
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStat);
}
public void Close()

View File

@@ -20,11 +20,11 @@
await Task.Delay(60000);
Logging.SaveLog("UpdateTaskRunSubscription");
var updateHandle = new UpdateHandler();
var updateHandle = new UpdateService();
while (true)
{
var updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();
var lstSubs = LazyConfig.Instance.SubItems()
var lstSubs = AppHandler.Instance.SubItems()
.Where(t => t.autoUpdateInterval > 0)
.Where(t => updateTime - t.updateTime >= t.autoUpdateInterval * 60)
.ToList();
@@ -53,7 +53,7 @@
//await Task.Delay(1000 * 120);
Logging.SaveLog("UpdateTaskRunGeo");
var updateHandle = new UpdateHandler();
var updateHandle = new UpdateService();
while (true)
{
await Task.Delay(1000 * 3600);

View File

@@ -17,7 +17,7 @@ namespace ServiceLib.Handler
public WebDavHandler()
{
_config = LazyConfig.Instance.Config;
_config = AppHandler.Instance.Config;
}
private async Task<bool> GetClient()
@@ -110,7 +110,7 @@ namespace ServiceLib.Handler
}
else
{
SaveLog(result.Description);
SaveLog(result.Description);
}
}
catch (Exception ex)

View File

@@ -2,10 +2,10 @@
{
public class CheckUpdateItem
{
public bool? isSelected { get; set; }
public string coreType { get; set; }
public string? remarks { get; set; }
public string? fileName { get; set; }
public bool? isFinished { get; set; }
public bool? IsSelected { get; set; }
public string? CoreType { get; set; }
public string? Remarks { get; set; }
public string? FileName { get; set; }
public bool? IsFinished { get; set; }
}
}

View File

@@ -103,8 +103,6 @@
public int trayMenuServersLimit { get; set; } = 20;
public bool enableHWA { get; set; } = false;
public bool enableLog { get; set; } = true;
}
[Serializable]

View File

@@ -3,28 +3,18 @@
[Serializable]
public class CoreInfo
{
public ECoreType coreType { get; set; }
public List<string> coreExes { get; set; }
public string arguments { get; set; }
public string coreUrl { get; set; }
public string coreReleaseApiUrl { get; set; }
public string coreDownloadUrl32 { get; set; }
public string coreDownloadUrl64 { get; set; }
public string coreDownloadUrlArm64 { get; set; }
public string? coreDownloadUrlLinux32 { get; set; }
public string? coreDownloadUrlLinux64 { get; set; }
public string? coreDownloadUrlLinuxArm64 { get; set; }
public string match { get; set; }
public string versionArg { get; set; }
public bool redirectInfo { get; set; }
public ECoreType CoreType { get; set; }
public List<string>? CoreExes { get; set; }
public string? Arguments { get; set; }
public string? Url { get; set; }
public string? ReleaseApiUrl { get; set; }
public string? DownloadUrlWin32 { get; set; }
public string? DownloadUrlWin64 { get; set; }
public string? DownloadUrlWinArm64 { get; set; }
public string? DownloadUrlLinux64 { get; set; }
public string? DownloadUrlLinuxArm64 { get; set; }
public string? Match { get; set; }
public string? VersionArg { get; set; }
public bool RedirectInfo { get; set; }
}
}

View File

@@ -1,13 +1,13 @@
namespace ServiceLib.Handler.CoreConfig
namespace ServiceLib.Services.CoreConfig
{
/// <summary>
/// Core configuration file processing class
/// </summary>
public class CoreConfigClash
public class CoreConfigClashService
{
private Config _config;
public CoreConfigClash(Config config)
public CoreConfigClashService(Config config)
{
_config = config;
}
@@ -78,14 +78,14 @@
}
//port
fileContent["port"] = LazyConfig.Instance.GetLocalPort(EInboundProtocol.http);
fileContent["port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
//socks-port
fileContent["socks-port"] = LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks);
fileContent["socks-port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
//log-level
fileContent["log-level"] = GetLogLevel(_config.coreBasicItem.loglevel);
//external-controller
fileContent["external-controller"] = $"{Global.Loopback}:{LazyConfig.Instance.StatePort2}";
fileContent["external-controller"] = $"{Global.Loopback}:{AppHandler.Instance.StatePort2}";
//allow-lan
if (_config.inbound[0].allowLANConn)
{

View File

@@ -2,13 +2,13 @@
using System.Net;
using System.Net.NetworkInformation;
namespace ServiceLib.Handler.CoreConfig
namespace ServiceLib.Services.CoreConfig
{
public class CoreConfigSingbox
public class CoreConfigSingboxService
{
private Config _config;
public CoreConfigSingbox(Config config)
public CoreConfigSingboxService(Config config)
{
_config = config;
}
@@ -120,7 +120,7 @@ namespace ServiceLib.Handler.CoreConfig
singboxConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
singboxConfig.outbounds.RemoveAt(0);
int httpPort = LazyConfig.Instance.GetLocalPort(EInboundProtocol.speedtest);
int httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds)
{
@@ -132,7 +132,7 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
var item = AppHandler.Instance.GetProfileItem(it.indexId);
if (it.configType is EConfigType.VMess or EConfigType.VLESS)
{
if (item is null || Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id))
@@ -192,7 +192,7 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
if ((it.configType is EConfigType.VLESS or EConfigType.Trojan)
if (it.configType is EConfigType.VLESS or EConfigType.Trojan
&& item.streamSecurity == Global.StreamSecurityReality
&& item.publicKey.IsNullOrEmpty())
{
@@ -282,7 +282,7 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
var item = AppHandler.Instance.GetProfileItem(it.indexId);
if (item is null)
{
continue;
@@ -476,7 +476,7 @@ namespace ServiceLib.Handler.CoreConfig
singboxConfig.inbounds = [];
if (!_config.tunModeItem.enableTun
|| (_config.tunModeItem.enableTun && _config.tunModeItem.enableExInbound && _config.runningCoreType == ECoreType.sing_box))
|| _config.tunModeItem.enableTun && _config.tunModeItem.enableExInbound && _config.runningCoreType == ECoreType.sing_box)
{
var inbound = new Inbound4Sbox()
{
@@ -486,7 +486,7 @@ namespace ServiceLib.Handler.CoreConfig
};
singboxConfig.inbounds.Add(inbound);
inbound.listen_port = LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks);
inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
inbound.sniff = _config.inbound[0].sniffingEnabled;
inbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled;
inbound.domain_strategy = Utils.IsNullOrEmpty(_config.routingBasicItem.domainStrategy4Singbox) ? null : _config.routingBasicItem.domainStrategy4Singbox;
@@ -600,7 +600,7 @@ namespace ServiceLib.Handler.CoreConfig
}
case EConfigType.Shadowsocks:
{
outbound.method = LazyConfig.Instance.GetShadowsocksSecurities(node).Contains(node.security) ? node.security : Global.None;
outbound.method = AppHandler.Instance.GetShadowsocksSecurities(node).Contains(node.security) ? node.security : Global.None;
outbound.password = node.id;
GenOutboundMux(node, outbound);
@@ -854,7 +854,7 @@ namespace ServiceLib.Handler.CoreConfig
}
try
{
var subItem = LazyConfig.Instance.GetSubItem(node.subid);
var subItem = AppHandler.Instance.GetSubItem(node.subid);
if (subItem is null)
{
return 0;
@@ -865,7 +865,7 @@ namespace ServiceLib.Handler.CoreConfig
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
//Previous proxy
var prevNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.prevProfile);
var prevNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.prevProfile);
if (prevNode is not null
&& prevNode.configType != EConfigType.Custom)
{
@@ -878,7 +878,7 @@ namespace ServiceLib.Handler.CoreConfig
}
//Next proxy
var nextNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.nextProfile);
var nextNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.nextProfile);
if (nextNode is not null
&& nextNode.configType != EConfigType.Custom)
{
@@ -992,13 +992,13 @@ namespace ServiceLib.Handler.CoreConfig
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
foreach (var it in coreInfo)
{
if (it.coreType == ECoreType.v2rayN)
if (it.CoreType == ECoreType.v2rayN)
{
continue;
}
foreach (var it2 in it.coreExes)
foreach (var it2 in it.CoreExes)
{
if (!lstDnsExe.Contains(it2) && it.coreType != ECoreType.sing_box)
if (!lstDnsExe.Contains(it2) && it.CoreType != ECoreType.sing_box)
{
lstDnsExe.Add($"{it2}.exe");
}
@@ -1173,7 +1173,7 @@ namespace ServiceLib.Handler.CoreConfig
{
try
{
var item = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box);
var item = AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
var strDNS = string.Empty;
if (_config.tunModeItem.enableTun)
{
@@ -1260,7 +1260,7 @@ namespace ServiceLib.Handler.CoreConfig
singboxConfig.experimental ??= new Experimental4Sbox();
singboxConfig.experimental.clash_api = new Clash_Api4Sbox()
{
external_controller = $"{Global.Loopback}:{LazyConfig.Instance.StatePort2}",
external_controller = $"{Global.Loopback}:{AppHandler.Instance.StatePort2}",
};
}

View File

@@ -2,13 +2,13 @@
using System.Net.NetworkInformation;
using System.Text.Json.Nodes;
namespace ServiceLib.Handler.CoreConfig
namespace ServiceLib.Services.CoreConfig
{
public class CoreConfigV2ray
public class CoreConfigV2rayService
{
private Config _config;
public CoreConfigV2ray(Config config)
public CoreConfigV2rayService(Config config)
{
_config = config;
}
@@ -118,7 +118,7 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
var item = AppHandler.Instance.GetProfileItem(it.indexId);
if (item is null)
{
continue;
@@ -236,7 +236,7 @@ namespace ServiceLib.Handler.CoreConfig
v2rayConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
v2rayConfig.outbounds.RemoveAt(0);
int httpPort = LazyConfig.Instance.GetLocalPort(EInboundProtocol.speedtest);
int httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds)
{
@@ -248,7 +248,7 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
var item = AppHandler.Instance.GetProfileItem(it.indexId);
if (it.configType is EConfigType.VMess or EConfigType.VLESS)
{
if (item is null || Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id))
@@ -308,7 +308,7 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
if ((it.configType is EConfigType.VLESS or EConfigType.Trojan)
if (it.configType is EConfigType.VLESS or EConfigType.Trojan
&& item.streamSecurity == Global.StreamSecurityReality
&& item.publicKey.IsNullOrEmpty())
{
@@ -637,7 +637,7 @@ namespace ServiceLib.Handler.CoreConfig
serversItem.address = node.address;
serversItem.port = node.port;
serversItem.password = node.id;
serversItem.method = LazyConfig.Instance.GetShadowsocksSecurities(node).Contains(node.security) ? node.security : "none";
serversItem.method = AppHandler.Instance.GetShadowsocksSecurities(node).Contains(node.security) ? node.security : "none";
serversItem.ota = false;
serversItem.level = 1;
@@ -1029,7 +1029,7 @@ namespace ServiceLib.Handler.CoreConfig
{
try
{
var item = LazyConfig.Instance.GetDNSItem(ECoreType.Xray);
var item = AppHandler.Instance.GetDNSItem(ECoreType.Xray);
var normalDNS = item?.normalDNS;
var domainStrategy4Freedom = item?.domainStrategy4Freedom;
if (Utils.IsNullOrEmpty(normalDNS))
@@ -1136,7 +1136,7 @@ namespace ServiceLib.Handler.CoreConfig
Inboundsettings4Ray apiInboundSettings = new();
apiInbound.tag = tag;
apiInbound.listen = Global.Loopback;
apiInbound.port = LazyConfig.Instance.StatePort;
apiInbound.port = AppHandler.Instance.StatePort;
apiInbound.protocol = Global.InboundAPIProtocol;
apiInboundSettings.address = Global.Loopback;
apiInbound.settings = apiInboundSettings;
@@ -1193,7 +1193,7 @@ namespace ServiceLib.Handler.CoreConfig
}
try
{
var subItem = LazyConfig.Instance.GetSubItem(node.subid);
var subItem = AppHandler.Instance.GetSubItem(node.subid);
if (subItem is null)
{
return 0;
@@ -1204,7 +1204,7 @@ namespace ServiceLib.Handler.CoreConfig
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
//Previous proxy
var prevNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.prevProfile);
var prevNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.prevProfile);
if (prevNode is not null
&& prevNode.configType != EConfigType.Custom
&& prevNode.configType != EConfigType.Hysteria2
@@ -1223,7 +1223,7 @@ namespace ServiceLib.Handler.CoreConfig
}
//Next proxy
var nextNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.nextProfile);
var nextNode = AppHandler.Instance.GetProfileItemViaRemarks(subItem.nextProfile);
if (nextNode is not null
&& nextNode.configType != EConfigType.Custom
&& nextNode.configType != EConfigType.Hysteria2

View File

@@ -3,12 +3,12 @@ using System.Net;
using System.Net.Http.Headers;
using System.Net.Sockets;
namespace ServiceLib.Handler
namespace ServiceLib.Services
{
/// <summary>
///Download
/// </summary>
public class DownloadHandler
public class DownloadService
{
public event EventHandler<ResultEventArgs>? UpdateCompleted;
@@ -30,7 +30,7 @@ namespace ServiceLib.Handler
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.Config.guiItem.enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var progress = new Progress<string>();
progress.ProgressChanged += (sender, value) =>
@@ -62,7 +62,7 @@ namespace ServiceLib.Handler
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.Config.guiItem.enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, $"{ResUI.Downloading} {url}"));
var progress = new Progress<double>();
@@ -92,7 +92,7 @@ namespace ServiceLib.Handler
public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
{
Utils.SetSecurityProtocol(LazyConfig.Instance.Config.guiItem.enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var webRequestHandler = new SocketsHttpHandler
{
AllowAutoRedirect = false,
@@ -181,7 +181,7 @@ namespace ServiceLib.Handler
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.Config.guiItem.enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var webProxy = GetWebProxy(blProxy);
var client = new HttpClient(new SocketsHttpHandler()
{
@@ -226,7 +226,7 @@ namespace ServiceLib.Handler
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.Config.guiItem.enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var webProxy = GetWebProxy(blProxy);
@@ -260,7 +260,7 @@ namespace ServiceLib.Handler
try
{
var config = LazyConfig.Instance.Config;
var config = AppHandler.Instance.Config;
int responseTime = await GetRealPingTime(config.speedTestItem.speedPingTestUrl, webProxy, 10);
return responseTime;
}
@@ -314,7 +314,7 @@ namespace ServiceLib.Handler
{
return null;
}
var httpPort = LazyConfig.Instance.GetLocalPort(EInboundProtocol.http);
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
if (!SocketCheck(Global.Loopback, httpPort))
{
return null;

View File

@@ -2,21 +2,20 @@
using System.Net;
using System.Net.Sockets;
namespace ServiceLib.Handler
namespace ServiceLib.Services
{
public class SpeedtestHandler
public class SpeedtestService
{
private Config? _config;
private CoreHandler _coreHandler;
private List<ServerTestItem> _selecteds;
private ESpeedActionType _actionType;
private Action<SpeedTestResult> _updateFunc;
private bool _exitLoop = false;
public SpeedtestHandler(Config config, CoreHandler coreHandler, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> update)
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> update)
{
_config = config;
_coreHandler = coreHandler;
_actionType = actionType;
_updateFunc = update;
@@ -137,14 +136,14 @@ namespace ServiceLib.Handler
{
string msg = string.Empty;
pid = _coreHandler.LoadCoreConfigSpeedtest(_selecteds);
pid = CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return Task.CompletedTask;
}
DownloadHandler downloadHandle = new DownloadHandler();
DownloadService downloadHandle = new DownloadService();
List<Task> tasks = new();
foreach (var it in _selecteds)
@@ -185,7 +184,7 @@ namespace ServiceLib.Handler
{
if (pid > 0)
{
_coreHandler.CoreStopPid(pid);
CoreHandler.Instance.CoreStopPid(pid);
}
ProfileExHandler.Instance.SaveTo();
}
@@ -201,7 +200,7 @@ namespace ServiceLib.Handler
// _selecteds = _selecteds.OrderBy(t => t.delay).ToList();
//}
pid = _coreHandler.LoadCoreConfigSpeedtest(_selecteds);
pid = CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
@@ -211,7 +210,7 @@ namespace ServiceLib.Handler
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandler downloadHandle = new();
DownloadService downloadHandle = new();
foreach (var it in _selecteds)
{
@@ -236,12 +235,12 @@ namespace ServiceLib.Handler
ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
var item = AppHandler.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
WebProxy webProxy = new(Global.Loopback, it.port);
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) =>
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{
decimal.TryParse(msg, out decimal dec);
if (dec > 0)
@@ -254,7 +253,7 @@ namespace ServiceLib.Handler
if (pid > 0)
{
_coreHandler.CoreStopPid(pid);
CoreHandler.Instance.CoreStopPid(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
ProfileExHandler.Instance.SaveTo();
@@ -263,7 +262,7 @@ namespace ServiceLib.Handler
private async Task RunSpeedTestMulti()
{
int pid = -1;
pid = _coreHandler.LoadCoreConfigSpeedtest(_selecteds);
pid = CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
@@ -273,7 +272,7 @@ namespace ServiceLib.Handler
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandler downloadHandle = new();
DownloadService downloadHandle = new();
foreach (var it in _selecteds)
{
@@ -299,11 +298,11 @@ namespace ServiceLib.Handler
ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
var item = AppHandler.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
WebProxy webProxy = new(Global.Loopback, it.port);
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) =>
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{
decimal.TryParse(msg, out decimal dec);
if (dec > 0)
@@ -319,7 +318,7 @@ namespace ServiceLib.Handler
if (pid > 0)
{
_coreHandler.CoreStopPid(pid);
CoreHandler.Instance.CoreStopPid(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
ProfileExHandler.Instance.SaveTo();
@@ -334,7 +333,7 @@ namespace ServiceLib.Handler
await RunSpeedTestMulti();
}
private async Task<string> GetRealPingTime(DownloadHandler downloadHandle, IWebProxy webProxy)
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
{
int responseTime = await downloadHandle.GetRealPingTime(_config.speedTestItem.speedPingTestUrl, webProxy, 10);
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
@@ -349,7 +348,7 @@ namespace ServiceLib.Handler
{
if (!IPAddress.TryParse(url, out IPAddress? ipAddress))
{
IPHostEntry ipHostInfo = System.Net.Dns.GetHostEntry(url);
IPHostEntry ipHostInfo = Dns.GetHostEntry(url);
ipAddress = ipHostInfo.AddressList[0];
}

View File

@@ -1,9 +1,9 @@
using System.Net.WebSockets;
using System.Text;
namespace ServiceLib.Handler.Statistics
namespace ServiceLib.Services.Statistics
{
public class StatisticsSingbox
public class StatisticsSingboxService
{
private Config _config;
private bool _exitFlag;
@@ -11,7 +11,7 @@ namespace ServiceLib.Handler.Statistics
private string url = string.Empty;
private Action<ServerSpeedItem> _updateFunc;
public StatisticsSingbox(Config config, Action<ServerSpeedItem> update)
public StatisticsSingboxService(Config config, Action<ServerSpeedItem> update)
{
_config = config;
_updateFunc = update;
@@ -26,7 +26,7 @@ namespace ServiceLib.Handler.Statistics
try
{
url = $"ws://{Global.Loopback}:{LazyConfig.Instance.StatePort2}/traffic";
url = $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic";
if (webSocket == null)
{
@@ -63,7 +63,7 @@ namespace ServiceLib.Handler.Statistics
await Task.Delay(1000);
try
{
if (!(_config.IsRunningCore(ECoreType.sing_box)))
if (!_config.IsRunningCore(ECoreType.sing_box))
{
continue;
}

View File

@@ -2,9 +2,9 @@
using Grpc.Net.Client;
using ProtosLib.Statistics;
namespace ServiceLib.Handler.Statistics
namespace ServiceLib.Services.Statistics
{
public class StatisticsV2ray
public class StatisticsV2rayService
{
private Models.Config _config;
private GrpcChannel? _channel;
@@ -12,7 +12,7 @@ namespace ServiceLib.Handler.Statistics
private bool _exitFlag;
private Action<ServerSpeedItem> _updateFunc;
public StatisticsV2ray(Models.Config config, Action<ServerSpeedItem> update)
public StatisticsV2rayService(Models.Config config, Action<ServerSpeedItem> update)
{
_config = config;
_updateFunc = update;
@@ -29,7 +29,7 @@ namespace ServiceLib.Handler.Statistics
{
try
{
_channel = GrpcChannel.ForAddress($"{Global.HttpProtocol}{Global.Loopback}:{LazyConfig.Instance.StatePort}");
_channel = GrpcChannel.ForAddress($"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}");
_client = new StatsService.StatsServiceClient(_channel);
}
catch (Exception ex)
@@ -51,7 +51,7 @@ namespace ServiceLib.Handler.Statistics
await Task.Delay(1000);
try
{
if (!(_config.IsRunningCore(ECoreType.Xray)))
if (!_config.IsRunningCore(ECoreType.Xray))
{
continue;
}

View File

@@ -3,9 +3,9 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
namespace ServiceLib.Handler
namespace ServiceLib.Services
{
public class UpdateHandler
public class UpdateService
{
private Action<bool, string> _updateFunc;
private Config _config;
@@ -32,7 +32,7 @@ namespace ServiceLib.Handler
var url = string.Empty;
var fileName = string.Empty;
DownloadHandler downloadHandle = new();
DownloadService downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
if (args.Success)
@@ -74,7 +74,7 @@ namespace ServiceLib.Handler
var url = string.Empty;
var fileName = string.Empty;
DownloadHandler downloadHandle = new();
DownloadService downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
if (args.Success)
@@ -110,7 +110,7 @@ namespace ServiceLib.Handler
url = args.Url;
var ext = Path.GetExtension(url);
fileName = Utils.GetTempPath(Utils.GetGUID()+ ext);
fileName = Utils.GetTempPath(Utils.GetGUID() + ext);
await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout);
}
else
@@ -128,7 +128,7 @@ namespace ServiceLib.Handler
_updateFunc = update;
_updateFunc(false, ResUI.MsgUpdateSubscriptionStart);
var subItem = LazyConfig.Instance.SubItems().OrderBy(t => t.sort).ToList();
var subItem = AppHandler.Instance.SubItems().OrderBy(t => t.sort).ToList();
if (subItem == null || subItem.Count <= 0)
{
@@ -144,7 +144,7 @@ namespace ServiceLib.Handler
string url = item.url.TrimEx();
string userAgent = item.userAgent.TrimEx();
string hashCode = $"{item.remarks}->";
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || (Utils.IsNotEmpty(subId) && item.id != subId))
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || Utils.IsNotEmpty(subId) && item.id != subId)
{
//_updateFunc(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
continue;
@@ -159,7 +159,7 @@ namespace ServiceLib.Handler
continue;
}
var downloadHandle = new DownloadHandler();
var downloadHandle = new DownloadService();
downloadHandle.Error += (sender2, args) =>
{
_updateFunc(false, $"{hashCode}{args.GetException().Message}");
@@ -264,18 +264,18 @@ namespace ServiceLib.Handler
public async Task RunAvailabilityCheck(Action<bool, string> update)
{
var time = await (new DownloadHandler()).RunAvailabilityCheck(null);
var time = await new DownloadService().RunAvailabilityCheck(null);
update(false, string.Format(ResUI.TestMeOutput, time));
}
#region private
private async Task<ResultEventArgs> CheckUpdateAsync(DownloadHandler downloadHandle, ECoreType type, bool preRelease)
private async Task<ResultEventArgs> CheckUpdateAsync(DownloadService downloadHandle, ECoreType type, bool preRelease)
{
try
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
var url = coreInfo?.coreReleaseApiUrl;
var url = coreInfo?.ReleaseApiUrl;
var result = await downloadHandle.TryDownloadString(url, true, Global.AppName);
if (Utils.IsNotEmpty(result))
@@ -304,10 +304,10 @@ namespace ServiceLib.Handler
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
string filePath = string.Empty;
foreach (string name in coreInfo.coreExes)
foreach (string name in coreInfo.CoreExes)
{
string vName = Utils.GetExeName(name);
vName = Utils.GetBinPath(vName, coreInfo.coreType.ToString());
vName = Utils.GetBinPath(vName, coreInfo.CoreType.ToString());
if (File.Exists(vName))
{
filePath = vName;
@@ -324,7 +324,7 @@ namespace ServiceLib.Handler
using Process p = new();
p.StartInfo.FileName = filePath;
p.StartInfo.Arguments = coreInfo.versionArg;
p.StartInfo.Arguments = coreInfo.VersionArg;
p.StartInfo.WorkingDirectory = Utils.GetConfigPath();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
@@ -339,7 +339,7 @@ namespace ServiceLib.Handler
case ECoreType.v2fly:
case ECoreType.Xray:
case ECoreType.v2fly_v5:
version = Regex.Match(echo, $"{coreInfo.match} ([0-9.]+) \\(").Groups[1].Value;
version = Regex.Match(echo, $"{coreInfo.Match} ([0-9.]+) \\(").Groups[1].Value;
break;
case ECoreType.mihomo:
@@ -429,19 +429,19 @@ namespace ServiceLib.Handler
if (Utils.IsWindows())
{
//Check for standalone windows .Net version
if (coreInfo?.coreType == ECoreType.v2rayN
if (coreInfo?.CoreType == ECoreType.v2rayN
&& File.Exists(Path.Combine(Utils.StartupPath(), "wpfgfx_cor3.dll"))
&& File.Exists(Path.Combine(Utils.StartupPath(), "D3DCompiler_47_cor3.dll"))
)
{
return coreInfo?.coreDownloadUrl64.Replace("v2rayN.zip", "zz_v2rayN-SelfContained.zip");
return coreInfo?.DownloadUrlWin64?.Replace("v2rayN.zip", "zz_v2rayN-SelfContained.zip");
}
return RuntimeInformation.ProcessArchitecture switch
{
Architecture.Arm64 => coreInfo?.coreDownloadUrlArm64,
Architecture.X86 => coreInfo?.coreDownloadUrl32,
Architecture.X64 => coreInfo?.coreDownloadUrl64,
Architecture.Arm64 => coreInfo?.DownloadUrlWinArm64,
Architecture.X86 => coreInfo?.DownloadUrlWin32,
Architecture.X64 => coreInfo?.DownloadUrlWin64,
_ => null,
};
}
@@ -449,9 +449,8 @@ namespace ServiceLib.Handler
{
return RuntimeInformation.ProcessArchitecture switch
{
Architecture.Arm64 => coreInfo?.coreDownloadUrlLinuxArm64,
Architecture.X86 => coreInfo?.coreDownloadUrlLinux32,
Architecture.X64 => coreInfo?.coreDownloadUrlLinux64,
Architecture.Arm64 => coreInfo?.DownloadUrlLinuxArm64,
Architecture.X64 => coreInfo?.DownloadUrlLinux64,
_ => null,
};
}
@@ -465,7 +464,7 @@ namespace ServiceLib.Handler
var url = string.Format(Global.GeoUrl, geoName);
var fileName = Utils.GetTempPath(Utils.GetGUID());
DownloadHandler downloadHandle = new();
DownloadService downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
if (args.Success)

View File

@@ -1,6 +1,5 @@
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
using System.Reactive;
namespace ServiceLib.ViewModels
@@ -20,8 +19,7 @@ namespace ServiceLib.ViewModels
public AddServer2ViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)
{
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.Config;
_config = AppHandler.Instance.Config;
_updateView = updateView;
if (profileItem.indexId.IsNullOrEmpty())
@@ -55,25 +53,25 @@ namespace ServiceLib.ViewModels
string remarks = SelectedSource.remarks;
if (Utils.IsNullOrEmpty(remarks))
{
_noticeHandler?.Enqueue(ResUI.PleaseFillRemarks);
NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks);
return;
}
if (Utils.IsNullOrEmpty(SelectedSource.address))
{
_noticeHandler?.Enqueue(ResUI.FillServerAddressCustom);
NoticeHandler.Instance.Enqueue(ResUI.FillServerAddressCustom);
return;
}
SelectedSource.coreType = CoreType.IsNullOrEmpty() ? null : (ECoreType)Enum.Parse(typeof(ECoreType), CoreType);
if (ConfigHandler.EditCustomServer(_config, SelectedSource) == 0)
{
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
await _updateView?.Invoke(EViewAction.CloseWindow, null);
}
else
{
_noticeHandler?.Enqueue(ResUI.OperationFailed);
NoticeHandler.Instance.Enqueue(ResUI.OperationFailed);
}
}
@@ -84,12 +82,12 @@ namespace ServiceLib.ViewModels
return;
}
var item = LazyConfig.Instance.GetProfileItem(SelectedSource.indexId);
var item = AppHandler.Instance.GetProfileItem(SelectedSource.indexId);
item ??= SelectedSource;
item.address = fileName;
if (ConfigHandler.AddCustomServer(_config, item, false) == 0)
{
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedCustomServer);
NoticeHandler.Instance.Enqueue(ResUI.SuccessfullyImportedCustomServer);
if (Utils.IsNotEmpty(item.indexId))
{
SelectedSource = JsonUtils.DeepCopy(item);
@@ -98,7 +96,7 @@ namespace ServiceLib.ViewModels
}
else
{
_noticeHandler?.Enqueue(ResUI.FailedImportedCustomServer);
NoticeHandler.Instance.Enqueue(ResUI.FailedImportedCustomServer);
}
}
@@ -107,7 +105,7 @@ namespace ServiceLib.ViewModels
var address = SelectedSource.address;
if (Utils.IsNullOrEmpty(address))
{
_noticeHandler?.Enqueue(ResUI.FillServerAddressCustom);
NoticeHandler.Instance.Enqueue(ResUI.FillServerAddressCustom);
return;
}
@@ -118,7 +116,7 @@ namespace ServiceLib.ViewModels
}
else
{
_noticeHandler?.Enqueue(ResUI.FailedReadConfiguration);
NoticeHandler.Instance.Enqueue(ResUI.FailedReadConfiguration);
}
}
}

View File

@@ -1,6 +1,5 @@
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
using System.Reactive;
namespace ServiceLib.ViewModels
@@ -17,8 +16,8 @@ namespace ServiceLib.ViewModels
public AddServerViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)
{
_config = LazyConfig.Instance.Config;
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = AppHandler.Instance.Config;
_updateView = updateView;
if (profileItem.indexId.IsNullOrEmpty())
@@ -45,32 +44,32 @@ namespace ServiceLib.ViewModels
{
if (Utils.IsNullOrEmpty(SelectedSource.remarks))
{
_noticeHandler?.Enqueue(ResUI.PleaseFillRemarks);
NoticeHandler.Instance.Enqueue(ResUI.PleaseFillRemarks);
return;
}
if (Utils.IsNullOrEmpty(SelectedSource.address))
{
_noticeHandler?.Enqueue(ResUI.FillServerAddress);
NoticeHandler.Instance.Enqueue(ResUI.FillServerAddress);
return;
}
var port = SelectedSource.port.ToString();
if (Utils.IsNullOrEmpty(port) || !Utils.IsNumeric(port)
|| SelectedSource.port <= 0 || SelectedSource.port >= Global.MaxPort)
{
_noticeHandler?.Enqueue(ResUI.FillCorrectServerPort);
NoticeHandler.Instance.Enqueue(ResUI.FillCorrectServerPort);
return;
}
if (SelectedSource.configType == EConfigType.Shadowsocks)
{
if (Utils.IsNullOrEmpty(SelectedSource.id))
{
_noticeHandler?.Enqueue(ResUI.FillPassword);
NoticeHandler.Instance.Enqueue(ResUI.FillPassword);
return;
}
if (Utils.IsNullOrEmpty(SelectedSource.security))
{
_noticeHandler?.Enqueue(ResUI.PleaseSelectEncryption);
NoticeHandler.Instance.Enqueue(ResUI.PleaseSelectEncryption);
return;
}
}
@@ -79,7 +78,7 @@ namespace ServiceLib.ViewModels
{
if (Utils.IsNullOrEmpty(SelectedSource.id))
{
_noticeHandler?.Enqueue(ResUI.FillUUID);
NoticeHandler.Instance.Enqueue(ResUI.FillUUID);
return;
}
}
@@ -87,12 +86,12 @@ namespace ServiceLib.ViewModels
if (ConfigHandler.AddServer(_config, SelectedSource) == 0)
{
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
await _updateView?.Invoke(EViewAction.CloseWindow, null);
}
else
{
_noticeHandler?.Enqueue(ResUI.OperationFailed);
NoticeHandler.Instance.Enqueue(ResUI.OperationFailed);
}
}
}

View File

@@ -22,9 +22,8 @@ namespace ServiceLib.ViewModels
public BackupAndRestoreViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
{
_config = LazyConfig.Instance.Config;
_config = AppHandler.Instance.Config;
_updateView = updateView;
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
WebDavCheckCmd = ReactiveCommand.CreateFromTask(async () =>
{

View File

@@ -22,9 +22,8 @@ namespace ServiceLib.ViewModels
public CheckUpdateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
{
_config = LazyConfig.Instance.Config;
_config = AppHandler.Instance.Config;
_updateView = updateView;
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
RefreshSubItems();
@@ -51,61 +50,61 @@ namespace ServiceLib.ViewModels
_checkUpdateItem.Add(new CheckUpdateItem()
{
isSelected = false,
coreType = _v2rayN,
remarks = ResUI.menuCheckUpdate,
IsSelected = false,
CoreType = _v2rayN,
Remarks = ResUI.menuCheckUpdate,
});
_checkUpdateItem.Add(new CheckUpdateItem()
{
isSelected = true,
coreType = ECoreType.Xray.ToString(),
remarks = ResUI.menuCheckUpdate,
IsSelected = true,
CoreType = ECoreType.Xray.ToString(),
Remarks = ResUI.menuCheckUpdate,
});
_checkUpdateItem.Add(new CheckUpdateItem()
{
isSelected = true,
coreType = ECoreType.mihomo.ToString(),
remarks = ResUI.menuCheckUpdate,
IsSelected = true,
CoreType = ECoreType.mihomo.ToString(),
Remarks = ResUI.menuCheckUpdate,
});
if (Utils.IsWindows())
{
_checkUpdateItem.Add(new CheckUpdateItem()
{
isSelected = true,
coreType = ECoreType.sing_box.ToString(),
remarks = ResUI.menuCheckUpdate,
IsSelected = true,
CoreType = ECoreType.sing_box.ToString(),
Remarks = ResUI.menuCheckUpdate,
});
}
_checkUpdateItem.Add(new CheckUpdateItem()
{
isSelected = true,
coreType = _geo,
remarks = ResUI.menuCheckUpdate,
IsSelected = true,
CoreType = _geo,
Remarks = ResUI.menuCheckUpdate,
});
}
private async Task CheckUpdate()
{
_lstUpdated.Clear();
_lstUpdated = _checkUpdateItem.Where(x => x.isSelected == true)
.Select(x => new CheckUpdateItem() { coreType = x.coreType }).ToList();
_lstUpdated = _checkUpdateItem.Where(x => x.IsSelected == true)
.Select(x => new CheckUpdateItem() { CoreType = x.CoreType }).ToList();
for (int k = _checkUpdateItem.Count - 1; k >= 0; k--)
{
var item = _checkUpdateItem[k];
if (item.isSelected == true)
if (item.IsSelected == true)
{
IsCheckUpdate = false;
UpdateView(item.coreType, "...");
if (item.coreType == _geo)
UpdateView(item.CoreType, "...");
if (item.CoreType == _geo)
{
await CheckUpdateGeo();
}
else if (item.coreType == _v2rayN)
else if (item.CoreType == _v2rayN)
{
await CheckUpdateN(EnableCheckPreReleaseUpdate);
}
else if (item.coreType == ECoreType.mihomo.ToString())
else if (item.CoreType == ECoreType.mihomo.ToString())
{
await CheckUpdateCore(item, false);
}
@@ -119,15 +118,15 @@ namespace ServiceLib.ViewModels
private void UpdatedPlusPlus(string coreType, string fileName)
{
var item = _lstUpdated.FirstOrDefault(x => x.coreType == coreType);
var item = _lstUpdated.FirstOrDefault(x => x.CoreType == coreType);
if (item == null)
{
return;
}
item.isFinished = true;
item.IsFinished = true;
if (!fileName.IsNullOrEmpty())
{
item.fileName = fileName;
item.FileName = fileName;
}
}
@@ -141,7 +140,7 @@ namespace ServiceLib.ViewModels
UpdatedPlusPlus(_geo, "");
}
}
await (new UpdateHandler()).UpdateGeoFileAll(_config, _updateUI)
await (new UpdateService()).UpdateGeoFileAll(_config, _updateUI)
.ContinueWith(t =>
{
UpdatedPlusPlus(_geo, "");
@@ -169,7 +168,7 @@ namespace ServiceLib.ViewModels
UpdatedPlusPlus(_v2rayN, msg);
}
}
await (new UpdateHandler()).CheckUpdateGuiN(_config, _updateUI, preRelease)
await (new UpdateService()).CheckUpdateGuiN(_config, _updateUI, preRelease)
.ContinueWith(t =>
{
UpdatedPlusPlus(_v2rayN, "");
@@ -180,31 +179,31 @@ namespace ServiceLib.ViewModels
{
void _updateUI(bool success, string msg)
{
UpdateView(item.coreType, msg);
UpdateView(item.CoreType, msg);
if (success)
{
UpdateView(item.coreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
UpdateView(item.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
UpdatedPlusPlus(item.coreType, msg);
UpdatedPlusPlus(item.CoreType, msg);
}
}
var type = (ECoreType)Enum.Parse(typeof(ECoreType), item.coreType);
await (new UpdateHandler()).CheckUpdateCore(type, _config, _updateUI, preRelease)
var type = (ECoreType)Enum.Parse(typeof(ECoreType), item.CoreType);
await (new UpdateService()).CheckUpdateCore(type, _config, _updateUI, preRelease)
.ContinueWith(t =>
{
UpdatedPlusPlus(item.coreType, "");
UpdatedPlusPlus(item.CoreType, "");
});
}
private async Task UpdateFinished()
{
if (_lstUpdated.Count > 0 && _lstUpdated.Count(x => x.isFinished == true) == _lstUpdated.Count)
if (_lstUpdated.Count > 0 && _lstUpdated.Count(x => x.IsFinished == true) == _lstUpdated.Count)
{
_updateView?.Invoke(EViewAction.DispatcherCheckUpdateFinished, false);
await Task.Delay(2000);
UpgradeCore();
if (_lstUpdated.Any(x => x.coreType == _v2rayN && x.isFinished == true))
if (_lstUpdated.Any(x => x.CoreType == _v2rayN && x.IsFinished == true))
{
await Task.Delay(1000);
UpgradeN();
@@ -231,7 +230,7 @@ namespace ServiceLib.ViewModels
{
try
{
var fileName = _lstUpdated.FirstOrDefault(x => x.coreType == _v2rayN)?.fileName;
var fileName = _lstUpdated.FirstOrDefault(x => x.CoreType == _v2rayN)?.FileName;
if (fileName.IsNullOrEmpty())
{
return;
@@ -248,17 +247,17 @@ namespace ServiceLib.ViewModels
{
foreach (var item in _lstUpdated)
{
if (item.fileName.IsNullOrEmpty())
if (item.FileName.IsNullOrEmpty())
{
continue;
}
var fileName = item.fileName;
var fileName = item.FileName;
if (!File.Exists(fileName))
{
continue;
}
string toPath = Utils.GetBinPath("", item.coreType);
string toPath = Utils.GetBinPath("", item.CoreType);
if (fileName.Contains(".tar.gz"))
{
@@ -266,14 +265,14 @@ namespace ServiceLib.ViewModels
}
else if (fileName.Contains(".gz"))
{
FileManager.UncompressedFile(fileName, toPath, item.coreType);
FileManager.UncompressedFile(fileName, toPath, item.CoreType);
}
else
{
FileManager.ZipExtractToFile(fileName, toPath, _config.guiItem.ignoreGeoUpdateCore ? "geo" : "");
}
UpdateView(item.coreType, ResUI.MsgUpdateV2rayCoreSuccessfully);
UpdateView(item.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfully);
if (File.Exists(fileName))
{
@@ -286,19 +285,19 @@ namespace ServiceLib.ViewModels
{
var item = new CheckUpdateItem()
{
coreType = coreType,
remarks = msg,
CoreType = coreType,
Remarks = msg,
};
_updateView?.Invoke(EViewAction.DispatcherCheckUpdate, item);
}
public void UpdateViewResult(CheckUpdateItem item)
{
var found = _checkUpdateItem.FirstOrDefault(t => t.coreType == item.coreType);
var found = _checkUpdateItem.FirstOrDefault(t => t.CoreType == item.CoreType);
if (found != null)
{
var itemCopy = JsonUtils.DeepCopy(found);
itemCopy.remarks = item.remarks;
itemCopy.Remarks = item.Remarks;
_checkUpdateItem.Replace(found, itemCopy);
}
}

View File

@@ -30,7 +30,7 @@ namespace ServiceLib.ViewModels
public ClashConnectionsViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
{
_config = LazyConfig.Instance.Config;
_config = AppHandler.Instance.Config;
_updateView = updateView;
SortingSelected = _config.clashUIItem.connectionsSorting;
AutoRefresh = _config.clashUIItem.connectionsAutoRefresh;

View File

@@ -2,7 +2,6 @@ using DynamicData;
using DynamicData.Binding;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
using System.Reactive;
using System.Reactive.Linq;
using static ServiceLib.Models.ClashProviders;
@@ -44,8 +43,7 @@ namespace ServiceLib.ViewModels
public ClashProxiesViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
{
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.Config;
_config = AppHandler.Instance.Config;
_updateView = updateView;
SelectedGroup = new();
@@ -135,7 +133,7 @@ namespace ServiceLib.ViewModels
private void UpdateHandler(bool notify, string msg)
{
_noticeHandler?.SendMessageEx(msg);
NoticeHandler.Instance.SendMessageEx(msg);
}
public void ProxiesReload()
@@ -363,7 +361,7 @@ namespace ServiceLib.ViewModels
var selectedProxy = TryGetProxy(name);
if (selectedProxy == null || selectedProxy.type != "Selector")
{
_noticeHandler?.Enqueue(ResUI.OperationFailed);
NoticeHandler.Instance.Enqueue(ResUI.OperationFailed);
return;
}
@@ -379,7 +377,7 @@ namespace ServiceLib.ViewModels
SelectedGroup = group2;
}
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
}
private void ProxiesDelayTest(bool blAll)

Some files were not shown because too many files have changed in this diff Show More