-
Notifications
You must be signed in to change notification settings - Fork 4
/
turn.go
115 lines (107 loc) · 3.19 KB
/
turn.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
"github.com/pion/webrtc/v3"
"github.com/twilio/twilio-go"
tapi "github.com/twilio/twilio-go/rest/api/v2010"
)
var now = time.Now
// ICEServer is used to represent a STUN or TURN server
type ICEServer struct {
Url string `redis:"url" json:"url,omitempty"`
Username string `redis:"username" json:"username,omitempyy"`
Credential string `redis:"-" json:"credential,omitempyy"`
Active bool `redis:"active" json:"-"`
Urls string `redis:"urls" json:"urls,omitempty"`
}
// genCredential returns a username and credential for a TURN server
// based on the username and the secret key
func genCredential(username string) (string, string) {
secretKey := os.Getenv("TURN_SECRET_KEY")
if secretKey == "" {
secretKey = "thisisatest"
}
h := hmac.New(sha1.New, []byte(secretKey))
timestamp := now().Add(24 * time.Hour).Unix()
compuser := fmt.Sprintf("%d:%s", timestamp, username)
_, _ = h.Write([]byte(compuser))
// return the compound username and the base64 encoded HMAC-SHA1
return compuser, base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// deprecated - use the webrtc connection instead
func serveICEServers(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Only the POST method is supported", http.StatusBadRequest)
return
}
servers, err := GetICEServers()
// return the JSON representation of the servers
if servers == nil {
servers = []webrtc.ICEServer{}
}
b, err := json.Marshal(servers)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to marshal servers: %s", err),
http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(b)
}
func getTwilio() ([]ICEServer, error) {
client := twilio.NewRestClient()
params := &tapi.CreateTokenParams{}
token, err := client.Api.CreateToken(params)
if err != nil {
return nil, err
}
var ret []ICEServer
for _, iceServer := range *token.IceServers {
ret = append(ret, ICEServer{
Url: iceServer.Url,
Urls: iceServer.Urls,
Username: iceServer.Username,
Credential: iceServer.Credential,
})
}
return ret, nil
}
// GetICEServers returns all the ICE servers from twilio
func GetICEServers() ([]webrtc.ICEServer, error) {
var iceservers []webrtc.ICEServer
servers, err := db.GetICEServers()
if err != nil {
Logger.Errorf("Failed to get ICE servers from db: %s", err)
} else {
// Add creredentials to the servers
for i, server := range servers {
servers[i].Username, servers[i].Credential = genCredential(server.Username)
}
}
if os.Getenv("TWILIO_AUTH_TOKEN") != "" {
twilioServers, err := getTwilio()
if err != nil {
Logger.Errorf("Failed to get ICE servers from twilio: %s", err)
} else {
servers = append(servers, twilioServers...)
}
} else {
Logger.Warn("TWILIO_AUTH_TOKEN not set, using local TURN servers: %v", servers)
}
for _, s := range servers {
iceservers = append(iceservers, webrtc.ICEServer{
URLs: []string{s.Urls},
Username: s.Username,
Credential: s.Credential,
CredentialType: webrtc.ICECredentialTypePassword,
})
}
return iceservers, nil
}