From 9dd5ec0ada2e06659d7ecbddb666d5d978a4141c Mon Sep 17 00:00:00 2001 From: 0xTux <0xtux@pm.me> Date: Wed, 23 Oct 2024 21:04:15 +0530 Subject: [PATCH] feat: add control client --- internal/client/init.go | 16 +++++++++- internal/client/tcp.go | 39 ++++++++++++++++++++++ internal/client/trok.go | 71 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 internal/client/tcp.go create mode 100644 internal/client/trok.go diff --git a/internal/client/init.go b/internal/client/init.go index cc1e7cc..d658340 100644 --- a/internal/client/init.go +++ b/internal/client/init.go @@ -5,9 +5,23 @@ Copyright © 2024 tux <0xtux@pm.me> package client import ( + "os" + "os/signal" + "github.com/rs/zerolog/log" ) func Start(port uint16) { - log.Info().Msgf("Hello from client: %d", port) + var trok Trok + if err := trok.Init(port); err != nil { + log.Fatal().Msgf("failed init trok %v", err) + } + + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, os.Interrupt) + + trok.Start() + defer trok.Stop() + + <-signalChan } diff --git a/internal/client/tcp.go b/internal/client/tcp.go new file mode 100644 index 0000000..8c509e2 --- /dev/null +++ b/internal/client/tcp.go @@ -0,0 +1,39 @@ +/* +Copyright © 2024 tux <0xtux@pm.me> +*/ + +package client + +import ( + "fmt" + "net" +) + +type TCPClient struct { + title string + conn net.Conn +} + +func (c *TCPClient) Init(port uint16, title string) error { + address := fmt.Sprintf(":%d", port) + conn, err := net.Dial("tcp", address) + if err != nil { + return err + } + + c.title = title + c.conn = conn + return nil +} + +func (c *TCPClient) Start(handler func(conn net.Conn)) { + handler(c.conn) +} + +func (c *TCPClient) Stop() error { + return c.conn.Close() +} + +func (c *TCPClient) Port() uint16 { + return uint16(c.conn.RemoteAddr().(*net.TCPAddr).Port) +} diff --git a/internal/client/trok.go b/internal/client/trok.go new file mode 100644 index 0000000..926768c --- /dev/null +++ b/internal/client/trok.go @@ -0,0 +1,71 @@ +/* +Copyright © 2024 tux <0xtux@pm.me> +*/ + +package client + +import ( + "net" + + "github.com/0xtux/trok/internal/lib" + "github.com/rs/zerolog/log" +) + +type Trok struct { + controlClient TCPClient +} + +func (t *Trok) Init(port uint16) error { + err := t.controlClient.Init(port, "Controller") + return err +} + +func (t *Trok) Start() { + go t.controlClient.Start(t.ControlConnHandler) + log.Info().Msgf("started Trok client on port %d", t.controlClient.Port()) +} + +func (t *Trok) Stop() { + t.controlClient.Stop() + log.Info().Msgf("stopped Trok client on port %d", t.controlClient.Port()) +} + +func (t *Trok) ControlConnHandler(conn net.Conn) { + p := lib.InitProtocolHandler(conn) + + p.WriteMessage(&lib.Message{CMD: "HELO", ARG: "Trok"}) + + for { + m, err := p.ReadMessage() + if err != nil { + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + log.Warn().Msgf("connection timed out: %s", conn.RemoteAddr()) + } else { + log.Logger.Info().Msgf("connection closed: %s", err) + } + return + } + + switch m.CMD { + + case "EHLO": + t.hanldeCMDEHLO(p, m) + + case "CNCT": + t.handleCMDCNCT(p, m) + + default: + log.Info().Msgf("invalid command") + } + } +} + +func (t *Trok) hanldeCMDEHLO(p *lib.ProtocolHandler, m *lib.Message) { + log.Info().Msgf("[CMD] %s [ARG] %s", m.CMD, m.ARG) + p.WriteMessage(m) +} + +func (t *Trok) handleCMDCNCT(p *lib.ProtocolHandler, m *lib.Message) { + log.Info().Msgf("[CMD] %s [ARG] %s", m.CMD, m.ARG) + p.WriteMessage(m) +}