Commit 450601f0 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Move ICE code into own module, add tests.

parent 845dccc2
......@@ -13,6 +13,7 @@ import (
"github.com/jech/galene/diskwriter"
"github.com/jech/galene/group"
"github.com/jech/galene/ice"
"github.com/jech/galene/webserver"
)
......@@ -39,7 +40,7 @@ func main() {
flag.StringVar(&mutexprofile, "mutexprofile", "",
"store mutex profile in `file`")
flag.BoolVar(&group.UseMDNS, "mdns", false, "gather mDNS addresses")
flag.BoolVar(&group.ICERelayOnly, "relay-only", false,
flag.BoolVar(&ice.ICERelayOnly, "relay-only", false,
"require use of TURN relays for all media traffic")
flag.Parse()
......@@ -81,7 +82,7 @@ func main() {
}()
}
group.ICEFilename = filepath.Join(dataDir, "ice-servers.json")
ice.ICEFilename = filepath.Join(dataDir, "ice-servers.json")
go group.ReadPublicGroups()
......
package group
package ice
import (
"bytes"
......@@ -16,14 +16,14 @@ import (
"github.com/pion/webrtc/v3"
)
type ICEServer struct {
type Server struct {
URLs []string `json:"urls"`
Username string `json:"username,omitempty"`
Credential interface{} `json:"credential,omitempty"`
CredentialType string `json:"credentialType,omitempty"`
}
func getICEServer(server ICEServer) (webrtc.ICEServer, error) {
func getServer(server Server) (webrtc.ICEServer, error) {
s := webrtc.ICEServer{
URLs: server.URLs,
Username: server.Username,
......@@ -65,16 +65,16 @@ func getICEServer(server ICEServer) (webrtc.ICEServer, error) {
var ICEFilename string
var ICERelayOnly bool
type iceConf struct {
type configuration struct {
conf webrtc.Configuration
timestamp time.Time
}
var iceConfiguration atomic.Value
var conf atomic.Value
func updateICEConfiguration() *iceConf {
func updateICEConfiguration() *configuration {
now := time.Now()
var conf webrtc.Configuration
var cf webrtc.Configuration
if ICEFilename != "" {
file, err := os.Open(ICEFilename)
......@@ -83,36 +83,36 @@ func updateICEConfiguration() *iceConf {
} else {
defer file.Close()
d := json.NewDecoder(file)
var servers []ICEServer
var servers []Server
err = d.Decode(&servers)
if err != nil {
log.Printf("Get ICE configuration: %v", err)
}
for _, s := range servers {
ss, err := getICEServer(s)
ss, err := getServer(s)
if err != nil {
log.Printf("parse ICE server: %v", err)
continue
}
conf.ICEServers = append(conf.ICEServers, ss)
cf.ICEServers = append(cf.ICEServers, ss)
}
}
}
if ICERelayOnly {
conf.ICETransportPolicy = webrtc.ICETransportPolicyRelay
cf.ICETransportPolicy = webrtc.ICETransportPolicyRelay
}
iceConf := iceConf{
conf: conf,
iceConf := configuration{
conf: cf,
timestamp: now,
}
iceConfiguration.Store(&iceConf)
conf.Store(&iceConf)
return &iceConf
}
func ICEConfiguration() *webrtc.Configuration {
conf, ok := iceConfiguration.Load().(*iceConf)
conf, ok := conf.Load().(*configuration)
if !ok || time.Since(conf.timestamp) > 5*time.Minute {
conf = updateICEConfiguration()
} else if time.Since(conf.timestamp) > 2*time.Minute {
......
package ice
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"reflect"
"strings"
"testing"
"github.com/pion/webrtc/v3"
)
func TestPassword(t *testing.T) {
s := Server{
URLs: []string{"turn:turn.example.org"},
Username: "jch",
Credential: "secret",
}
ss := webrtc.ICEServer{
URLs: []string{"turn:turn.example.org"},
Username: "jch",
Credential: "secret",
}
sss, err := getServer(s)
if err != nil || !reflect.DeepEqual(sss, ss) {
t.Errorf("Got %v, expected %v", sss, ss)
}
}
func TestHMAC(t *testing.T) {
s := Server{
URLs: []string{"turn:turn.example.org"},
Username: "jch",
Credential: "secret",
CredentialType: "hmac-sha1",
}
ss := webrtc.ICEServer{
URLs: []string{"turn:turn.example.org"},
}
sss, err := getServer(s)
if !strings.HasSuffix(sss.Username, ":"+s.Username) {
t.Errorf("username is %v", ss.Username)
}
ss.Username = sss.Username
mac := hmac.New(sha1.New, []byte(s.Credential.(string)))
mac.Write([]byte(sss.Username))
buf := bytes.Buffer{}
e := base64.NewEncoder(base64.StdEncoding, &buf)
e.Write(mac.Sum(nil))
e.Close()
ss.Credential = string(buf.Bytes())
if err != nil || !reflect.DeepEqual(sss, ss) {
t.Errorf("Got %v, expected %v", sss, ss)
}
}
......@@ -16,6 +16,7 @@ import (
"github.com/jech/galene/conn"
"github.com/jech/galene/estimator"
"github.com/jech/galene/group"
"github.com/jech/galene/ice"
"github.com/jech/galene/jitter"
"github.com/jech/galene/packetcache"
"github.com/jech/galene/rtptime"
......@@ -138,7 +139,7 @@ type rtpDownConnection struct {
func newDownConn(c group.Client, id string, remote conn.Up) (*rtpDownConnection, error) {
api := group.APIFromCodecs(remote.Codecs())
pc, err := api.NewPeerConnection(*group.ICEConfiguration())
pc, err := api.NewPeerConnection(*ice.ICEConfiguration())
if err != nil {
return nil, err
}
......@@ -457,7 +458,7 @@ func pushConn(up *rtpUpConnection, g *group.Group, cs []group.Client) {
}
func newUpConn(c group.Client, id string, labels map[string]string) (*rtpUpConnection, error) {
pc, err := c.Group().API().NewPeerConnection(*group.ICEConfiguration())
pc, err := c.Group().API().NewPeerConnection(*ice.ICEConfiguration())
if err != nil {
return nil, err
}
......
......@@ -16,6 +16,7 @@ import (
"github.com/jech/galene/diskwriter"
"github.com/jech/galene/estimator"
"github.com/jech/galene/group"
"github.com/jech/galene/ice"
)
func errorToWSCloseMessage(id string, err error) (*clientMessage, []byte) {
......@@ -877,7 +878,7 @@ func clientLoop(c *webClient, ws *websocket.Conn) error {
Kind: "change",
Group: g.Name(),
Permissions: &perms,
RTCConfiguration: group.ICEConfiguration(),
RTCConfiguration: ice.ICEConfiguration(),
})
if !c.permissions.Present {
up := getUpConns(c)
......@@ -1084,7 +1085,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
Kind: "join",
Group: m.Group,
Permissions: &perms,
RTCConfiguration: group.ICEConfiguration(),
RTCConfiguration: ice.ICEConfiguration(),
})
if err != nil {
return err
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment