aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-08-23 04:31:47 +0200
committerMel <einebeere@gmail.com>2023-08-23 04:31:47 +0200
commitf05272d9214e8fbb13ac55d0b133855464c5afc5 (patch)
treefdebe999540f71af95a2115fc8a6c31d85904722
parent48b1e7fd8fb16daacd7b87f6bc6d422400cd0a5f (diff)
downloadcthcous-f05272d9214e8fbb13ac55d0b133855464c5afc5.tar.zst
cthcous-f05272d9214e8fbb13ac55d0b133855464c5afc5.zip
Simple container bridge server
-rw-r--r--.gitignore3
-rw-r--r--Taskfile.yml5
-rw-r--r--bridge/main.go110
3 files changed, 115 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index d163863..542a269 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-build/ \ No newline at end of file
+build/
+test.socket \ No newline at end of file
diff --git a/Taskfile.yml b/Taskfile.yml
index adda6eb..ec302d9 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -18,3 +18,8 @@ tasks:
deps: [build]
cmds:
- build/bridge
+
+ open-test-socket:
+ desc: "Opens and listens to `./test.socket`."
+ cmds:
+ - ncat -Ulk ./test.socket
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)
+ }
+}