Files
mc-gateway/internal/adminservice/service.go
tursom f508ecc1b9
Some checks failed
Go / build (.exe, 386, windows, windows-386) (push) Has been cancelled
Go / build (.exe, amd64, windows, windows-amd64) (push) Has been cancelled
Go / build (.exe, arm64, windows, windows-arm64) (push) Has been cancelled
Go / build (386, freebsd, freebsd-386) (push) Has been cancelled
Go / build (386, linux, linux-386) (push) Has been cancelled
Go / build (386, netbsd, netbsd-386) (push) Has been cancelled
Go / build (386, openbsd, openbsd-386) (push) Has been cancelled
Go / build (386, plan9, plan9-386) (push) Has been cancelled
Go / build (amd64, darwin, darwin-amd64) (push) Has been cancelled
Go / build (amd64, dragonfly, dragonfly-amd64) (push) Has been cancelled
Go / build (amd64, freebsd, freebsd-amd64) (push) Has been cancelled
Go / build (amd64, illumos, illumos-amd64) (push) Has been cancelled
Go / build (amd64, linux, linux-amd64) (push) Has been cancelled
Go / build (amd64, netbsd, netbsd-amd64) (push) Has been cancelled
Go / build (amd64, openbsd, openbsd-amd64) (push) Has been cancelled
Go / build (amd64, plan9, plan9-amd64) (push) Has been cancelled
Go / build (amd64, solaris, solaris-amd64) (push) Has been cancelled
Go / build (arm, 6, linux, linux-armv6) (push) Has been cancelled
Go / build (arm, 7, linux, linux-armv7) (push) Has been cancelled
Go / build (arm, freebsd, freebsd-arm) (push) Has been cancelled
Go / build (arm, netbsd, netbsd-arm) (push) Has been cancelled
Go / build (arm, openbsd, openbsd-arm) (push) Has been cancelled
Go / build (arm, plan9, plan9-arm) (push) Has been cancelled
Go / build (arm64, darwin, darwin-arm64) (push) Has been cancelled
Go / build (arm64, freebsd, freebsd-arm64) (push) Has been cancelled
Go / build (arm64, linux, linux-arm64) (push) Has been cancelled
Go / build (arm64, netbsd, netbsd-arm64) (push) Has been cancelled
Go / build (arm64, openbsd, openbsd-arm64) (push) Has been cancelled
Go / build (loong64, linux, linux-loong64) (push) Has been cancelled
Go / build (mips, linux, linux-mips) (push) Has been cancelled
Go / build (mips64, linux, linux-mips64) (push) Has been cancelled
Go / build (mips64le, linux, linux-mips64le) (push) Has been cancelled
Go / build (mipsle, linux, linux-mipsle) (push) Has been cancelled
Go / build (ppc64, aix, aix-ppc64) (push) Has been cancelled
Go / build (ppc64, linux, linux-ppc64) (push) Has been cancelled
Go / build (ppc64, openbsd, openbsd-ppc64) (push) Has been cancelled
Go / build (ppc64le, linux, linux-ppc64le) (push) Has been cancelled
Go / build (riscv64, freebsd, freebsd-riscv64) (push) Has been cancelled
Go / build (riscv64, linux, linux-riscv64) (push) Has been cancelled
Go / build (riscv64, openbsd, openbsd-riscv64) (push) Has been cancelled
Go / build (s390x, linux, linux-s390x) (push) Has been cancelled
Docker Image / docker (push) Has been cancelled
Go / merge-artifacts (push) Has been cancelled
docs: 补充中文代码注释
2026-06-27 20:15:29 +08:00

203 lines
5.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// internal/adminservice/service.go 在原始服务仓库之上应用服务校验、默认值和更新语义。
package adminservice
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
)
const (
NameTCPAdmin = "tcp_admin"
NameKCP = "kcp"
NameQUIC = "quic"
NameWebSocket = "websocket"
DefaultKCPPort = 25566
DefaultKCPDataShards = 10
DefaultKCPParityShards = 3
DefaultQUICPort = 25565
DefaultWebSocketPort = 25566
DefaultWebSocketPath = "/"
)
var defaultQUICApplicationProtocols = []string{"minecraft", "quic", "raw", "h3"}
type Record struct {
Name string `json:"name"`
Enabled bool `json:"enabled"`
Port int `json:"port"`
Options map[string]any `json:"options"`
RestartRequired bool `json:"restart_required"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
UpdatedBy string `json:"updated_by"`
Running bool `json:"running"`
}
// DefaultRecords 给新数据库写入可管理的监听服务。只有 TCP/Admin 默认启用,
// 其他传输保留配置但不自动开放端口。
func DefaultRecords(tcpAdminPort int) []Record {
return []Record{
{Name: NameTCPAdmin, Enabled: true, Port: tcpAdminPort, Options: map[string]any{}},
{Name: NameKCP, Enabled: false, Port: DefaultKCPPort, Options: map[string]any{
"data_shards": DefaultKCPDataShards,
"parity_shards": DefaultKCPParityShards,
}},
{Name: NameQUIC, Enabled: false, Port: DefaultQUICPort, Options: map[string]any{
"application_protocols": append([]string(nil), defaultQUICApplicationProtocols...),
}},
{Name: NameWebSocket, Enabled: false, Port: DefaultWebSocketPort, Options: map[string]any{
"path": DefaultWebSocketPath,
}},
}
}
// DefaultPort 返回服务的默认端口TCP/Admin 使用启动配置传入的端口。
func DefaultPort(name string, tcpAdminPort int) int {
switch name {
case NameTCPAdmin:
return tcpAdminPort
case NameKCP:
return DefaultKCPPort
case NameQUIC:
return DefaultQUICPort
case NameWebSocket:
return DefaultWebSocketPort
default:
return 0
}
}
// ValidateUpdate 校验管理端提交的服务更新。TCP/Admin 是控制面入口,不能禁用。
func ValidateUpdate(name string, enabled bool, port int) error {
if !IsKnown(name) {
return fmt.Errorf("unknown service %q", name)
}
if port < 1 || port > 65535 {
return errors.New("port must be an integer from 1 to 65535")
}
if name == NameTCPAdmin && !enabled {
return errors.New("tcp_admin cannot be disabled")
}
return nil
}
// IsKnown 判断服务名是否属于当前网关支持的内置监听服务。
func IsKnown(name string) bool {
switch name {
case NameTCPAdmin, NameKCP, NameQUIC, NameWebSocket:
return true
default:
return false
}
}
// DecodeOptions 容错解析 JSON 选项;坏数据不会让整个服务列表不可读。
func DecodeOptions(optionsJSON string) map[string]any {
options := map[string]any{}
if strings.TrimSpace(optionsJSON) == "" {
return options
}
if err := json.Unmarshal([]byte(optionsJSON), &options); err != nil {
return map[string]any{}
}
return options
}
// NormalizeOptions 为不同服务补齐选项默认值,并修正 WebSocket path 这种可恢复输入。
func NormalizeOptions(name string, options map[string]any) map[string]any {
if options == nil {
options = map[string]any{}
}
normalized := map[string]any{}
for key, value := range options {
normalized[key] = value
}
switch name {
case NameKCP:
if IntOption(normalized, "data_shards", 0) <= 0 {
normalized["data_shards"] = DefaultKCPDataShards
}
if IntOption(normalized, "parity_shards", 0) <= 0 {
normalized["parity_shards"] = DefaultKCPParityShards
}
case NameQUIC:
if len(StringSliceOption(normalized, "application_protocols")) == 0 {
normalized["application_protocols"] = append([]string(nil), defaultQUICApplicationProtocols...)
}
case NameWebSocket:
p := StringOption(normalized, "path", DefaultWebSocketPath)
if !strings.HasPrefix(p, "/") {
p = "/" + p
}
normalized["path"] = p
}
return normalized
}
// IntOption 从 JSON 解码后的 map 中读取整数,兼容 number 和字符串形式。
func IntOption(options map[string]any, key string, fallback int) int {
value, ok := options[key]
if !ok {
return fallback
}
switch v := value.(type) {
case int:
return v
case int64:
return int(v)
case float64:
return int(v)
case json.Number:
i, err := v.Int64()
if err == nil {
return int(i)
}
case string:
i, err := strconv.Atoi(v)
if err == nil {
return i
}
}
return fallback
}
// StringOption 从 JSON 选项中读取非空字符串。
func StringOption(options map[string]any, key, fallback string) string {
value, ok := options[key]
if !ok {
return fallback
}
if s, ok := value.(string); ok && s != "" {
return s
}
return fallback
}
// StringSliceOption 从 JSON 选项中读取字符串数组,兼容 []any 的解码结果。
func StringSliceOption(options map[string]any, key string) []string {
value, ok := options[key]
if !ok {
return nil
}
switch v := value.(type) {
case []string:
return v
case []any:
out := make([]string, 0, len(v))
for _, item := range v {
if s, ok := item.(string); ok && s != "" {
out = append(out, s)
}
}
return out
}
return nil
}