113 lines
2.8 KiB
Go
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")
|
|
}
|
|
}
|