diff options
| author | Mel <einebeere@gmail.com> | 2023-08-23 04:31:47 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2023-08-23 04:31:47 +0200 |
| commit | f05272d9214e8fbb13ac55d0b133855464c5afc5 (patch) | |
| tree | fdebe999540f71af95a2115fc8a6c31d85904722 /bridge | |
| parent | 48b1e7fd8fb16daacd7b87f6bc6d422400cd0a5f (diff) | |
| download | cthcous-f05272d9214e8fbb13ac55d0b133855464c5afc5.tar.zst cthcous-f05272d9214e8fbb13ac55d0b133855464c5afc5.zip | |
Simple container bridge server
Diffstat (limited to 'bridge')
| -rw-r--r-- | bridge/main.go | 110 |
1 files changed, 108 insertions, 2 deletions
diff --git a/bridge/main.go b/bridge/main.go index 8a55772..1c70fdc 100644 --- a/bridge/main.go +++ b/bridge/main.go @@ -1,5 +1,111 @@ package main +import ( + "bytes" + "fmt" + "io" + "log/slog" + "net" + "os" + "strconv" +) + func main() { - println("hello!!!! this is the container bridge") -} \ No newline at end of file + slog.Info("starting container bridge...") + + info := getInfo() + slog.Info("got configuration from environment variables.", slog.Any("info", info)) + + source, err := net.Listen("tcp", fmt.Sprintf(":%d", info.Port)) + dieIfErr(err, "failed to listen on port.") + + slog.Info("listening...", slog.Uint64("port", uint64(info.Port))) + for { + conn, err := source.Accept() + if err != nil { + slog.Error("could not accept conenction.", slog.Any("error", err)) + continue + } + slog.Info("accepted connection.", slog.String("remoteAddr", conn.RemoteAddr().String())) + + go bridge(conn, info.SocketPath) + } +} + +func bridge(source net.Conn, socketPath string) { + data := bytes.NewBuffer([]byte{}) + for { + buffer := make([]byte, 1024) + n, err := source.Read(buffer) + if err != nil { + if err == io.EOF { + slog.Info("got EOF...", slog.String("remoteAddr", source.RemoteAddr().String())) + break + } + slog.Error("could not read from connection.", slog.Any("error", err)) + break + } + + n, err = data.Write(buffer[:n]) + if err != nil { + slog.Error("could not write to buffer.", slog.Any("error", err)) + break + } + } + source.Close() + slog.Info("connection completed. attempting write...", slog.String("remoteAddr", source.RemoteAddr().String())) + + destination, err := net.Dial("unix", socketPath) + if err != nil { + slog.Error("could not connect to destination socket.", slog.Any("error", err)) + return + } + defer destination.Close() + + _, err = destination.Write(data.Bytes()) + if err != nil { + slog.Error("could not write to destination socket.", slog.Any("error", err)) + return + } + + slog.Info("write to destination socket successful.", slog.String("remoteAddr", source.RemoteAddr().String())) +} + +type Info struct { + Port uint64 + SocketPath string +} + +func getInfo() Info { + portStr := os.Getenv("PORT") + if portStr == "" { + die("`PORT` environment variable must be set.") + } + + port, err := strconv.ParseUint(portStr, 10, 32) + dieIfErr(err, "could not parse `PORT` environment variable.") + + path := os.Getenv("SOCKET_PATH") + if path == "" { + defaultPath := fmt.Sprintf("/run/cthcous/%d.socket", port) + slog.Warn("`SOCKET_PATH` environment variable not set.", "default", string(defaultPath)) + } + + if _, err := os.Stat(path); os.IsNotExist(err) { + die(fmt.Sprintf("socket path `%s` does not exist.", path)) + } + + return Info{Port: port, SocketPath: path} +} + +func die(msg string) { + slog.Error(msg) + os.Exit(1) +} + +func dieIfErr(err error, msg string) { + if err != nil { + slog.Error(msg, slog.Any("error", err)) + os.Exit(1) + } +} |
