Add SCUM Source RCON transport
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
maxSourceRCONCommandBytes = 4000
|
||||
maxSourceRCONChatBytes = 1024
|
||||
)
|
||||
|
||||
var sourceRCONSteamIDPattern = regexp.MustCompile(`^[0-9]{17}$`)
|
||||
|
||||
func ValidateSourceRCONCommandRequest(request domain.SourceRCONCommandRequest) error {
|
||||
request = domain.CopySourceRCONCommandRequest(request)
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "serverInstanceId", request.ServerInstanceID)
|
||||
violations = appendRequired(violations, "idempotencyKey", request.IdempotencyKey)
|
||||
if len([]byte(request.IdempotencyKey)) > 128 || strings.ContainsAny(request.IdempotencyKey, "\x00\r\n") {
|
||||
violations = append(violations, "idempotencyKey is invalid")
|
||||
}
|
||||
switch request.Kind {
|
||||
case domain.SourceRCONCommandKindChat:
|
||||
if request.Command != "" {
|
||||
violations = append(violations, "command must be empty for chat")
|
||||
}
|
||||
violations = append(violations, validateSourceRCONText("message", request.Message, maxSourceRCONChatBytes, true)...)
|
||||
if request.ChatType < 0 || request.ChatType > 7 {
|
||||
violations = append(violations, "chatType must be between 0 and 7")
|
||||
}
|
||||
if request.TargetSteamID != "" && !sourceRCONSteamIDPattern.MatchString(request.TargetSteamID) {
|
||||
violations = append(violations, "targetSteamId must be a 17-digit SteamID64")
|
||||
}
|
||||
case domain.SourceRCONCommandKindCommand:
|
||||
if request.Message != "" || request.TargetSteamID != "" || request.ChatType != 0 {
|
||||
violations = append(violations, "chat fields are not allowed for a raw command")
|
||||
}
|
||||
violations = append(violations, validateSourceRCONText("command", request.Command, maxSourceRCONCommandBytes, true)...)
|
||||
default:
|
||||
violations = append(violations, "kind must be chat or command")
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func validateRuntimeSourceRCONPlan(prefix string, plan *domain.RuntimeSourceRCONPlan) []string {
|
||||
if plan == nil {
|
||||
return []string{prefix + " is required"}
|
||||
}
|
||||
var violations []string
|
||||
if plan.Protocol != "source-rcon" {
|
||||
violations = append(violations, prefix+".protocol must be source-rcon")
|
||||
}
|
||||
violations = append(violations, validateProfileKey(prefix+".extensionKey", plan.ExtensionKey)...)
|
||||
if !runtimeDLLModKeyPattern.MatchString(plan.ModKey) {
|
||||
violations = append(violations, prefix+".modKey is invalid")
|
||||
}
|
||||
if plan.ConfigRef != "ue4ss/Mods/"+plan.ModKey+"/config.ini" || !validLogicalFileKey(plan.ConfigRef) {
|
||||
violations = append(violations, prefix+".configRef must be the managed UE4SS config path")
|
||||
}
|
||||
if !validSourceRCONDeploymentStateRef(plan.DeploymentStateRef) {
|
||||
violations = append(violations, prefix+".deploymentStateRef must be a managed UE4SS deployment state path")
|
||||
}
|
||||
if plan.Port < 1024 || plan.Port > 65535 {
|
||||
violations = append(violations, prefix+".port must be an unprivileged TCP port")
|
||||
}
|
||||
return violations
|
||||
}
|
||||
|
||||
func validSourceRCONDeploymentStateRef(value string) bool {
|
||||
const prefix = "runtime/ue4ss-dll/"
|
||||
const suffix = "/release.json"
|
||||
if !strings.HasPrefix(value, prefix) || !strings.HasSuffix(value, suffix) {
|
||||
return false
|
||||
}
|
||||
targetKey := strings.TrimSuffix(strings.TrimPrefix(value, prefix), suffix)
|
||||
return targetKey != "" && validLogicalFileKey(targetKey)
|
||||
}
|
||||
|
||||
func validateSourceRCONText(field string, value string, maxBytes int, required bool) []string {
|
||||
if required && strings.TrimSpace(value) == "" {
|
||||
return []string{field + " is required"}
|
||||
}
|
||||
if !utf8.ValidString(value) || len([]byte(value)) > maxBytes || strings.ContainsAny(value, "\x00\r\n") {
|
||||
return []string{field + " must be bounded UTF-8 without command framing controls"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user