WIP: test (+ more todos)

This commit is contained in:
Suyono 2025-05-11 13:02:54 +10:00
parent 9eeda34e19
commit 72745cf268
4 changed files with 104 additions and 43 deletions

View File

@ -19,11 +19,12 @@ package main
import (
"context"
"fmt"
"golang.org/x/sys/unix"
"net"
"os/signal"
"time"
"golang.org/x/sys/unix"
"gitea.suyono.dev/suyono/netbounce/cmd/slicewriter"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
@ -38,7 +39,7 @@ func main() {
defer cancel()
parseFlags()
log.Debug().Msgf("Sending messages to %s server: %s", viper.GetString(PROTOCOL), viper.GetString(SERVER))
log.Debug().Caller().Msgf("Sending messages to %s server: %s", viper.GetString(PROTOCOL), viper.GetString(SERVER))
sendMessages(ctx)
}
@ -50,6 +51,7 @@ const (
NAME = "name"
MESSAGE = "message"
SLEEP = "sleep"
READTIMEOUT = "read-timeout"
)
func sendMessages(ctx context.Context) {
@ -59,7 +61,7 @@ func sendMessages(ctx context.Context) {
case "tcp":
sendTCP(ctx)
default:
log.Fatal().Str(PROTOCOL, viper.GetString(PROTOCOL)).Msg("Unknown protocol")
log.Fatal().Caller().Str(PROTOCOL, viper.GetString(PROTOCOL)).Msg("Unknown protocol")
}
}
@ -72,7 +74,7 @@ func sendTCP(ctx context.Context) {
)
if conn, err = net.Dial(TCP, viper.GetString(SERVER)); err != nil {
log.Fatal().Err(err).Msg("Failed to connect to server")
log.Fatal().Caller().Err(err).Msg("Failed to connect to server")
}
defer func() {
_ = conn.Close()
@ -86,18 +88,21 @@ func sendTCP(ctx context.Context) {
for gLimit.isContinue(ctx) {
sb := slicewriter.NewSliceWriter(buf)
if _, err = fmt.Fprintf(sb, "client %s | %v | %s", viper.GetString(NAME), time.Now(), viper.GetString(MESSAGE)); err != nil {
log.Fatal().Err(err).Msg("Failed to build client message")
log.Fatal().Caller().Err(err).Msg("Failed to build client message")
}
b = sb.Bytes()
if _, err = conn.Write(b); err != nil {
log.Fatal().Err(err).Str(PROTOCOL, TCP).Str(SERVER, viper.GetString(SERVER)).Msg("Failed to send client message")
log.Fatal().Caller().Err(err).Str(PROTOCOL, TCP).Str(SERVER, viper.GetString(SERVER)).Msg("Failed to send client message")
}
if err = conn.SetReadDeadline(time.Now().Add(viper.GetDuration(READTIMEOUT))); err != nil {
log.Fatal().Caller().Err(err).Str(PROTOCOL, TCP).Str(SERVER, viper.GetString(SERVER)).Msg("Failed to send client message")
}
if n, err = conn.Read(buf); err != nil {
log.Fatal().Err(err).Str(PROTOCOL, TCP).Str(SERVER, viper.GetString(SERVER)).Msg("read from the server")
log.Fatal().Caller().Err(err).Str(PROTOCOL, TCP).Str(SERVER, viper.GetString(SERVER)).Msg("read from the server")
}
log.Info().Str(PROTOCOL, TCP).Str(SERVER, viper.GetString(SERVER)).Msgf("%s", buf[:n])
log.Info().Caller().Str(PROTOCOL, TCP).Str(SERVER, viper.GetString(SERVER)).Msgf("%s", buf[:n])
time.Sleep(viper.GetDuration(SLEEP))
}
@ -105,7 +110,7 @@ func sendTCP(ctx context.Context) {
func sendUDP(ctx context.Context) {
var (
addr *net.UDPAddr
addr, laddr *net.UDPAddr
conn *net.UDPConn
rAddr net.Addr
err error
@ -114,12 +119,20 @@ func sendUDP(ctx context.Context) {
)
if addr, err = net.ResolveUDPAddr(UDP, viper.GetString(SERVER)); err != nil {
log.Fatal().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("udp resolve address")
log.Fatal().Caller().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("udp resolve server address")
}
if conn, err = net.DialUDP(UDP, nil, addr); err != nil {
log.Fatal().Err(err).Str("server", viper.GetString(SERVER)).Msg("dial server udp")
if laddr, err = net.ResolveUDPAddr(UDP, ""); err != nil {
log.Fatal().Caller().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("udp resolve local/self address")
}
//TODO: log address to be bound by client
//TODO: use un-connected socket of UDP, replace all net.DialUDP() with net.ListenUDP()
// In Go, binding for UDP using ListenUDP. Confusing!!
if conn, err = net.ListenUDP(UDP, laddr); err != nil {
log.Fatal().Caller().Err(err).Str(SERVER, viper.GetString(SERVER)).Msg("fail to bind local/self address")
}
defer func() {
_ = conn.Close()
}()
@ -132,24 +145,28 @@ func sendUDP(ctx context.Context) {
for gLimit.isContinue(ctx) {
sb := slicewriter.NewSliceWriter(buf)
if _, err = fmt.Fprintf(sb, "client %s | %v | %s", viper.GetString(NAME), time.Now(), viper.GetString(MESSAGE)); err != nil {
log.Fatal().Err(err).Msg("Failed to build client message")
log.Fatal().Caller().Err(err).Msg("Failed to build client message")
}
b = sb.Bytes()
if _, err = conn.WriteTo(b, addr); err != nil {
log.Fatal().Err(err).Str(PROTOCOL, UDP).Str(SERVER, viper.GetString(SERVER)).Msg("Failed to send client message")
log.Fatal().Caller().Err(err).Str(PROTOCOL, UDP).Str(SERVER, viper.GetString(SERVER)).Msg("Failed to send client message")
}
if err = conn.SetReadDeadline(time.Now().Add(viper.GetDuration(READTIMEOUT))); err != nil {
log.Error().Caller().Err(err).Str(PROTOCOL, UDP).Str(SERVER, viper.GetString(SERVER)).Msg("set read timeout on the socket")
}
if n, rAddr, err = conn.ReadFrom(b); err != nil {
log.Fatal().Err(err).Str(PROTOCOL, UDP).Str(SERVER, viper.GetString(SERVER)).Msg("read from server")
log.Fatal().Caller().Err(err).Str(PROTOCOL, UDP).Str(SERVER, viper.GetString(SERVER)).Msg("read from server")
}
log.Info().Str(PROTOCOL, UDP).Str(SERVER, rAddr.String()).Msgf("%s", buf[:n])
log.Info().Caller().Str(PROTOCOL, UDP).Str(SERVER, rAddr.String()).Msgf("%s", buf[:n])
}
}
func parseFlags() {
pflag.String(NAME, "", "client name")
pflag.IntP("number", "n", 5, "number of messages to send; default 5; set to 0 for infinite")
pflag.Duration(READTIMEOUT, 5*time.Second, "read timeout; default 5 seconds")
pflag.DurationP(SLEEP, "s", 10*time.Millisecond, "sleep time between requests; default 10ms")
pflag.StringP(MESSAGE, "m", "message from client", "message to send")
pflag.Bool("debug", false, "run in debug mode")
@ -162,15 +179,15 @@ func parseFlags() {
gLimit = makeCounter(viper.GetInt("number"))
if !viper.IsSet(NAME) {
log.Fatal().Msg("server name is required")
log.Fatal().Caller().Msg("server name is required")
}
if viper.IsSet(TCP) && viper.IsSet(UDP) {
log.Fatal().Msg("cannot use tcp and udp at once")
log.Fatal().Caller().Msg("cannot use tcp and udp at once")
}
if !viper.IsSet(TCP) && !viper.IsSet(UDP) {
log.Fatal().Msg("server address is required")
log.Fatal().Caller().Msg("--tcp or --udp is required, use one of them not both.")
}
if viper.IsSet(TCP) {
@ -198,7 +215,7 @@ func makeCounter(limit int) *counter {
log.Fatal().Msg("number must be > 0")
}
return &counter{limit: limit, tick: 0}
return &counter{limit: limit, tick: -1}
}
func (c *counter) isContinue(ctx context.Context) bool {
@ -213,9 +230,5 @@ func (c *counter) isContinue(ctx context.Context) bool {
}
c.tick++
if c.tick < c.limit {
return true
}
return false
return c.tick < c.limit
}

View File

@ -19,16 +19,17 @@ package main
import (
"context"
"fmt"
"net"
"os/signal"
"sync"
"time"
"gitea.suyono.dev/suyono/netbounce/cmd/slicewriter"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"golang.org/x/sys/unix"
"net"
"os/signal"
"sync"
"time"
)
func main() {
@ -43,6 +44,13 @@ func main() {
openPorts(wg, ctx)
wg.Wait()
select {
case <-ctx.Done():
log.Debug().Caller().Msg("received signal to quit")
default:
log.Debug().Caller().Msg("unexpected exit")
}
}
func parseFlags() {
@ -94,7 +102,7 @@ func bindUDP(ctx context.Context, wg *sync.WaitGroup, address string) {
addr net.Addr
)
log.Debug().Str("address", address).Msg("binding socket for UDP")
log.Debug().Caller().Msgf("binding socket for UDP on %v", address)
if conn, err = net.ListenPacket("udp", address); err != nil {
panic(fmt.Errorf("failed to bind udp address: %v", err))
}
@ -158,6 +166,7 @@ func listen(ctx context.Context, wg *sync.WaitGroup, address string) {
conn net.Conn
)
log.Debug().Caller().Msgf("listeng for TCP on %v", address)
if listener, err = net.Listen("tcp", address); err != nil {
log.Error().Err(err).Str("address", address).Msg("failed to listen")
return

View File

@ -0,0 +1,39 @@
name: bounce-test
services:
server:
build:
context: .
dockerfile: docker/Dockerfile-test-server
no_cache: true
tty: true
hostname: server
command: [
"/usr/local/bin/test-server", "--name", "server", "--debug",
"--udp", "0.0.0.0:10010",
"--tcp", "0.0.0.0:10020"
]
client-udp:
build:
context: .
dockerfile: docker/Dockerfile-test-client
no_cache: true
tty: true
hostname: client
command: [
"/usr/local/bin/test-client", "--debug", "--name", "client-udp",
"--udp", "server:10010"
]
client-tcp:
build:
context: .
dockerfile: docker/Dockerfile-test-client
no_cache: true
tty: true
hostname: client
command: [
"/usr/local/bin/test-client", "--debug", "--name", "client-tcp",
"--tcp", "server:10020"
]

View File

@ -8,4 +8,4 @@ FROM alpine:3.21
RUN apk add tzdata && ln -s /usr/share/zoneinfo/Australia/Sydney /etc/localtime
COPY --from=builder /go/test-client /usr/local/bin/test-client
CMD ["/usr/local/bin/test-server"]
CMD ["/usr/local/bin/test-client"]