echo-web/bridge/main.go
2022-08-03 19:59:42 +01:00

113 lines
2.8 KiB
Go

package main
import (
echo "git.vh7.uk/jakew/echo-go"
"github.com/gorilla/websocket"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/samber/lo"
"gopkg.in/yaml.v3"
"io/ioutil"
"net/http"
"os"
)
type Config struct {
AllowedServers []string `yaml:"allowedServers"`
}
type websocketHandler struct {
config Config
}
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func (h *websocketHandler) socketHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Warn().Err(err).Msg("failed to upgrade connection")
return
}
defer conn.Close()
log.Info().Str("address", conn.RemoteAddr().String()).Msg("websocket connection opened")
server := r.URL.Query().Get("server")
username := r.URL.Query().Get("username")
password := r.URL.Query().Get("password")
if !lo.Contains[string](h.config.AllowedServers, server) {
_ = conn.WriteMessage(websocket.TextMessage, []byte("{\"error\": \"Server not allowed\"}"))
return
}
log.Info().Str("dest", server).Str("user", username).Msg("creating echo client")
client, err := echo.New(server, username)
if err != nil {
log.Error().Err(err).Msg("failed to create echo client")
_ = conn.WriteMessage(websocket.TextMessage, []byte("{\"error\": \"Failed to connect\"}"))
return
}
defer client.Disconnect()
err = client.HandshakeLoop(password)
if err != nil {
log.Error().Err(err).Msg("failed to handshake with server")
_ = conn.WriteMessage(websocket.TextMessage, []byte("{\"error\": \"Failed to connect\"}"))
return
}
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Warn().Err(err).Msg("failed to receive websocket message")
break
}
if messageType == websocket.CloseMessage {
break
} else if messageType == websocket.TextMessage {
err = conn.WriteMessage(messageType, message)
if err != nil {
log.Warn().Err(err).Msg("failed to send websocket message")
break
}
} else {
log.Warn().Int("type", messageType).Bytes("message", message).Msg("message type not implemented")
}
}
log.Info().Str("address", conn.RemoteAddr().String()).Msg("websocket connection closed")
}
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
log.Debug().Msg("loading config")
bytes, err := ioutil.ReadFile("config.yml")
if err != nil {
log.Fatal().Err(err).Msg("failed to load config file")
}
var config Config
err = yaml.Unmarshal(bytes, &config)
if err != nil {
log.Fatal().Err(err).Msg("failed to load config file")
}
handler := websocketHandler{
config: config,
}
http.HandleFunc("/", handler.socketHandler)
log.Info().Msg("starting server")
err = http.ListenAndServe(":4000", nil)
if err != nil {
log.Fatal().Err(err).Msg("failed to start server")
}
}