streamdeck-obs-replay/obsws/client_connection.go

94 lines
2.1 KiB
Go

package obsws
import (
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"github.com/gorilla/websocket"
)
// Connect opens a WebSocket connection and authenticates if necessary.
func (c *Client) Connect() error {
c.handlers = make(map[string]func(Event))
c.respQ = make(chan map[string]interface{}, bufferSize)
conn, err := connectWS(c.Host, c.Port)
if err != nil {
return err
}
c.conn = conn
// We can't use SendReceive yet because we haven't started polling.
reqGAR := NewGetAuthRequiredRequest()
if err = c.conn.WriteJSON(reqGAR); err != nil {
return err
}
respGAR := &GetAuthRequiredResponse{}
if err = c.conn.ReadJSON(respGAR); err != nil {
return err
}
if !respGAR.AuthRequired {
Logger.Println("logged in (no authentication required)")
c.connected = true
go c.poll()
return nil
}
auth := getAuth(c.Password, respGAR.Salt, respGAR.Challenge)
Logger.Println("auth:", auth)
reqA := NewAuthenticateRequest(auth)
if err = c.conn.WriteJSON(reqA); err != nil {
return err
}
respA := &AuthenticateResponse{}
if err = c.conn.ReadJSON(respA); err != nil {
return err
}
if respA.Status() != "ok" {
return errors.New(respA.Error())
}
Logger.Println("logged in (authentication successful)")
c.connected = true
go c.poll()
return nil
}
// Disconnect closes the WebSocket connection.
func (c *Client) Disconnect() error {
c.connected = false
if err := c.conn.Close(); err != nil {
return err
}
return nil
}
// connectWS opens the WebSocket connection.
func connectWS(host string, port int) (*websocket.Conn, error) {
url := fmt.Sprintf("ws://%s:%d", host, port)
Logger.Println("connecting to", url)
conn, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
return nil, err
}
return conn, nil
}
// getAuth computes the auth challenge response.
func getAuth(password, salt, challenge string) string {
sha := sha256.Sum256([]byte(password + salt))
b64 := base64.StdEncoding.EncodeToString([]byte(sha[:]))
sha = sha256.Sum256([]byte(b64 + challenge))
b64 = base64.StdEncoding.EncodeToString([]byte(sha[:]))
return b64
}