This commit is contained in:
InkerBot
2026-03-05 13:33:05 +08:00
commit 648aa93360
22 changed files with 1427 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/.idea
+41
View File
@@ -0,0 +1,41 @@
# O.M.V. 帝江号
## 开发规范
**补丁规范**
所有的更改必须被 `// OMV start``// OMV end` 包裹(必须单独起一行),如果单行更改则只需要在行末添加 `// OMV` 即可,新建文件的只需要在文件开头添加 `// OMV` 即可。
除非非常简单的更改,否则务必说明更改的内容 `// OMV start: register sql protocol`
所有补丁必须遵循最小化修改的原则,在完成需求的情况下,务必保证对项目的修改最小,改动的数量也需要最小。
## 开发指南
**初始化**
```sh
bin/update
```
克隆或拉取最新的上游 sing-box 到 `works/sing-box/`
**生成工作目录**
```sh
bin/apply
```
将上游代码同步到 `works/core/`,并应用 `works/patch/` 中的所有补丁。
**修改代码**
直接编辑 `works/core/` 中的文件。
**保存修改为补丁**
```sh
bin/generate
```
对比 `works/core/``works/sing-box/`,将差异写入 `works/patch/`(按原目录结构,每个文件对应一个 `.patch`)。之后提交 `works/patch/` 即可。
Executable
+68
View File
@@ -0,0 +1,68 @@
#!/bin/sh
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(dirname "$SCRIPT_DIR")"
SING_BOX="$ROOT/works/sing-box"
PATCH_DIR="$ROOT/works/patch"
OUTPUT="$ROOT/works/core"
if [ ! -d "$SING_BOX/.git" ]; then
echo "Error: works/sing-box not found. Run update first." >&2
exit 1
fi
echo "Initializing works/core/..."
rm -rf "$OUTPUT"
mkdir -p "$OUTPUT"
git init "$OUTPUT"
echo "Syncing sing-box files to works/core/..."
rsync -a --exclude='.git/' "$SING_BOX/" "$OUTPUT/"
VERSION="$(git -C "$SING_BOX" describe --tags --always 2>/dev/null || git -C "$SING_BOX" rev-parse --short HEAD)"
git -C "$OUTPUT" add -A
git -C "$OUTPUT" commit -m "upstream: $VERSION"
echo "Applying patches..."
applied=0
failed=0
failed_list=""
if [ -d "$PATCH_DIR" ]; then
patch_list="$(mktemp)"
trap 'rm -f "$patch_list"' EXIT
find "$PATCH_DIR" -name "*.patch" | sort > "$patch_list"
while IFS= read -r patch_file; do
rel="${patch_file#$PATCH_DIR/}"
rel="${rel%.patch}"
dst="$OUTPUT/$rel"
mkdir -p "$(dirname "$dst")"
if patch --merge --no-backup-if-mismatch --force "$dst" < "$patch_file"; then
applied=$((applied + 1))
else
echo " FAILED: $rel" >&2
failed=$((failed + 1))
failed_list="${failed_list} ${rel}
"
fi
done < "$patch_list"
fi
git -C "$OUTPUT" add -A
git -C "$OUTPUT" commit -m "patches applied" --allow-empty
total=$((applied + failed))
echo ""
echo "Result: $applied/$total patches applied."
if [ "$failed" -gt 0 ]; then
echo ""
echo "Failed patches (merge conflicts written to files):"
printf "%s" "$failed_list"
echo ""
echo "Resolve conflicts in works/core/, then run 'bin/generate' to update patches."
exit 1
fi
echo "Done."
+74
View File
@@ -0,0 +1,74 @@
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Root = Split-Path -Parent $ScriptDir
$SingBox = Join-Path $Root 'works/sing-box'
$PatchDir = Join-Path $Root 'works/patch'
$Output = Join-Path $Root 'works/core'
if (-not (Test-Path (Join-Path $SingBox '.git'))) {
Write-Error 'works/sing-box not found. Run update first.'
exit 1
}
Write-Host 'Initializing works/core/...'
if (Test-Path $Output) { Remove-Item -Recurse -Force $Output }
New-Item -ItemType Directory -Path $Output -Force | Out-Null
git init $Output
Write-Host 'Syncing sing-box files to works/core/...'
Get-ChildItem -Path $SingBox -Recurse -File | Where-Object {
$_.FullName -notmatch [regex]::Escape((Join-Path $SingBox '.git'))
} | ForEach-Object {
$rel = $_.FullName.Substring($SingBox.Length + 1)
$dst = Join-Path $Output $rel
$dstDir = Split-Path -Parent $dst
if (-not (Test-Path $dstDir)) { New-Item -ItemType Directory -Path $dstDir -Force | Out-Null }
Copy-Item -Path $_.FullName -Destination $dst -Force
}
$version = git -C $SingBox describe --tags --always 2>$null
if (-not $version) { $version = git -C $SingBox rev-parse --short HEAD }
git -C $Output add -A
git -C $Output commit -m "upstream: $version"
Write-Host 'Applying patches...'
$applied = 0
$failed = 0
$failedList = @()
if (Test-Path $PatchDir) {
Get-ChildItem -Path $PatchDir -Recurse -Filter '*.patch' | Sort-Object FullName | ForEach-Object {
$rel = $_.FullName.Substring($PatchDir.Length + 1) -replace '\.patch$', ''
$dst = Join-Path $Output $rel
$dstDir = Split-Path -Parent $dst
if (-not (Test-Path $dstDir)) { New-Item -ItemType Directory -Path $dstDir -Force | Out-Null }
& patch --merge --no-backup-if-mismatch --force -i $_.FullName $dst 2>&1
if ($LASTEXITCODE -eq 0) {
$applied++
} else {
Write-Host " FAILED: $rel" -ForegroundColor Red
$failed++
$failedList += $rel
}
}
}
git -C $Output add -A
git -C $Output commit -m 'patches applied' --allow-empty
$total = $applied + $failed
Write-Host ""
Write-Host "Result: $applied/$total patches applied."
if ($failed -gt 0) {
Write-Host ""
Write-Host "Failed patches (merge conflicts written to files):" -ForegroundColor Red
foreach ($f in $failedList) {
Write-Host " $f" -ForegroundColor Red
}
Write-Host ""
Write-Host "Resolve conflicts in works/core/, then run 'bin/generate' to update patches."
exit 1
}
Write-Host 'Done.'
Executable
+80
View File
@@ -0,0 +1,80 @@
#!/bin/sh
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(dirname "$SCRIPT_DIR")"
SING_BOX="$ROOT/works/sing-box"
PATCH_DIR="$ROOT/works/patch"
CORE="$ROOT/works/core"
if [ ! -d "$SING_BOX/.git" ]; then
echo "Error: works/sing-box not found. Run update first." >&2
exit 1
fi
if [ ! -d "$CORE" ]; then
echo "Error: works/core not found. Run generate first." >&2
exit 1
fi
IGNORE_FILE="$ROOT/works/ignore"
is_ignored() {
[ -f "$IGNORE_FILE" ] || return 1
_rel="$1"
_name="${_rel##*/}"
while IFS= read -r _pattern || [ -n "$_pattern" ]; do
case "$_pattern" in
''|\#*) continue ;;
esac
case "$_pattern" in
*/*)
case "$_rel" in $_pattern) return 0 ;; esac
;;
*)
case "$_name" in $_pattern) return 0 ;; esac
;;
esac
done < "$IGNORE_FILE"
return 1
}
echo "Clearing existing patches..."
rm -rf "$PATCH_DIR"
mkdir -p "$PATCH_DIR"
echo "Generating patches for modified/new files..."
find "$CORE" -not -path "$CORE/.git/*" -type f | sort | while read -r dst_file; do
rel="${dst_file#$CORE/}"
if is_ignored "$rel"; then continue; fi
src_file="$SING_BOX/$rel"
patch_file="$PATCH_DIR/$rel.patch"
if [ -f "$src_file" ]; then
if ! diff -q "$src_file" "$dst_file" > /dev/null 2>&1; then
mkdir -p "$(dirname "$patch_file")"
diff -u "$src_file" "$dst_file" > "$patch_file" || true
echo " Modified: $rel"
fi
else
mkdir -p "$(dirname "$patch_file")"
diff -u /dev/null "$dst_file" > "$patch_file" || true
echo " New: $rel"
fi
done
echo "Generating patches for deleted files..."
find "$SING_BOX" -not -path "$SING_BOX/.git/*" -type f | sort | while read -r src_file; do
rel="${src_file#$SING_BOX/}"
if is_ignored "$rel"; then continue; fi
dst_file="$CORE/$rel"
patch_file="$PATCH_DIR/$rel.patch"
if [ ! -f "$dst_file" ]; then
mkdir -p "$(dirname "$patch_file")"
diff -u "$src_file" /dev/null > "$patch_file" || true
echo " Deleted: $rel"
fi
done
echo "Done."
+82
View File
@@ -0,0 +1,82 @@
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Root = Split-Path -Parent $ScriptDir
$SingBox = Join-Path $Root 'works/sing-box'
$PatchDir = Join-Path $Root 'works/patch'
$Core = Join-Path $Root 'works/core'
if (-not (Test-Path (Join-Path $SingBox '.git'))) {
Write-Error 'works/sing-box not found. Run update first.'
exit 1
}
if (-not (Test-Path $Core)) {
Write-Error 'works/core not found. Run generate first.'
exit 1
}
$IgnoreFile = Join-Path $Root 'works/ignore'
$IgnorePatterns = @()
if (Test-Path $IgnoreFile) {
$IgnorePatterns = Get-Content $IgnoreFile | Where-Object { $_ -ne '' -and $_ -notmatch '^\s*#' }
}
function Test-Ignored {
param([string]$RelPath)
foreach ($pattern in $IgnorePatterns) {
if ($pattern -match '/') {
if ($RelPath -like $pattern) { return $true }
} else {
if ((Split-Path -Leaf $RelPath) -like $pattern) { return $true }
}
}
return $false
}
Write-Host 'Clearing existing patches...'
if (Test-Path $PatchDir) { Remove-Item -Recurse -Force $PatchDir }
New-Item -ItemType Directory -Path $PatchDir -Force | Out-Null
Write-Host 'Generating patches for modified/new files...'
Get-ChildItem -Path $Core -Recurse -File | Where-Object {
$_.FullName -notmatch [regex]::Escape((Join-Path $Core '.git'))
} | Sort-Object FullName | ForEach-Object {
$rel = $_.FullName.Substring($Core.Length + 1) -replace '\\', '/'
if (Test-Ignored $rel) { return }
$srcFile = Join-Path $SingBox $rel
$patchFile = Join-Path $PatchDir "$rel.patch"
$patchFileDir = Split-Path -Parent $patchFile
if (-not (Test-Path $patchFileDir)) { New-Item -ItemType Directory -Path $patchFileDir -Force | Out-Null }
if (Test-Path $srcFile) {
$srcHash = (Get-FileHash $srcFile -Algorithm MD5).Hash
$dstHash = (Get-FileHash $_.FullName -Algorithm MD5).Hash
if ($srcHash -ne $dstHash) {
diff -u $srcFile $_.FullName | Out-File -FilePath $patchFile -Encoding utf8
Write-Host " Modified: $rel"
}
} else {
diff -u /dev/null $_.FullName | Out-File -FilePath $patchFile -Encoding utf8
Write-Host " New: $rel"
}
}
Write-Host 'Generating patches for deleted files...'
Get-ChildItem -Path $SingBox -Recurse -File | Where-Object {
$_.FullName -notmatch [regex]::Escape((Join-Path $SingBox '.git'))
} | Sort-Object FullName | ForEach-Object {
$rel = $_.FullName.Substring($SingBox.Length + 1) -replace '\\', '/'
if (Test-Ignored $rel) { return }
$dstFile = Join-Path $Core $rel
$patchFile = Join-Path $PatchDir "$rel.patch"
if (-not (Test-Path $dstFile)) {
$patchFileDir = Split-Path -Parent $patchFile
if (-not (Test-Path $patchFileDir)) { New-Item -ItemType Directory -Path $patchFileDir -Force | Out-Null }
diff -u $_.FullName /dev/null | Out-File -FilePath $patchFile -Encoding utf8
Write-Host " Deleted: $rel"
}
}
Write-Host 'Done.'
Executable
+33
View File
@@ -0,0 +1,33 @@
#!/bin/sh
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(dirname "$SCRIPT_DIR")"
SING_BOX="$ROOT/works/sing-box"
# defaults
REPO_URL="git@git.inker.bot:arknights/sing-box.git"
UPSTREAM_BRANCH="main"
CONFIG="$ROOT/works/config"
if [ -f "$CONFIG" ]; then
. "$CONFIG"
fi
if [ -d "$SING_BOX/.git" ]; then
echo "Updating sing-box..."
git -C "$SING_BOX" fetch --all
if [ -n "$UPSTREAM_BRANCH" ]; then
git -C "$SING_BOX" checkout "$UPSTREAM_BRANCH"
fi
git -C "$SING_BOX" pull
else
echo "Cloning sing-box..."
if [ -n "$UPSTREAM_BRANCH" ]; then
git clone -b "$UPSTREAM_BRANCH" "$REPO_URL" "$SING_BOX"
else
git clone "$REPO_URL" "$SING_BOX"
fi
fi
echo "Done. Version: $(git -C "$SING_BOX" describe --tags --always 2>/dev/null || git -C "$SING_BOX" rev-parse --short HEAD)"
+39
View File
@@ -0,0 +1,39 @@
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Root = Split-Path -Parent $ScriptDir
$SingBox = Join-Path $Root 'works/sing-box'
# defaults
$RepoUrl = 'git@git.inker.bot:arknights/sing-box.git'
$UpstreamBranch = 'main'
$ConfigFile = Join-Path $Root 'works/config'
if (Test-Path $ConfigFile) {
Get-Content $ConfigFile | ForEach-Object {
if ($_ -match '^([^#=]+)=(.*)$') {
$key = $Matches[1].Trim()
$val = $Matches[2].Trim()
if ($key -eq 'REPO_URL') { $RepoUrl = $val }
elseif ($key -eq 'UPSTREAM_BRANCH') { $UpstreamBranch = $val }
}
}
}
if (Test-Path (Join-Path $SingBox '.git')) {
Write-Host 'Updating sing-box...'
git -C $SingBox fetch --all
if ($UpstreamBranch) { git -C $SingBox checkout $UpstreamBranch }
git -C $SingBox pull
} else {
Write-Host 'Cloning sing-box...'
if ($UpstreamBranch) {
git clone -b $UpstreamBranch $RepoUrl $SingBox
} else {
git clone $RepoUrl $SingBox
}
}
$version = git -C $SingBox describe --tags --always 2>$null
if (-not $version) { $version = git -C $SingBox rev-parse --short HEAD }
Write-Host "Done. Version: $version"
+2
View File
@@ -0,0 +1,2 @@
/sing-box
/core
+2
View File
@@ -0,0 +1,2 @@
REPO_URL=git@git.inker.bot:arknights/sing-box.git
UPSTREAM_BRANCH=dev-next
+1
View File
@@ -0,0 +1 @@
.idea
+47
View File
@@ -0,0 +1,47 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/cmd/sing-box/cmd_run.go 2026-03-05 11:39:22.614241536 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/cmd/sing-box/cmd_run.go 2026-03-05 13:09:50.466040286 +0800
@@ -3,6 +3,7 @@
import (
"context"
"io"
+ "net/http" // OMV
"os"
"os/signal"
"path/filepath"
@@ -49,8 +50,36 @@
configContent []byte
err error
)
+ // OMV start: fetch subscription from env
+ subscriptionLink := os.Getenv("SING_SUBSCRIPTION_LINK")
+ subscriptionCache := os.Getenv("SING_SUBSCRIPTION_CACHE")
+ // OMV end
if path == "stdin" {
configContent, err = io.ReadAll(os.Stdin)
+ // OMV start: fetch subscription from env
+ } else if path == "env" && subscriptionLink != "" {
+ configContentResponse, err := http.Get(subscriptionLink)
+ if err != nil {
+ log.Warn("Cannot fetch subscription: ", err)
+ }
+ if err != nil || configContentResponse.StatusCode != 200 {
+ if subscriptionCache != "" {
+ log.Info("using previous subscription cache")
+ configContent, err = os.ReadFile(subscriptionCache)
+ } else {
+ return nil, E.Cause(err, "failed to GET subscription link")
+ }
+ } else {
+ defer configContentResponse.Body.Close()
+ configContent, err = io.ReadAll(configContentResponse.Body)
+ if err == nil && subscriptionCache != "" {
+ _err := os.WriteFile(subscriptionCache, configContent, 0600)
+ if _err != nil {
+ log.Error(E.Cause(_err, "failed to cache subscription file"))
+ }
+ }
+ }
+ // OMV end
} else {
configContent, err = os.ReadFile(path)
}
+21
View File
@@ -0,0 +1,21 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/constant/proxy.go 2026-03-05 11:39:22.619163709 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/constant/proxy.go 2026-03-05 13:11:43.857690519 +0800
@@ -31,6 +31,7 @@
TypeCCM = "ccm"
TypeOCM = "ocm"
TypeOOMKiller = "oom-killer"
+ TypeMySQL = "mysql" // OMV
)
const (
@@ -88,6 +89,10 @@
return "AnyTLS"
case TypeTailscale:
return "Tailscale"
+ // OMV start: register mysql type name
+ case TypeMySQL:
+ return "MySQL"
+ // OMV end
case TypeSelector:
return "Selector"
case TypeURLTest:
+52
View File
@@ -0,0 +1,52 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/go.mod 2026-03-05 12:48:33.529768921 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/go.mod 2026-03-05 13:02:19.454323175 +0800
@@ -11,6 +11,7 @@
github.com/database64128/tfo-go/v2 v2.3.2
github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/render v1.0.3
+ github.com/go-mysql-org/go-mysql v1.13.0
github.com/godbus/dbus/v5 v5.2.2
github.com/gofrs/uuid/v5 v5.4.0
github.com/insomniacslk/dhcp v0.0.0-20260220084031-5adc3eb26f91
@@ -85,6 +86,7 @@
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
+ github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.7.0 // indirect
@@ -100,6 +102,9 @@
github.com/mdlayher/socket v0.5.1 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
+ github.com/pingcap/errors v0.11.5-0.20250318082626-8f80e5cb09ec // indirect
+ github.com/pingcap/log v1.1.1-0.20241212030209-7e3ff8601a2a // indirect
+ github.com/pingcap/tidb/pkg/parser v0.0.0-20250421232622-526b2c79173d // indirect
github.com/pires/go-proxyproto v0.8.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus-community/pro-bing v0.4.0 // indirect
@@ -136,6 +141,7 @@
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260303100323-125d0d93b3e6 // indirect
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
+ github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
@@ -151,6 +157,7 @@
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
+ go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap/exp v0.3.0 // indirect
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
@@ -163,6 +170,7 @@
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
+ gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect
)
+158
View File
@@ -0,0 +1,158 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/go.sum 2026-03-05 12:48:33.529768921 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/go.sum 2026-03-05 13:02:19.455279219 +0800
@@ -14,6 +14,7 @@
github.com/anthropics/anthropic-sdk-go v1.26.0/go.mod h1:qUKmaW+uuPB64iy1l+4kOSvaLqPXnHTTBKH6RVZ7q5Q=
github.com/anytls/sing-anytls v0.0.11 h1:w8e9Uj1oP3m4zxkyZDewPk0EcQbvVxb7Nn+rapEx4fc=
github.com/anytls/sing-anytls v0.0.11/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
+github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/caddyserver/certmagic v0.25.2 h1:D7xcS7ggX/WEY54x0czj7ioTkmDWKIgxtIi2OcQclUc=
github.com/caddyserver/certmagic v0.25.2/go.mod h1:llW/CvsNmza8S6hmsuggsZeiX+uS27dkqY27wDIuBWg=
github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE=
@@ -36,6 +37,7 @@
github.com/database64128/tfo-go/v2 v2.3.2 h1:UhZMKiMq3swZGUiETkLBDzQnZBPSAeBMClpJGlnJ5Fw=
github.com/database64128/tfo-go/v2 v2.3.2/go.mod h1:GC3uB5oa4beGpCUbRb2ZOWP73bJJFmMyAVgQSO7r724=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk=
@@ -68,12 +70,14 @@
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-mysql-org/go-mysql v1.13.0/go.mod h1:FQxw17uRbFvMZFK+dPtIPufbU46nBdrGaxOw0ac9MFs=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/gofrs/uuid/v5 v5.4.0 h1:EfbpCTjqMuGyq5ZJwxqzn3Cbr2d0rUZU7v5ycAk/e/0=
@@ -110,6 +114,9 @@
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU=
github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk=
github.com/letsencrypt/pebble/v2 v2.10.0 h1:Wq6gYXlsY6ubqI3hhxsTzdyotvfdjFBxuwYqCLCnj/U=
@@ -144,8 +151,13 @@
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
+github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pingcap/errors v0.11.5-0.20250318082626-8f80e5cb09ec/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg=
+github.com/pingcap/log v1.1.1-0.20241212030209-7e3ff8601a2a/go.mod h1:ORfBOFp1eteu2odzsyaxI+b8TzJwgjwyQcGhI+9SfEA=
+github.com/pingcap/tidb/pkg/parser v0.0.0-20250421232622-526b2c79173d/go.mod h1:+8feuexTKcXHZF/dkDfvCwEyBAmgb4paFc3/WeYV2eE=
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -260,11 +272,14 @@
github.com/sagernet/wireguard-go v0.0.2-beta.1.0.20260224074747-506b7631853c/go.mod h1:WUxgxUDZoCF2sxVmW+STSxatP02Qn3FcafTiI2BLtE0=
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
+github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
@@ -319,10 +334,18 @@
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
+go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
@@ -332,6 +355,7 @@
go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
@@ -339,17 +363,22 @@
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -361,6 +390,7 @@
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
@@ -368,8 +398,12 @@
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -389,10 +423,14 @@
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
+26
View File
@@ -0,0 +1,26 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/include/registry.go 2026-03-05 12:48:33.529768921 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/include/registry.go 2026-03-05 13:14:06.319924033 +0800
@@ -23,6 +23,7 @@
"github.com/sagernet/sing-box/protocol/group"
"github.com/sagernet/sing-box/protocol/http"
"github.com/sagernet/sing-box/protocol/mixed"
+ "github.com/sagernet/sing-box/protocol/mysql" // OMV
"github.com/sagernet/sing-box/protocol/naive"
"github.com/sagernet/sing-box/protocol/redirect"
"github.com/sagernet/sing-box/protocol/shadowsocks"
@@ -62,6 +63,7 @@
shadowtls.RegisterInbound(registry)
vless.RegisterInbound(registry)
anytls.RegisterInbound(registry)
+ mysql.RegisterInbound(registry) // OMV
registerQUICInbounds(registry)
registerStubForRemovedInbounds(registry)
@@ -90,6 +92,7 @@
shadowtls.RegisterOutbound(registry)
vless.RegisterOutbound(registry)
anytls.RegisterOutbound(registry)
+ mysql.RegisterOutbound(registry) // OMV
registerQUICOutbounds(registry)
registerStubForRemovedOutbounds(registry)
+10
View File
@@ -0,0 +1,10 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/option/group.go 2026-03-05 11:39:22.629561767 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/option/group.go 2026-03-05 13:14:27.190665236 +0800
@@ -10,6 +10,7 @@
type URLTestOutboundOptions struct {
Outbounds []string `json:"outbounds"`
+ Costs map[string]uint16 `json:"costs,omitempty"` // OMV
URL string `json:"url,omitempty"`
Interval badoption.Duration `json:"interval,omitempty"`
Tolerance uint16 `json:"tolerance,omitempty"`
+26
View File
@@ -0,0 +1,26 @@
--- /dev/null 2026-03-05 11:06:53.990718185 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/option/mysql.go 2026-03-05 13:14:38.655523071 +0800
@@ -0,0 +1,23 @@
+// OMV
+package option
+
+type MySQLInboundOptions struct {
+ ListenOptions
+ InboundTLSOptionsContainer
+ Users []MySQLUser `json:"users,omitempty"`
+ Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
+}
+
+type MySQLUser struct {
+ User string `json:"user,omitempty"`
+ Password string `json:"password,omitempty"`
+}
+
+type MySQLOutboundOptions struct {
+ DialerOptions
+ ServerOptions
+ OutboundTLSOptionsContainer
+ Username string `json:"username,omitempty"`
+ Password string `json:"password,omitempty"`
+ Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
+}
@@ -0,0 +1,80 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/protocol/group/urltest.go 2026-03-05 11:39:22.630699577 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/protocol/group/urltest.go 2026-03-05 13:17:32.300369913 +0800
@@ -39,6 +39,7 @@
connection adapter.ConnectionManager
logger log.ContextLogger
tags []string
+ costs map[string]uint16 // OMV
link string
interval time.Duration
tolerance uint16
@@ -61,6 +62,7 @@
tolerance: options.Tolerance,
idleTimeout: time.Duration(options.IdleTimeout),
interruptExternalConnections: options.InterruptExistConnections,
+ costs: options.Costs, // OMV
}
if len(outbound.tags) == 0 {
return nil, E.New("missing tags")
@@ -77,7 +79,7 @@
}
outbounds = append(outbounds, detour)
}
- group, err := NewURLTestGroup(s.ctx, s.outbound, s.logger, outbounds, s.link, s.interval, s.tolerance, s.idleTimeout, s.interruptExternalConnections)
+ group, err := NewURLTestGroup(s.ctx, s.outbound, s.logger, outbounds, s.costs, s.link, s.interval, s.tolerance, s.idleTimeout, s.interruptExternalConnections) // OMV
if err != nil {
return err
}
@@ -194,6 +196,7 @@
pauseCallback *list.Element[pause.Callback]
logger log.Logger
outbounds []adapter.Outbound
+ costs map[string]uint16 // OMV
link string
interval time.Duration
tolerance uint16
@@ -211,7 +214,7 @@
lastActive common.TypedValue[time.Time]
}
-func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManager, logger log.Logger, outbounds []adapter.Outbound, link string, interval time.Duration, tolerance uint16, idleTimeout time.Duration, interruptExternalConnections bool) (*URLTestGroup, error) {
+func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManager, logger log.Logger, outbounds []adapter.Outbound, costs map[string]uint16, link string, interval time.Duration, tolerance uint16, idleTimeout time.Duration, interruptExternalConnections bool) (*URLTestGroup, error) { // OMV
if interval == 0 {
interval = C.DefaultURLTestInterval
}
@@ -221,6 +224,11 @@
if idleTimeout == 0 {
idleTimeout = C.DefaultURLTestIdleTimeout
}
+ // OMV start: initialize costs map
+ if costs == nil {
+ costs = map[string]uint16{}
+ }
+ // OMV end
if interval > idleTimeout {
return nil, E.New("interval must be less or equal than idle_timeout")
}
@@ -237,6 +245,7 @@
outbound: outboundManager,
logger: logger,
outbounds: outbounds,
+ costs: costs, // OMV
link: link,
interval: interval,
tolerance: tolerance,
@@ -392,7 +401,14 @@
g.logger.Debug("outbound ", tag, " unavailable: ", err)
g.history.DeleteURLTestHistory(realTag)
} else {
- g.logger.Debug("outbound ", tag, " available: ", t, "ms")
+ // OMV start: apply cost penalty to url test latency
+ add_latency, exist := g.costs[tag]
+ if !exist {
+ add_latency = 0
+ }
+ t = t + add_latency
+ g.logger.Debug("outbound ", tag, " available: ", t, "ms (add latency: ", add_latency, "ms)")
+ // OMV end
g.history.StoreURLTestHistory(realTag, &adapter.URLTestHistory{
Time: time.Now(),
Delay: t,
+258
View File
@@ -0,0 +1,258 @@
--- /dev/null 2026-03-05 11:06:53.990718185 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/protocol/mysql/inbound.go 2026-03-05 13:14:59.956258942 +0800
@@ -0,0 +1,255 @@
+// OMV
+package mysql
+
+import (
+ "context"
+ "net"
+ "os"
+
+ "github.com/sagernet/sing-box/adapter"
+ "github.com/sagernet/sing-box/adapter/inbound"
+ "github.com/sagernet/sing-box/common/listener"
+ "github.com/sagernet/sing-box/common/mux"
+ boxTLS "github.com/sagernet/sing-box/common/tls"
+ "github.com/sagernet/sing-box/common/uot"
+ C "github.com/sagernet/sing-box/constant"
+ "github.com/sagernet/sing-box/log"
+ "github.com/sagernet/sing-box/option"
+ "github.com/sagernet/sing/common"
+ E "github.com/sagernet/sing/common/exceptions"
+ "github.com/sagernet/sing/common/logger"
+ M "github.com/sagernet/sing/common/metadata"
+ N "github.com/sagernet/sing/common/network"
+ "github.com/sagernet/sing/common/task"
+ "github.com/sagernet/smux"
+
+ gmysql "github.com/go-mysql-org/go-mysql/mysql"
+ "github.com/go-mysql-org/go-mysql/server"
+)
+
+func RegisterInbound(registry *inbound.Registry) {
+ inbound.Register[option.MySQLInboundOptions](registry, C.TypeMySQL, NewInbound)
+}
+
+var _ adapter.TCPInjectableInbound = (*Inbound)(nil)
+
+type Inbound struct {
+ inbound.Adapter
+ router adapter.ConnectionRouterEx
+ logger logger.ContextLogger
+ listener *listener.Listener
+ tlsConfig boxTLS.ServerConfig
+ identityProvider *server.InMemoryProvider
+ mysqlServer *server.Server
+}
+
+func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.MySQLInboundOptions) (adapter.Inbound, error) {
+ inbound := &Inbound{
+ Adapter: inbound.NewAdapter(C.TypeMySQL, tag),
+ router: uot.NewRouter(router, logger),
+ logger: logger,
+ identityProvider: server.NewInMemoryProvider(),
+ }
+ for _, user := range options.Users {
+ inbound.identityProvider.AddUser(user.User, user.Password)
+ }
+
+ if options.TLS == nil || !options.TLS.Enabled {
+ return nil, C.ErrTLSRequired
+ }
+
+ tlsConfig, err := boxTLS.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
+ if err != nil {
+ return nil, err
+ }
+ inbound.tlsConfig = tlsConfig
+
+ // Get the standard *tls.Config from our TLS config for go-mysql server
+ stdTLSConfig, err := tlsConfig.STDConfig()
+ if err != nil {
+ return nil, E.Cause(err, "get std tls config")
+ }
+
+ // Create a go-mysql server with our TLS config
+ inbound.mysqlServer = server.NewServer(
+ "8.0.12",
+ gmysql.DEFAULT_COLLATION_ID,
+ gmysql.AUTH_NATIVE_PASSWORD,
+ nil,
+ stdTLSConfig,
+ )
+
+ inbound.router, err = mux.NewRouterWithOptions(inbound.router, logger, common.PtrValueOrDefault(options.Multiplex))
+ if err != nil {
+ return nil, err
+ }
+
+ inbound.listener = listener.New(listener.Options{
+ Context: ctx,
+ Logger: logger,
+ Network: []string{N.NetworkTCP},
+ Listen: options.ListenOptions,
+ ConnectionHandler: inbound,
+ })
+ return inbound, nil
+}
+
+func (h *Inbound) Start(stage adapter.StartStage) error {
+ if stage != adapter.StartStateStart {
+ return nil
+ }
+ if h.tlsConfig != nil {
+ err := h.tlsConfig.Start()
+ if err != nil {
+ return E.Cause(err, "create TLS config")
+ }
+ }
+ return h.listener.Start()
+}
+
+func (h *Inbound) Close() error {
+ return common.Close(
+ h.listener,
+ h.tlsConfig,
+ )
+}
+
+func (h *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
+ // Use go-mysql server to perform the MySQL handshake (which negotiates TLS)
+ mysqlConn, err := h.mysqlServer.NewCustomizedConn(conn, h.identityProvider, &emptyHandler{})
+ if err != nil {
+ N.CloseOnHandshakeFailure(conn, onClose, err)
+ h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source, ": MySQL handshake"))
+ return
+ }
+
+ // After MySQL handshake, the underlying connection is TLS-encrypted.
+ // Now get the underlying net.Conn (which is a *tls.Conn) and use smux on top of it.
+ tlsConn := mysqlConn.Conn.Conn
+
+ h.logger.InfoContext(ctx, "MySQL handshake completed from ", metadata.Source)
+
+ // Handle smux session over the TLS-encrypted connection
+ err = h.handleMuxSession(ctx, tlsConn, metadata.Source, onClose, mysqlConn.GetUser())
+ if err != nil && !E.IsClosed(err) {
+ h.logger.ErrorContext(ctx, E.Cause(err, "process mux session from ", metadata.Source))
+ }
+}
+
+func (h *Inbound) handleMuxSession(ctx context.Context, conn net.Conn, source M.Socksaddr, onClose N.CloseHandlerFunc, user string) error {
+ session, err := smux.Server(conn, smuxConfig())
+ if err != nil {
+ if onClose != nil {
+ onClose(err)
+ }
+ return err
+ }
+ var group task.Group
+ group.Append0(func(_ context.Context) error {
+ for {
+ stream, sErr := session.AcceptStream()
+ if sErr != nil {
+ return sErr
+ }
+ go h.handleMuxStream(ctx, stream, source, user)
+ }
+ })
+ group.Cleanup(func() {
+ session.Close()
+ if onClose != nil {
+ onClose(os.ErrClosed)
+ }
+ })
+ return group.Run(ctx)
+}
+
+func (h *Inbound) handleMuxStream(ctx context.Context, conn net.Conn, source M.Socksaddr, user string) {
+ err := h.handleMuxStream0(ctx, conn, source, user)
+ if err != nil {
+ h.logger.ErrorContext(ctx, E.Cause(err, "process mux stream"))
+ }
+}
+
+func (h *Inbound) handleMuxStream0(ctx context.Context, conn net.Conn, source M.Socksaddr, user string) error {
+ // Read destination from the stream header:
+ // 1 byte command (0x01=TCP, 0x03=UDP)
+ // then socks address (using SocksaddrSerializer)
+ var cmdBuf [1]byte
+ _, err := conn.Read(cmdBuf[:])
+ if err != nil {
+ return E.Cause(err, "read command")
+ }
+ command := cmdBuf[0]
+
+ destination, err := M.SocksaddrSerializer.ReadAddrPort(conn)
+ if err != nil {
+ return E.Cause(err, "read destination")
+ }
+
+ var metadata adapter.InboundContext
+ metadata.Inbound = h.Tag()
+ metadata.InboundType = h.Type()
+ metadata.Source = source
+ metadata.User = user
+
+ switch command {
+ case commandTCP:
+ metadata.Destination = destination
+ h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
+ h.router.RouteConnectionEx(ctx, conn, metadata, nil)
+ case commandUDP:
+ metadata.Destination = destination
+ h.logger.InfoContext(ctx, "inbound UoT packet connection to ", metadata.Destination)
+ h.router.RouteConnectionEx(ctx, conn, metadata, nil)
+ default:
+ return E.New("unknown command ", command)
+ }
+ return nil
+}
+
+func smuxConfig() *smux.Config {
+ config := smux.DefaultConfig()
+ config.KeepAliveDisabled = true
+ return config
+}
+
+const (
+ commandTCP byte = 0x01
+ commandUDP byte = 0x03
+)
+
+// emptyHandler implements go-mysql server.Handler with no-op operations.
+// It is used because we only need the MySQL handshake for TLS negotiation,
+// not actual MySQL query handling.
+type emptyHandler struct{}
+
+func (h *emptyHandler) UseDB(dbName string) error {
+ return nil
+}
+
+func (h *emptyHandler) HandleQuery(query string) (*gmysql.Result, error) {
+ return nil, gmysql.NewError(gmysql.ER_UNKNOWN_ERROR, "not supported")
+}
+
+func (h *emptyHandler) HandleFieldList(table string, fieldWildcard string) ([]*gmysql.Field, error) {
+ return nil, gmysql.NewError(gmysql.ER_UNKNOWN_ERROR, "not supported")
+}
+
+func (h *emptyHandler) HandleStmtPrepare(query string) (int, int, interface{}, error) {
+ return 0, 0, nil, gmysql.NewError(gmysql.ER_UNKNOWN_ERROR, "not supported")
+}
+
+func (h *emptyHandler) HandleStmtExecute(context interface{}, query string, args []interface{}) (*gmysql.Result, error) {
+ return nil, gmysql.NewError(gmysql.ER_UNKNOWN_ERROR, "not supported")
+}
+
+func (h *emptyHandler) HandleStmtClose(context interface{}) error {
+ return nil
+}
+
+func (h *emptyHandler) HandleOtherCommand(cmd byte, data []byte) error {
+ return gmysql.NewError(gmysql.ER_UNKNOWN_ERROR, "not supported")
+}
+
+// compile-time check
+var _ server.Handler = (*emptyHandler)(nil)
@@ -0,0 +1,299 @@
--- /dev/null 2026-03-05 11:06:53.990718185 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/protocol/mysql/outbound.go 2026-03-05 13:15:28.015911006 +0800
@@ -0,0 +1,296 @@
+// OMV
+package mysql
+
+import (
+ "context"
+ "crypto/tls"
+ "net"
+ "sync"
+ "sync/atomic"
+
+ "github.com/sagernet/sing-box/adapter"
+ "github.com/sagernet/sing-box/adapter/outbound"
+ "github.com/sagernet/sing-box/common/dialer"
+ C "github.com/sagernet/sing-box/constant"
+ "github.com/sagernet/sing-box/log"
+ "github.com/sagernet/sing-box/option"
+ "github.com/sagernet/sing/common"
+ E "github.com/sagernet/sing/common/exceptions"
+ "github.com/sagernet/sing/common/logger"
+ M "github.com/sagernet/sing/common/metadata"
+ N "github.com/sagernet/sing/common/network"
+ "github.com/sagernet/sing/common/uot"
+ "github.com/sagernet/smux"
+
+ "github.com/go-mysql-org/go-mysql/client"
+)
+
+func RegisterOutbound(registry *outbound.Registry) {
+ outbound.Register[option.MySQLOutboundOptions](registry, C.TypeMySQL, NewOutbound)
+}
+
+var _ adapter.InterfaceUpdateListener = (*Outbound)(nil)
+
+type Outbound struct {
+ outbound.Adapter
+ ctx context.Context
+ logger logger.ContextLogger
+ dialer N.Dialer
+ serverAddr M.Socksaddr
+ username string
+ password string
+ tlsConfig *tls.Config
+ maxConnections int
+ nextSession uint32
+
+ sessionAccess sync.Mutex
+ sessions []*muxSession
+}
+
+type muxSession struct {
+ session *smux.Session
+ conn net.Conn
+}
+
+func closeMuxSession(entry *muxSession) {
+ if entry == nil {
+ return
+ }
+ _ = common.Close(entry.session, entry.conn)
+}
+
+func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.MySQLOutboundOptions) (adapter.Outbound, error) {
+ outboundDialer, err := dialer.New(ctx, options.DialerOptions, options.ServerIsDomain())
+ if err != nil {
+ return nil, err
+ }
+
+ outbound := &Outbound{
+ Adapter: outbound.NewAdapterWithDialerOptions(C.TypeMySQL, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
+ ctx: ctx,
+ logger: logger,
+ dialer: outboundDialer,
+ serverAddr: options.ServerOptions.Build(),
+ username: options.Username,
+ password: options.Password,
+ maxConnections: 1,
+ }
+
+ if options.Multiplex != nil && options.Multiplex.Enabled && options.Multiplex.MaxConnections > 1 {
+ outbound.maxConnections = options.Multiplex.MaxConnections
+ }
+ outbound.sessions = make([]*muxSession, outbound.maxConnections)
+
+ if outbound.serverAddr.Port == 0 {
+ outbound.serverAddr.Port = 3306
+ }
+
+ if outbound.username == "" {
+ outbound.username = "root"
+ }
+
+ // Build TLS config for MySQL client handshake
+ if options.TLS != nil && options.TLS.Enabled {
+ outbound.tlsConfig = &tls.Config{
+ InsecureSkipVerify: options.TLS.Insecure,
+ ServerName: options.TLS.ServerName,
+ }
+ if outbound.tlsConfig.ServerName == "" {
+ outbound.tlsConfig.ServerName = options.Server
+ }
+ } else {
+ // Default: use insecure TLS (since this is for tunneling, not real MySQL)
+ outbound.tlsConfig = &tls.Config{
+ InsecureSkipVerify: true,
+ }
+ }
+
+ return outbound, nil
+}
+
+func (h *Outbound) createSession() (*muxSession, error) {
+ h.logger.InfoContext(h.ctx, "creating smux session")
+ // Dial TCP connection to server
+ conn, err := h.dialer.DialContext(h.ctx, N.NetworkTCP, h.serverAddr)
+ if err != nil {
+ return nil, E.Cause(err, "dial server")
+ }
+
+ // Perform MySQL handshake with TLS
+ mysqlConn, err := client.ConnectWithDialer(
+ h.ctx,
+ "tcp",
+ h.serverAddr.String(),
+ h.username,
+ h.password,
+ "",
+ func(ctx context.Context, network, address string) (net.Conn, error) {
+ // Return the already-established connection
+ return conn, nil
+ },
+ func(c *client.Conn) error {
+ c.SetTLSConfig(h.tlsConfig)
+ return nil
+ },
+ )
+ if err != nil {
+ conn.Close()
+ return nil, E.Cause(err, "MySQL handshake")
+ }
+
+ // After MySQL handshake, the underlying connection is TLS-encrypted.
+ // Get the underlying net.Conn.
+ tlsConn := mysqlConn.Conn.Conn
+
+ // Create smux session over the TLS connection
+ session, err := smux.Client(tlsConn, smuxConfig())
+ if err != nil {
+ tlsConn.Close()
+ return nil, E.Cause(err, "create mux session")
+ }
+
+ return &muxSession{session: session, conn: tlsConn}, nil
+}
+
+func (h *Outbound) getSession(index int) (*smux.Session, error) {
+ h.sessionAccess.Lock()
+ defer h.sessionAccess.Unlock()
+
+ entry := h.sessions[index]
+ if entry != nil && !entry.session.IsClosed() {
+ return entry.session, nil
+ }
+ if entry != nil {
+ closeMuxSession(entry)
+ h.sessions[index] = nil
+ }
+
+ entry, err := h.createSession()
+ if err != nil {
+ return nil, err
+ }
+ h.sessions[index] = entry
+
+ go func(index int, session *smux.Session, conn net.Conn) {
+ // When session is closed, clean up
+ <-session.CloseChan()
+ h.sessionAccess.Lock()
+ if current := h.sessions[index]; current != nil && current.session == session {
+ h.sessions[index] = nil
+ }
+ h.sessionAccess.Unlock()
+ _ = common.Close(session, conn)
+ }(index, entry.session, entry.conn)
+
+ return entry.session, nil
+}
+
+func (h *Outbound) invalidateSession(index int, session *smux.Session) {
+ h.sessionAccess.Lock()
+ defer h.sessionAccess.Unlock()
+
+ if current := h.sessions[index]; current != nil && current.session == session {
+ h.sessions[index] = nil
+ closeMuxSession(current)
+ }
+}
+
+func (h *Outbound) openStream(ctx context.Context, command byte, destination M.Socksaddr) (net.Conn, error) {
+ _ = ctx
+ start := int(atomic.AddUint32(&h.nextSession, 1)-1) % h.maxConnections
+ var lastErr error
+ for i := 0; i < h.maxConnections; i++ {
+ index := (start + i) % h.maxConnections
+ session, err := h.getSession(index)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+
+ stream, err := session.OpenStream()
+ if err != nil {
+ h.invalidateSession(index, session)
+ lastErr = err
+ continue
+ }
+
+ // Write stream header: command + destination
+ _, err = stream.Write([]byte{command})
+ if err != nil {
+ stream.Close()
+ lastErr = E.Cause(err, "write stream header command")
+ continue
+ }
+ err = M.SocksaddrSerializer.WriteAddrPort(stream, destination)
+ if err != nil {
+ stream.Close()
+ lastErr = E.Cause(err, "write stream header destination")
+ continue
+ }
+
+ return stream, nil
+ }
+ if lastErr == nil {
+ lastErr = E.New("open mux stream")
+ }
+ return nil, E.Cause(lastErr, "open mux stream")
+}
+
+func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
+ switch N.NetworkName(network) {
+ case N.NetworkTCP:
+ h.logger.InfoContext(ctx, "outbound connection to ", destination)
+ return h.openStream(ctx, commandTCP, destination)
+ case N.NetworkUDP:
+ h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
+ conn, err := h.openStream(ctx, commandUDP, uot.RequestDestination(uot.Version))
+ if err != nil {
+ return nil, err
+ }
+ return uot.NewLazyConn(conn, uot.Request{
+ IsConnect: true,
+ Destination: destination,
+ }), nil
+ default:
+ return nil, E.New("unsupported network: ", network)
+ }
+}
+
+func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
+ h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
+ conn, err := h.openStream(ctx, commandUDP, uot.RequestDestination(uot.Version))
+ if err != nil {
+ return nil, err
+ }
+ return uot.NewLazyConn(conn, uot.Request{
+ IsConnect: false,
+ Destination: destination,
+ }), nil
+}
+
+func (h *Outbound) InterfaceUpdated() {
+ h.sessionAccess.Lock()
+ defer h.sessionAccess.Unlock()
+ for i, session := range h.sessions {
+ if session == nil {
+ continue
+ }
+ session.session.Close()
+ session.conn.Close()
+ h.sessions[i] = nil
+ }
+}
+
+func (h *Outbound) Close() error {
+ h.sessionAccess.Lock()
+ defer h.sessionAccess.Unlock()
+ var err error
+ for i, session := range h.sessions {
+ if session == nil {
+ continue
+ }
+ err = common.Close(session.session, session.conn)
+ h.sessions[i] = nil
+ }
+ return err
+}
+27
View File
@@ -0,0 +1,27 @@
--- /data/projects/arknights/omv-dijiang/works/sing-box/route/route.go 2026-03-05 12:48:33.530768910 +0800
+++ /data/projects/arknights/omv-dijiang/works/core/route/route.go 2026-03-05 13:21:58.162073283 +0800
@@ -421,19 +421,19 @@
} else {
if processInfo.ProcessPath != "" {
if processInfo.UserName != "" {
- r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user: ", processInfo.UserName)
+ r.logger.DebugContext(ctx, "found process path: ", processInfo.ProcessPath, ", user: ", processInfo.UserName) // OMV: info -> debug
} else if processInfo.UserId != -1 {
- r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user id: ", processInfo.UserId)
+ r.logger.DebugContext(ctx, "found process path: ", processInfo.ProcessPath, ", user id: ", processInfo.UserId) // OMV: info -> debug
} else {
- r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath)
+ r.logger.DebugContext(ctx, "found process path: ", processInfo.ProcessPath) // OMV: info -> debug
}
} else if processInfo.AndroidPackageName != "" {
r.logger.InfoContext(ctx, "found package name: ", processInfo.AndroidPackageName)
} else if processInfo.UserId != -1 {
if processInfo.UserName != "" {
- r.logger.InfoContext(ctx, "found user: ", processInfo.UserName)
+ r.logger.DebugContext(ctx, "found user: ", processInfo.UserName) // OMV: info -> debug
} else {
- r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId)
+ r.logger.DebugContext(ctx, "found user id: ", processInfo.UserId) // OMV: info -> debug
}
}
metadata.ProcessInfo = processInfo