feat: add TCP Server, UDP Server, and COM port forwarding modes

Extend Mode constants (3=TCPServer, 4=UDPServer, 5=COMPort) with
explicit values. Refactor Target to support multiple connection types
(listener+conns map, packetConn, serialPort). Add acceptLoop,
readLoopPacket, readLoopSerial. Mode-aware Broadcast dispatches to
all accepted conns (TCP-S), known remotes (UDP-S), or serial port.
Update flag help, command completions, and TUI panel hints.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
JiXieShi
2026-05-23 23:10:02 +08:00
parent d8fc9d7374
commit 30d6c2bc3c
6 changed files with 367 additions and 57 deletions
+2 -2
View File
@@ -39,7 +39,7 @@ func (d *Dispatcher) handleForwardCommand(args []string) error {
case "add":
if len(args) < 4 {
return fmt.Errorf("usage: .forward add <tcp|udp> <address>")
return fmt.Errorf("usage: .forward add <tcp|udp|tcp-s|udp-s|com> <address>")
}
mode, ok := forward.ParseMode(args[2])
if !ok {
@@ -71,7 +71,7 @@ func (d *Dispatcher) handleForwardCommand(args []string) error {
case "update":
if len(args) < 5 {
return fmt.Errorf("usage: .forward update <id> <tcp|udp> <address>")
return fmt.Errorf("usage: .forward update <id> <tcp|udp|tcp-s|udp-s|com> <address>")
}
id, err := strconv.Atoi(args[2])
if err != nil {
+3 -3
View File
@@ -29,15 +29,15 @@ func filterPrefix(cands []string, cur string) []string {
func completeForward(args []string) []string {
if len(args) <= 2 {
return []string{"list", "add", "remove", "enable", "disable", "update", "stats"}
return []string{"list", "add", "remove", "enable", "disable", "update"}
}
if len(args) == 3 && args[1] == "add" {
return []string{"tcp", "udp"}
return []string{"tcp", "udp", "tcp-s", "udp-s", "com"}
}
if len(args) == 4 && args[1] == "update" {
return []string{"tcp", "udp"}
return []string{"tcp", "udp", "tcp-s", "udp-s", "com"}
}
return nil
+2 -2
View File
@@ -99,8 +99,8 @@ func (d *Dispatcher) registerAll() {
d.register(RuntimeCommand{
Name: ".forward",
Usage: ".forward <list|add|remove|enable|disable|update|stats>",
Description: "manage forwarding at runtime",
Usage: ".forward <list|add|remove|enable|disable|update>",
Description: "manage forwarding (tcp/udp/tcp-s/udp-s/com)",
Handler: d.handleForwardCommand,
Completer: completeForward,
})
+3 -3
View File
@@ -37,7 +37,7 @@ func Init(cfg *config.Config) {
pflag.IntVarP(&cfg.ParityBit, "verify", "v", 0, "parity (0:none,1:odd,2:even,3:mark,4:space)")
pflag.BoolVarP(&cfg.EnableGUI, "gui", "g", false, "enable TUI mode")
pflag.StringVarP(&cfg.HotkeyMod, "hotkey-mod", "k", "ctrl+alt", "hotkey modifier (ctrl+alt|ctrl+shift)")
pflag.IntSliceVarP(&cfg.ForWard, "forward", "f", nil, "forward mode (0:none,1:TCP,2:UDP)")
pflag.IntSliceVarP(&cfg.ForWard, "forward", "f", nil, "forward mode (0:none,1:TCP,2:UDP,3:TCP-S,4:UDP-S,5:COM)")
pflag.StringArrayVarP(&cfg.Address, "address", "a", nil, "forward address")
pflag.StringVarP(&cfg.LogFilePath, "log", "l", "", "log file path")
_ = pflag.Lookup("log") // mark for NoOptDefVal
@@ -99,7 +99,7 @@ func PrintUsage(ports []string) {
{"-v", "--verify", "int", "parity", "0"},
{"-g", "--gui", "bool", "enable TUI", "false"},
{"-k", "--hotkey-mod", "string", "hotkey modifier", "ctrl+alt"},
{"-f", "--forward", "[]int", "forward mode", "0"},
{"-f", "--forward", "[]int", "forward (0:none,1:TCP,2:UDP,3:TCP-S,4:UDP-S,5:COM)", "0"},
{"-a", "--address", "[]string", "forward address", "127.0.0.1:12345"},
{"-l", "--log", "string", "log path", "./%s-$s.txt"},
{"-t", "--time", "string", "timestamp format", "[06-01-02 15:04:05.000]"},
@@ -122,7 +122,7 @@ var (
datas = []string{"5", "6", "7", "8"}
stops = []string{"1", "1.5", "2"}
paritys = []string{"None", "Odd", "Even", "Mark", "Space"}
forwards = []string{"No", "TCP-C", "UDP-C"}
forwards = []string{"No", "TCP-C", "UDP-C", "TCP-S", "UDP-S", "COM"}
)
// GetCliFlag runs an interactive configuration wizard when no port is specified.
+3 -3
View File
@@ -103,10 +103,10 @@ func (m *Model) handleForwardPanelKey(key string) bool {
m.refreshPanel()
return true
case "a":
m.startPrompt("Add Forward", "tcp 127.0.0.1:12345", "", func(v string) {
m.startPrompt("Add Forward", "tcp 127.0.0.1:12345 (tcp|udp|tcp-s|udp-s|com)", "", func(v string) {
parts := strings.Fields(v)
if len(parts) < 2 {
m.panelError = "usage: <tcp|udp> <address>"
m.panelError = "usage: <tcp|udp|tcp-s|udp-s|com> <address>"
return
}
mode, ok := forward.ParseMode(parts[0])
@@ -158,7 +158,7 @@ func (m *Model) handleForwardPanelKey(key string) bool {
m.startPrompt("Update Forward #"+fmt.Sprint(sel.ID), "tcp 127.0.0.1:12345", fmt.Sprintf("%s %s", sel.Mode, sel.Address), func(v string) {
parts := strings.Fields(v)
if len(parts) < 2 {
m.panelError = "usage: <tcp|udp> <address>"
m.panelError = "usage: <tcp|udp|tcp-s|udp-s|com> <address>"
return
}
mode, ok := forward.ParseMode(parts[0])