diff --git a/connector/handle_game_connection.go b/connector/handle_game_connection.go new file mode 100644 index 0000000..b2dc32e --- /dev/null +++ b/connector/handle_game_connection.go @@ -0,0 +1,16 @@ +package connector + +import ( + "io" +) + +// This is the size that Netty apparently uses to read from the incoming +// connection at a time +// +// This is documented in a mod that removes this limit: +// https://www.curseforge.com/minecraft/mc-mods/xl-packets +const nettyMaxPacketSize = 2_097_152 // 16MiB + +func handleGameConnection(conn io.Reader) { + panic("Unhandled game traffic") +} diff --git a/connector/listen_port.go b/connector/listen_port.go new file mode 100644 index 0000000..f2a7e7b --- /dev/null +++ b/connector/listen_port.go @@ -0,0 +1,77 @@ +package connector + +import ( + "bytes" + "fmt" + "io" + "net" + + log "github.com/sirupsen/logrus" + + "github.com/spf13/cobra" +) + +var ( + inputPort int + outputPort int +) + +func init() { + ProxyPortCommand.Flags().IntVar(&inputPort, "in", -1, "The input port, or the port to listen to a server on") + ProxyPortCommand.Flags().IntVar(&outputPort, "out", -1, "The output port, or the port for the client to listen on") + ProxyPortCommand.MarkFlagRequired("in") + ProxyPortCommand.MarkFlagRequired("out") +} + +var ProxyPortCommand = &cobra.Command{ + Use: "proxy", + Short: "Proxies the connection between the input and output ports", + RunE: func(cmd *cobra.Command, args []string) error { + + // Listen for connections to the local server + l, err := net.Listen("tcp", fmt.Sprintf(":%d", inputPort)) + if err != nil { + return err + } + + log.Infof("Listening for incoming connections on port %d", inputPort) + for { + conn, err := l.Accept() + if err != nil { + return err + } + + go handleConn(conn) + } + }, +} + +func handleConn(conn net.Conn) { + defer conn.Close() + log.Infof("Received connection from %v", conn.RemoteAddr()) + // Open a connection to the remote server + serverConn, err := net.Dial("tcp", fmt.Sprintf(":%d", outputPort)) + if err != nil { + panic(err) + } + defer serverConn.Close() + + var sidecarServerDataStream bytes.Buffer + + // Divert any data read from the server to be copied into the sidecar data stream + serverReader := io.TeeReader(serverConn, &sidecarServerDataStream) + + go handleGameConnection(&sidecarServerDataStream) + + // Start copying data from the server to the client + go func() { + if _, err := io.Copy(conn, serverReader); err != nil { + panic(err) + } + }() + + // Copy data from the client to the server + if _, err := io.Copy(serverConn, conn); err != nil { + panic(err) + } +} diff --git a/go.mod b/go.mod index 1d6fac8..6559197 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21.3 require ( github.com/charmbracelet/bubbletea v0.24.2 github.com/charmbracelet/lipgloss v0.9.1 + github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 ) diff --git a/go.sum b/go.sum index bd9bd1a..a5930f2 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/main.go b/main.go index 275f56d..4e47741 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "git.nicholasnovak.io/nnovak/spatial-db/connector" "git.nicholasnovak.io/nnovak/spatial-db/visualization" "github.com/spf13/cobra" ) @@ -11,6 +12,7 @@ func main() { } rootCmd.AddCommand(visualization.VisualizeCommand) + rootCmd.AddCommand(connector.ProxyPortCommand) if err := rootCmd.Execute(); err != nil { panic(err)