feat:多跳(B->D->C->A)功能
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
kcp "github.com/xtaci/kcp-go/v5"
|
||||
|
||||
@@ -13,94 +14,124 @@ import (
|
||||
"omnisocketgo/cmd/internal/transport"
|
||||
)
|
||||
|
||||
const (
|
||||
kcpServerModeHub = "hub"
|
||||
kcpServerModeRelay = "relay"
|
||||
)
|
||||
|
||||
func main() {
|
||||
listenAddr := flag.String("listen", ":9002", "KCP server listen address")
|
||||
mode := flag.String("mode", kcpServerModeHub, "kcpserver mode: hub or relay")
|
||||
listenAddr := flag.String("listen", ":9002", "listen address; KCP listener in hub mode, UDP relay listener in relay mode")
|
||||
bindDevice := flag.String("bind-device", "", "optional Linux network device used when listening")
|
||||
logPath := flag.String("latency-log", "", "optional JSONL file path for latency timestamp logs")
|
||||
kcpTimestampDebugLogPath := flag.String("kcp-ts-debug-log", "", "optional JSONL file path for KCP packet kernel timestamp debug records")
|
||||
kcpSessionStatsLogPath := flag.String("kcp-session-stats-log", "", "optional JSONL file path for KCP session stats records")
|
||||
kcpSessionStatsInterval := flag.String("kcp-session-stats-interval", transport.DefaultKCPSessionStatsInterval.String(), "sampling interval for KCP session stats, for example 100ms")
|
||||
relayListenAddr := flag.String("relay-listen", "", "optional raw UDP relay listen address")
|
||||
relayPeerAddr := flag.String("relay-peer", "", "optional fixed raw UDP relay peer address")
|
||||
relayLearnPeer := flag.Bool("relay-learn-peer", false, "learn the relay peer address from the first inbound relay packet")
|
||||
relayListenAddr := flag.String("relay-listen", "", "deprecated alias for -listen in relay mode")
|
||||
relayRemoteAddr := flag.String("relay-remote", "", "fixed remote UDP address used in relay mode")
|
||||
relayPeerAddr := flag.String("relay-peer", "", "deprecated alias for -relay-remote")
|
||||
flag.Parse()
|
||||
|
||||
var relayRemoteFlagSet bool
|
||||
var relayPeerFlagSet bool
|
||||
var relayListenFlagSet bool
|
||||
flag.Visit(func(f *flag.Flag) {
|
||||
switch f.Name {
|
||||
case "relay-listen":
|
||||
relayListenFlagSet = true
|
||||
case "relay-remote":
|
||||
relayRemoteFlagSet = true
|
||||
case "relay-peer":
|
||||
relayPeerFlagSet = true
|
||||
}
|
||||
})
|
||||
|
||||
switch {
|
||||
case relayRemoteFlagSet && relayPeerFlagSet && *relayRemoteAddr != *relayPeerAddr:
|
||||
log.Fatal("flags -relay-remote and -relay-peer must match when both are set")
|
||||
case *relayRemoteAddr == "" && *relayPeerAddr != "":
|
||||
*relayRemoteAddr = *relayPeerAddr
|
||||
}
|
||||
if relayPeerFlagSet {
|
||||
log.Printf("warning: flag -relay-peer is deprecated; use -relay-remote instead")
|
||||
}
|
||||
if relayListenFlagSet {
|
||||
if *relayListenAddr == "" {
|
||||
log.Fatal("flag -relay-listen must not be empty when set")
|
||||
}
|
||||
if *mode != kcpServerModeRelay {
|
||||
log.Fatal("flag -relay-listen may only be used in relay mode")
|
||||
}
|
||||
if *listenAddr != ":9002" && *listenAddr != *relayListenAddr {
|
||||
log.Fatal("flags -listen and -relay-listen must match when both are set in relay mode")
|
||||
}
|
||||
*listenAddr = *relayListenAddr
|
||||
log.Printf("warning: flag -relay-listen is deprecated; use -listen with -mode=relay instead")
|
||||
}
|
||||
|
||||
statsInterval, err := transport.ParseKCPSessionStatsInterval(*kcpSessionStatsInterval)
|
||||
if err != nil {
|
||||
log.Fatalf("parse -kcp-session-stats-interval=%q: %v", *kcpSessionStatsInterval, err)
|
||||
}
|
||||
|
||||
switch *mode {
|
||||
case kcpServerModeHub:
|
||||
if *relayRemoteAddr != "" {
|
||||
log.Fatal("flag -relay-remote may only be used in relay mode")
|
||||
}
|
||||
runHubServer(*listenAddr, *bindDevice, *logPath, *kcpTimestampDebugLogPath, *kcpSessionStatsLogPath, statsInterval)
|
||||
case kcpServerModeRelay:
|
||||
if *bindDevice != "" {
|
||||
log.Fatal("flag -bind-device is not supported in relay mode")
|
||||
}
|
||||
if *relayRemoteAddr == "" {
|
||||
log.Fatal("flag -relay-remote is required in relay mode")
|
||||
}
|
||||
runUDPRelayServer(*listenAddr, *relayRemoteAddr)
|
||||
default:
|
||||
log.Fatalf("unsupported -mode=%q; want %q or %q", *mode, kcpServerModeHub, kcpServerModeRelay)
|
||||
}
|
||||
}
|
||||
|
||||
func runHubServer(listenAddr, bindDevice, logPath, packetDebugLogPath, sessionStatsLogPath string, statsInterval time.Duration) {
|
||||
hubOptions := make([]server.KCPOption, 0, 2)
|
||||
if *logPath != "" {
|
||||
logger, err := latencylog.NewJSONLLogger(*logPath)
|
||||
if logPath != "" {
|
||||
logger, err := latencylog.NewJSONLLogger(logPath)
|
||||
if err != nil {
|
||||
log.Fatalf("create latency logger %s: %v", *logPath, err)
|
||||
log.Fatalf("create latency logger %s: %v", logPath, err)
|
||||
}
|
||||
defer logger.Close()
|
||||
hubOptions = append(hubOptions, server.WithKCPLogger(logger))
|
||||
}
|
||||
|
||||
var packetLogger transport.KCPPacketDebugLogger
|
||||
if *kcpTimestampDebugLogPath != "" {
|
||||
logger, err := transport.NewJSONLKCPPacketDebugLogger(*kcpTimestampDebugLogPath)
|
||||
if packetDebugLogPath != "" {
|
||||
logger, err := transport.NewJSONLKCPPacketDebugLogger(packetDebugLogPath)
|
||||
if err != nil {
|
||||
log.Fatalf("create kcp packet debug logger %s: %v", *kcpTimestampDebugLogPath, err)
|
||||
log.Fatalf("create kcp packet debug logger %s: %v", packetDebugLogPath, err)
|
||||
}
|
||||
defer logger.Close()
|
||||
packetLogger = logger
|
||||
}
|
||||
if *kcpSessionStatsLogPath != "" {
|
||||
logger, err := transport.NewJSONLKCPSessionStatsLogger(*kcpSessionStatsLogPath)
|
||||
if sessionStatsLogPath != "" {
|
||||
logger, err := transport.NewJSONLKCPSessionStatsLogger(sessionStatsLogPath)
|
||||
if err != nil {
|
||||
log.Fatalf("create kcp session stats logger %s: %v", *kcpSessionStatsLogPath, err)
|
||||
log.Fatalf("create kcp session stats logger %s: %v", sessionStatsLogPath, err)
|
||||
}
|
||||
defer logger.Close()
|
||||
hubOptions = append(hubOptions, server.WithKCPSessionStatsLogger(logger, statsInterval))
|
||||
}
|
||||
|
||||
listener, packetConn, err := transport.ListenKCPSessions(*listenAddr, *bindDevice, packetLogger, latencylog.NodeRoleServer, "hub")
|
||||
listener, packetConn, err := transport.ListenKCPSessions(listenAddr, bindDevice, packetLogger, latencylog.NodeRoleServer, "hub")
|
||||
if err != nil {
|
||||
log.Fatalf("listen kcp on %s: %v", *listenAddr, err)
|
||||
log.Fatalf("listen kcp on %s: %v", listenAddr, err)
|
||||
}
|
||||
defer packetConn.Close()
|
||||
defer listener.Close()
|
||||
|
||||
hub := server.NewKCPHub(hubOptions...)
|
||||
|
||||
if *relayPeerAddr != "" && *relayListenAddr == "" {
|
||||
log.Fatal("flag -relay-listen is required when -relay-peer is set")
|
||||
}
|
||||
if *relayLearnPeer && *relayListenAddr == "" {
|
||||
log.Fatal("flag -relay-listen is required when -relay-learn-peer is set")
|
||||
}
|
||||
if *relayListenAddr != "" {
|
||||
relayConn, err := net.ListenPacket("udp", *relayListenAddr)
|
||||
if err != nil {
|
||||
log.Fatalf("listen relay udp on %s: %v", *relayListenAddr, err)
|
||||
}
|
||||
defer relayConn.Close()
|
||||
|
||||
var relayPeer net.Addr
|
||||
if *relayPeerAddr != "" {
|
||||
relayPeer, err = net.ResolveUDPAddr("udp", *relayPeerAddr)
|
||||
if err != nil {
|
||||
log.Fatalf("resolve relay peer %s: %v", *relayPeerAddr, err)
|
||||
}
|
||||
}
|
||||
|
||||
hub.SetRelaySocket(relayConn, relayPeer, *relayLearnPeer)
|
||||
go func() {
|
||||
if serveErr := hub.ServeRelay(); serveErr != nil {
|
||||
log.Printf("kcp relay loop ended: %v", serveErr)
|
||||
}
|
||||
}()
|
||||
log.Printf("kcp relay listening on %s", relayConn.LocalAddr())
|
||||
if relayPeer != nil {
|
||||
log.Printf("kcp relay peer configured as %s", relayPeer)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("kcp server listening on %s", listener.Addr())
|
||||
log.Printf("kcp hub listening on %s", listener.Addr())
|
||||
|
||||
for {
|
||||
session, err := listener.AcceptKCP()
|
||||
@@ -119,3 +150,26 @@ func main() {
|
||||
}(session)
|
||||
}
|
||||
}
|
||||
|
||||
func runUDPRelayServer(listenAddr, remoteAddr string) {
|
||||
conn, err := net.ListenPacket("udp", listenAddr)
|
||||
if err != nil {
|
||||
log.Fatalf("listen udp relay on %s: %v", listenAddr, err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
remote, err := net.ResolveUDPAddr("udp", remoteAddr)
|
||||
if err != nil {
|
||||
log.Fatalf("resolve relay remote %s: %v", remoteAddr, err)
|
||||
}
|
||||
|
||||
relay, err := server.NewUDPRelay(conn, remote)
|
||||
if err != nil {
|
||||
log.Fatalf("create udp relay: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("udp relay listening on %s and forwarding to %s", conn.LocalAddr(), remote)
|
||||
if err := relay.Serve(); err != nil {
|
||||
log.Fatalf("udp relay stopped: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user