mirror of
https://github.com/jech/galene.git
synced 2024-11-22 16:45:58 +01:00
Move ICE code into own module, add tests.
This commit is contained in:
parent
845dccc2bb
commit
450601f0e8
5 changed files with 89 additions and 21 deletions
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/jech/galene/diskwriter"
|
"github.com/jech/galene/diskwriter"
|
||||||
"github.com/jech/galene/group"
|
"github.com/jech/galene/group"
|
||||||
|
"github.com/jech/galene/ice"
|
||||||
"github.com/jech/galene/webserver"
|
"github.com/jech/galene/webserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ func main() {
|
||||||
flag.StringVar(&mutexprofile, "mutexprofile", "",
|
flag.StringVar(&mutexprofile, "mutexprofile", "",
|
||||||
"store mutex profile in `file`")
|
"store mutex profile in `file`")
|
||||||
flag.BoolVar(&group.UseMDNS, "mdns", false, "gather mDNS addresses")
|
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")
|
"require use of TURN relays for all media traffic")
|
||||||
flag.Parse()
|
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()
|
go group.ReadPublicGroups()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package group
|
package ice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -16,14 +16,14 @@ import (
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ICEServer struct {
|
type Server struct {
|
||||||
URLs []string `json:"urls"`
|
URLs []string `json:"urls"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Credential interface{} `json:"credential,omitempty"`
|
Credential interface{} `json:"credential,omitempty"`
|
||||||
CredentialType string `json:"credentialType,omitempty"`
|
CredentialType string `json:"credentialType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getICEServer(server ICEServer) (webrtc.ICEServer, error) {
|
func getServer(server Server) (webrtc.ICEServer, error) {
|
||||||
s := webrtc.ICEServer{
|
s := webrtc.ICEServer{
|
||||||
URLs: server.URLs,
|
URLs: server.URLs,
|
||||||
Username: server.Username,
|
Username: server.Username,
|
||||||
|
@ -65,16 +65,16 @@ func getICEServer(server ICEServer) (webrtc.ICEServer, error) {
|
||||||
var ICEFilename string
|
var ICEFilename string
|
||||||
var ICERelayOnly bool
|
var ICERelayOnly bool
|
||||||
|
|
||||||
type iceConf struct {
|
type configuration struct {
|
||||||
conf webrtc.Configuration
|
conf webrtc.Configuration
|
||||||
timestamp time.Time
|
timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
var iceConfiguration atomic.Value
|
var conf atomic.Value
|
||||||
|
|
||||||
func updateICEConfiguration() *iceConf {
|
func updateICEConfiguration() *configuration {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
var conf webrtc.Configuration
|
var cf webrtc.Configuration
|
||||||
|
|
||||||
if ICEFilename != "" {
|
if ICEFilename != "" {
|
||||||
file, err := os.Open(ICEFilename)
|
file, err := os.Open(ICEFilename)
|
||||||
|
@ -83,36 +83,36 @@ func updateICEConfiguration() *iceConf {
|
||||||
} else {
|
} else {
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
d := json.NewDecoder(file)
|
d := json.NewDecoder(file)
|
||||||
var servers []ICEServer
|
var servers []Server
|
||||||
err = d.Decode(&servers)
|
err = d.Decode(&servers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Get ICE configuration: %v", err)
|
log.Printf("Get ICE configuration: %v", err)
|
||||||
}
|
}
|
||||||
for _, s := range servers {
|
for _, s := range servers {
|
||||||
ss, err := getICEServer(s)
|
ss, err := getServer(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("parse ICE server: %v", err)
|
log.Printf("parse ICE server: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
conf.ICEServers = append(conf.ICEServers, ss)
|
cf.ICEServers = append(cf.ICEServers, ss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ICERelayOnly {
|
if ICERelayOnly {
|
||||||
conf.ICETransportPolicy = webrtc.ICETransportPolicyRelay
|
cf.ICETransportPolicy = webrtc.ICETransportPolicyRelay
|
||||||
}
|
}
|
||||||
|
|
||||||
iceConf := iceConf{
|
iceConf := configuration{
|
||||||
conf: conf,
|
conf: cf,
|
||||||
timestamp: now,
|
timestamp: now,
|
||||||
}
|
}
|
||||||
iceConfiguration.Store(&iceConf)
|
conf.Store(&iceConf)
|
||||||
return &iceConf
|
return &iceConf
|
||||||
}
|
}
|
||||||
|
|
||||||
func ICEConfiguration() *webrtc.Configuration {
|
func ICEConfiguration() *webrtc.Configuration {
|
||||||
conf, ok := iceConfiguration.Load().(*iceConf)
|
conf, ok := conf.Load().(*configuration)
|
||||||
if !ok || time.Since(conf.timestamp) > 5*time.Minute {
|
if !ok || time.Since(conf.timestamp) > 5*time.Minute {
|
||||||
conf = updateICEConfiguration()
|
conf = updateICEConfiguration()
|
||||||
} else if time.Since(conf.timestamp) > 2*time.Minute {
|
} else if time.Since(conf.timestamp) > 2*time.Minute {
|
65
ice/ice_test.go
Normal file
65
ice/ice_test.go
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
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/conn"
|
||||||
"github.com/jech/galene/estimator"
|
"github.com/jech/galene/estimator"
|
||||||
"github.com/jech/galene/group"
|
"github.com/jech/galene/group"
|
||||||
|
"github.com/jech/galene/ice"
|
||||||
"github.com/jech/galene/jitter"
|
"github.com/jech/galene/jitter"
|
||||||
"github.com/jech/galene/packetcache"
|
"github.com/jech/galene/packetcache"
|
||||||
"github.com/jech/galene/rtptime"
|
"github.com/jech/galene/rtptime"
|
||||||
|
@ -138,7 +139,7 @@ type rtpDownConnection struct {
|
||||||
|
|
||||||
func newDownConn(c group.Client, id string, remote conn.Up) (*rtpDownConnection, error) {
|
func newDownConn(c group.Client, id string, remote conn.Up) (*rtpDownConnection, error) {
|
||||||
api := group.APIFromCodecs(remote.Codecs())
|
api := group.APIFromCodecs(remote.Codecs())
|
||||||
pc, err := api.NewPeerConnection(*group.ICEConfiguration())
|
pc, err := api.NewPeerConnection(*ice.ICEConfiguration())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/jech/galene/diskwriter"
|
"github.com/jech/galene/diskwriter"
|
||||||
"github.com/jech/galene/estimator"
|
"github.com/jech/galene/estimator"
|
||||||
"github.com/jech/galene/group"
|
"github.com/jech/galene/group"
|
||||||
|
"github.com/jech/galene/ice"
|
||||||
)
|
)
|
||||||
|
|
||||||
func errorToWSCloseMessage(id string, err error) (*clientMessage, []byte) {
|
func errorToWSCloseMessage(id string, err error) (*clientMessage, []byte) {
|
||||||
|
@ -877,7 +878,7 @@ func clientLoop(c *webClient, ws *websocket.Conn) error {
|
||||||
Kind: "change",
|
Kind: "change",
|
||||||
Group: g.Name(),
|
Group: g.Name(),
|
||||||
Permissions: &perms,
|
Permissions: &perms,
|
||||||
RTCConfiguration: group.ICEConfiguration(),
|
RTCConfiguration: ice.ICEConfiguration(),
|
||||||
})
|
})
|
||||||
if !c.permissions.Present {
|
if !c.permissions.Present {
|
||||||
up := getUpConns(c)
|
up := getUpConns(c)
|
||||||
|
@ -1084,7 +1085,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
Kind: "join",
|
Kind: "join",
|
||||||
Group: m.Group,
|
Group: m.Group,
|
||||||
Permissions: &perms,
|
Permissions: &perms,
|
||||||
RTCConfiguration: group.ICEConfiguration(),
|
RTCConfiguration: ice.ICEConfiguration(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in a new issue