From 1baea857deee552de26700c77bc779072f6e53d1 Mon Sep 17 00:00:00 2001 From: Brandon Fulljames Date: Thu, 7 Nov 2024 18:26:28 +0900 Subject: [PATCH] Make listen echo optional --- README.md | 4 +++- cmd/cyn/cmds/root.go | 14 ++++++++++---- pkg/cyn/cyn.go | 16 ++++++++-------- pkg/httpserver/server.go | 4 ++-- pkg/listener/tcp.go | 21 +++++++++++++++------ pkg/listener/udp.go | 21 +++++++++++++++------ tests/features/listen-tcp.feature | 3 ++- tests/features/listen-udp.feature | 12 +++++++++--- tests/features/tcp.feature | 4 +++- tests/features/udp.feature | 5 +++-- 10 files changed, 70 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 8becc91..5d3377c 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ and/or environment variables. All available flags can be seen by running `cyn --help`. This README snippet should have the latest, but when in doubt, just run the command to check. -```bash +```text $ cyn --help Usage: [flags] @@ -130,6 +130,7 @@ Flags: -c, --config string A file path to load as additional configuration. -h, --help help for this command --http.address string An address:port to host an HTTP server on for realtime data, such as '127.0.0.1:8080' + -e, --listen.echo If enabled, echo the data that's received. Otherwise just print the length received (default). -t, --listen.tcp strings An IP:port address to listen on for TCP. Can be specified multiple times. -u, --listen.udp strings An IP:port address to listen on for UDP. Can be specified multiple times. -d, --send.data string The string data to send. (default "hi") @@ -161,6 +162,7 @@ A full configuration file with all options is given below. ```yaml # my-cyn-config.yaml listen: + echo: true udp: - 192.168.58.4:2345 tcp: diff --git a/cmd/cyn/cmds/root.go b/cmd/cyn/cmds/root.go index 47f4d59..6d8e6e4 100644 --- a/cmd/cyn/cmds/root.go +++ b/cmd/cyn/cmds/root.go @@ -18,8 +18,9 @@ import ( var config struct { Listen struct { - Udp []string `mapstructure:"udp"` - Tcp []string `mapstructure:"tcp"` + Udp []string `mapstructure:"udp"` + Tcp []string `mapstructure:"tcp"` + Echo bool `mapstructure:"echo"` } `mapstructure:"listen"` Send struct { @@ -55,6 +56,7 @@ func init() { flags.StringSliceP("listen.udp", "u", nil, "An IP:port address to listen on for UDP. Can be specified multiple times.") flags.StringSliceP("listen.tcp", "t", nil, "An IP:port address to listen on for TCP. Can be specified multiple times.") + flags.BoolP("listen.echo", "e", false, "If enabled, echo the data that's received. Otherwise just print the length received (default).") flags.StringSliceP("send.udp", "U", nil, "An IP:port address to send to (UDP). Can be specified multiple times.") flags.StringSliceP("send.tcp", "T", nil, "An IP:port address to send to (TCP). Can be specified multiple times.") flags.StringP("send.data", "d", "hi", "The string data to send.") @@ -113,7 +115,9 @@ var rootCmd = &cobra.Command{ return fmt.Errorf("net.ResolveUDPAddr for %q: %w", listenOnUDP, err) } - instance.AddUDPListener(listener.NewUDP(*addr)) + instance.AddUDPListener(listener.NewUDP(*addr, listener.UdpConfig{ + Echo: config.Listen.Echo, + })) } for _, listenOnTCP := range config.Listen.Tcp { @@ -123,7 +127,9 @@ var rootCmd = &cobra.Command{ return fmt.Errorf("net.ResolveTCPAddr for %q: %w", listenOnTCP, err) } - instance.AddTCPListener(listener.NewTCP(*addr)) + instance.AddTCPListener(listener.NewTCP(*addr, listener.TcpConfig{ + Echo: config.Listen.Echo, + })) } for _, sendUDPTo := range config.Send.Udp { diff --git a/pkg/cyn/cyn.go b/pkg/cyn/cyn.go index d17a183..9e3c5d2 100644 --- a/pkg/cyn/cyn.go +++ b/pkg/cyn/cyn.go @@ -11,8 +11,8 @@ import ( type Cyn struct { mu sync.RWMutex - tcpListeners []*listener.TCPListener - udpListeners []*listener.UDPListener + tcpListeners []*listener.TcpListener + udpListeners []*listener.UdpListener tcpSenders []*sender.TCPSender udpSenders []*sender.UDPSender @@ -23,33 +23,33 @@ func New() *Cyn { return &Cyn{} } -func (c *Cyn) AddTCPListener(tcpListener *listener.TCPListener) { +func (c *Cyn) AddTCPListener(tcpListener *listener.TcpListener) { c.mu.Lock() c.tcpListeners = append(c.tcpListeners, tcpListener) c.mu.Unlock() } -func (c *Cyn) TCPListeners() []*listener.TCPListener { +func (c *Cyn) TCPListeners() []*listener.TcpListener { c.mu.RLock() defer c.mu.RUnlock() - listeners := make([]*listener.TCPListener, len(c.tcpListeners)) + listeners := make([]*listener.TcpListener, len(c.tcpListeners)) copy(listeners, c.tcpListeners) return listeners } -func (c *Cyn) AddUDPListener(udpListener *listener.UDPListener) { +func (c *Cyn) AddUDPListener(udpListener *listener.UdpListener) { c.mu.Lock() c.udpListeners = append(c.udpListeners, udpListener) c.mu.Unlock() } -func (c *Cyn) UDPListeners() []*listener.UDPListener { +func (c *Cyn) UDPListeners() []*listener.UdpListener { c.mu.RLock() defer c.mu.RUnlock() - listeners := make([]*listener.UDPListener, len(c.udpListeners)) + listeners := make([]*listener.UdpListener, len(c.udpListeners)) copy(listeners, c.udpListeners) return listeners diff --git a/pkg/httpserver/server.go b/pkg/httpserver/server.go index dedc2dc..2d85135 100644 --- a/pkg/httpserver/server.go +++ b/pkg/httpserver/server.go @@ -13,8 +13,8 @@ type Server struct { } type OverallStatusGetter interface { - TCPListeners() []*listener.TCPListener - UDPListeners() []*listener.UDPListener + TCPListeners() []*listener.TcpListener + UDPListeners() []*listener.UdpListener } func NewServer(addr string, statusGetter OverallStatusGetter) *Server { diff --git a/pkg/listener/tcp.go b/pkg/listener/tcp.go index 180b7a9..fb73e08 100644 --- a/pkg/listener/tcp.go +++ b/pkg/listener/tcp.go @@ -11,25 +11,31 @@ import ( "github.com/evertras/cynomys/pkg/constants" ) -type TCPListener struct { +type TcpListener struct { mu sync.RWMutex addr net.TCPAddr + cfg TcpConfig } -func NewTCP(addr net.TCPAddr) *TCPListener { - return &TCPListener{ +type TcpConfig struct { + Echo bool +} + +func NewTCP(addr net.TCPAddr, cfg TcpConfig) *TcpListener { + return &TcpListener{ addr: addr, + cfg: cfg, } } -func (l *TCPListener) Addr() string { +func (l *TcpListener) Addr() string { l.mu.RLock() defer l.mu.RUnlock() return l.addr.String() } -func (l *TCPListener) Listen() error { +func (l *TcpListener) Listen() error { l.mu.RLock() listener, err := net.ListenTCP("tcp", &l.addr) l.mu.RUnlock() @@ -76,7 +82,10 @@ func (l *TCPListener) Listen() error { } log.Printf("Read %d bytes from %v", rlen, remote) - log.Printf("Received: %s", strings.ReplaceAll(string(buf), "\n", "\\n")) + + if l.cfg.Echo { + log.Printf("Received: %s", strings.ReplaceAll(string(buf), "\n", "\\n")) + } } log.Printf("TCP disconnected from %s", remote) diff --git a/pkg/listener/udp.go b/pkg/listener/udp.go index b64a3ed..a375082 100644 --- a/pkg/listener/udp.go +++ b/pkg/listener/udp.go @@ -10,25 +10,31 @@ import ( "github.com/evertras/cynomys/pkg/constants" ) -type UDPListener struct { +type UdpListener struct { mu sync.RWMutex addr net.UDPAddr + cfg UdpConfig } -func NewUDP(addr net.UDPAddr) *UDPListener { - return &UDPListener{ +type UdpConfig struct { + Echo bool +} + +func NewUDP(addr net.UDPAddr, cfg UdpConfig) *UdpListener { + return &UdpListener{ addr: addr, + cfg: cfg, } } -func (l *UDPListener) Addr() string { +func (l *UdpListener) Addr() string { l.mu.RLock() defer l.mu.RUnlock() return l.addr.String() } -func (l *UDPListener) Listen() error { +func (l *UdpListener) Listen() error { l.mu.RLock() conn, err := net.ListenUDP("udp", &l.addr) l.mu.RUnlock() @@ -55,6 +61,9 @@ func (l *UDPListener) Listen() error { } log.Printf("Read %d bytes from %v", rlen, remote) - log.Printf("Received: %s", strings.ReplaceAll(string(buf), "\n", "\\n")) + + if l.cfg.Echo { + log.Printf("Received: %s", strings.ReplaceAll(string(buf), "\n", "\\n")) + } } } diff --git a/tests/features/listen-tcp.feature b/tests/features/listen-tcp.feature index eb70c6c..1c6b7b0 100644 --- a/tests/features/listen-tcp.feature +++ b/tests/features/listen-tcp.feature @@ -23,7 +23,7 @@ Feature: listen for TCP And the stdout contains "TCP disconnected" Scenario: a TCP connection is made and data is sent (shorthand flag) - Given I run cyn -t 127.0.0.1:24565 + Given I run cyn -t 127.0.0.1:24565 -e When I connect with TCP to 127.0.0.1:24565 And I send "my tcp stuff" over my TCP connection And I wait a moment @@ -34,6 +34,7 @@ Feature: listen for TCP Given a configuration file that contains: """ listen: + echo: true tcp: - 127.0.0.1:14568 """ diff --git a/tests/features/listen-udp.feature b/tests/features/listen-udp.feature index cdc2b83..32cacf2 100644 --- a/tests/features/listen-udp.feature +++ b/tests/features/listen-udp.feature @@ -4,17 +4,22 @@ Feature: listen for UDP Scenario: nothing is sent #Given cyn is listening for UDP on 127.0.0.1:14563 - Given I run cyn --listen.udp 127.0.0.1:14563 + Given I run cyn --listen.udp 127.0.0.1:14563 -e When I wait 1 second Then there is no output Scenario: a single UDP packet is sent - Given I run cyn --listen.udp 127.0.0.1:14564 + Given I run cyn --listen.udp 127.0.0.1:14564 --listen.echo When I send a UDP packet containing "hello" to 127.0.0.1:14564 Then the stdout contains "hello" + Scenario: a single UDP packet is sent but listen.echoecho is not defined + Given I run cyn --listen.udp 127.0.0.1:14564 + When I send a UDP packet containing "hello" to 127.0.0.1:14564 + Then the stdout does not contain "hello" + Scenario: multiple UDP packets are sent (shorthand flag) - Given I run cyn -u 127.0.0.1:14564 + Given I run cyn -u 127.0.0.1:14564 -e When I send a UDP packet containing "hello" to 127.0.0.1:14564 And I send a UDP packet containing "another" to 127.0.0.1:14564 Then the stdout contains "hello" @@ -24,6 +29,7 @@ Feature: listen for UDP Given a configuration file that contains: """ listen: + echo: true udp: - 127.0.0.1:14568 """ diff --git a/tests/features/tcp.feature b/tests/features/tcp.feature index eb7684b..6e1015e 100644 --- a/tests/features/tcp.feature +++ b/tests/features/tcp.feature @@ -8,7 +8,7 @@ Feature: send and receive TCP Then the stdout contains "connection refused" Scenario: one listen one send (shorthand flags) - Given I run cyn -t 127.0.0.1:15235 + Given I run cyn -t 127.0.0.1:15235 -e And I run cyn -T 127.0.0.1:15235 -i 10ms When I wait a moment Then the stdout contains "connected" @@ -38,6 +38,7 @@ Feature: send and receive TCP Given a configuration file that contains: """ listen: + echo: true tcp: - 127.0.0.1:24568 send: @@ -53,6 +54,7 @@ Feature: send and receive TCP Given a configuration file that contains: """ listen: + echo: true tcp: - 127.0.0.1:24568 send: diff --git a/tests/features/udp.feature b/tests/features/udp.feature index f29796f..141b13a 100644 --- a/tests/features/udp.feature +++ b/tests/features/udp.feature @@ -3,13 +3,13 @@ Feature: send and receive UDP Cyn should both send and receive UDP packets Scenario: one listen one send to nothing - Given I run cyn --listen-udp 127.0.0.1:14563 + Given I run cyn --listen-udp 127.0.0.1:14563 --listen.echo And I run cyn --send.udp 127.0.0.1:14568 --send.interval 10ms When I wait a moment Then the stdout contains "connection refused" Scenario: one listen one send (shorthand flags) - Given I run cyn -u 127.0.0.1:14563 + Given I run cyn -u 127.0.0.1:14563 -e And I run cyn -U 127.0.0.1:14563 -i 10ms -d "bdd-test-data" When I wait a moment Then the stdout contains "bdd-test-data" @@ -26,6 +26,7 @@ Feature: send and receive UDP listen: udp: - 127.0.0.1:14568 + echo: true send: udp: - 127.0.0.1:14568