This repository has been archived by the owner on Jan 14, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathclient_connection.go
93 lines (76 loc) · 2.06 KB
/
client_connection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
}