Files
OmniSocketGo/cmd/kcppeer/interactive.go
nnbcccscdscdsc be013b701b feat:KCP协议
2026-03-24 21:09:06 +08:00

87 lines
2.6 KiB
Go

package main
import (
"errors"
"fmt"
"io"
"strings"
)
const (
kcpInteractiveCommandHelp = "help"
kcpInteractiveCommandQuit = "quit"
kcpInteractiveCommandText = "text"
kcpInteractiveCommandFile = "file"
)
var errKCPEmptyInteractiveCommand = errors.New("interactive command is empty")
type kcpInteractiveCommand struct {
name string
to string
value string
}
func parseKCPInteractiveCommand(line string) (kcpInteractiveCommand, error) {
commandName, rest, ok := cutKCPInteractiveField(strings.TrimSpace(line))
if !ok {
return kcpInteractiveCommand{}, errKCPEmptyInteractiveCommand
}
switch strings.ToLower(commandName) {
case "help", "h", "?":
return kcpInteractiveCommand{name: kcpInteractiveCommandHelp}, nil
case "quit", "exit":
return kcpInteractiveCommand{name: kcpInteractiveCommandQuit}, nil
case kcpInteractiveCommandText:
to, body, err := parseKCPInteractiveTargetValue(rest, kcpInteractiveCommandText)
if err != nil {
return kcpInteractiveCommand{}, err
}
return kcpInteractiveCommand{name: kcpInteractiveCommandText, to: to, value: body}, nil
case kcpInteractiveCommandFile:
to, path, err := parseKCPInteractiveTargetValue(rest, kcpInteractiveCommandFile)
if err != nil {
return kcpInteractiveCommand{}, err
}
return kcpInteractiveCommand{name: kcpInteractiveCommandFile, to: to, value: path}, nil
default:
return kcpInteractiveCommand{}, fmt.Errorf("unknown command %q; type help for usage", commandName)
}
}
func parseKCPInteractiveTargetValue(rest, commandName string) (string, string, error) {
to, value, ok := cutKCPInteractiveField(strings.TrimSpace(rest))
if !ok {
return "", "", fmt.Errorf("%s command requires a target peer and payload", commandName)
}
if strings.TrimSpace(value) == "" {
return "", "", fmt.Errorf("%s command requires a non-empty payload", commandName)
}
return to, strings.TrimSpace(value), nil
}
func cutKCPInteractiveField(input string) (string, string, bool) {
trimmed := strings.TrimSpace(input)
if trimmed == "" {
return "", "", false
}
for i, r := range trimmed {
if r == ' ' || r == '\t' {
return trimmed[:i], strings.TrimSpace(trimmed[i+1:]), true
}
}
return trimmed, "", true
}
func printKCPInteractiveHelp(w io.Writer) {
_, _ = fmt.Fprintln(w, "interactive mode commands (KCP):")
_, _ = fmt.Fprintln(w, " help show this help")
_, _ = fmt.Fprintln(w, " text <peer> <message> send one text message over the existing KCP session")
_, _ = fmt.Fprintln(w, " file <peer> <path> send one file over the existing KCP session")
_, _ = fmt.Fprintln(w, " quit exit this peer process")
}