diff --git a/backend/services/controller/internal/ws/ws.go b/backend/services/controller/internal/ws/ws.go new file mode 100644 index 0000000..3e585bf --- /dev/null +++ b/backend/services/controller/internal/ws/ws.go @@ -0,0 +1,95 @@ +package ws + +import ( + "context" + "log" + "time" + + "github.com/gorilla/websocket" +) + +type Ws struct { + Addr string + Port string + Token string + Route string + Auth bool + TLS bool + Ctx context.Context +} + +const ( + WS_CONNECTION_RETRY = 10 * time.Second +) + +// Global Websocket connection used in this package +var wsConn *websocket.Conn + +func (w *Ws) Connect() { + + var wsUrl string + if w.Auth { + log.Println("WS token: ", w.Token) + // e.g. ws://localhost:8080/ws/controller?token=123456 + wsUrl = "ws://" + w.Addr + ":" + w.Port + w.Route + "?token=" + w.Token + } else { + // e.g. ws://localhost:8080/ws/controller + wsUrl = "ws://" + w.Addr + ":" + w.Port + w.Route + } + + // Keeps trying to connect to the WS endpoint until it succeeds or receives a stop signal + go func() { + for { + c, _, err := websocket.DefaultDialer.Dial(wsUrl, nil) + if err != nil { + log.Printf("Error to connect to %s, err: %s", wsUrl, err) + time.Sleep(WS_CONNECTION_RETRY) + continue + } + // instantiate global ws connection + wsConn = c + log.Println("Connected to WS endpoint--> ", wsUrl) + go w.Subscribe() + break + } + }() +} + +func (w *Ws) Disconnect() { + log.Println("Disconnecting from WS endpoint...") + + if wsConn != nil { + err := wsConn.Close() + if err != nil { + log.Println("Error while disconnecting from WS endpoint:", err.Error()) + } + log.Println("Succesfully disconnected from WS endpoint") + } else { + log.Println("No WS connection to close") + } +} + +// Websockets doesn't follow pub/sub architecture, but we use these +// naming here to implement the Broker interface and abstract the MTP layer. +/* -------------------------------------------------------------------------- */ + +func (w *Ws) Subscribe() { + for { + _, message, err := wsConn.ReadMessage() + if err != nil { + log.Println("read:", err) + return + } + log.Printf("recv: %s", message) + } +} + +func (w *Ws) Publish(msg []byte, topic, respTopic string, retain bool) { + err := wsConn.WriteMessage(websocket.TextMessage, msg) + if err != nil { + log.Println("write:", err) + return + } +} + +/* -------------------------------------------------------------------------- */