mirror of
https://github.com/jech/galene.git
synced 2024-11-09 18:25:58 +01:00
Send RTC configuration with joined message.
This avoids one HTTP request, and is potentially more flexible.
This commit is contained in:
parent
d09c0f0a80
commit
a0418d26ec
8 changed files with 121 additions and 101 deletions
|
@ -1 +0,0 @@
|
|||
[]
|
|
@ -79,7 +79,7 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
group.IceFilename = filepath.Join(dataDir, "ice-servers.json")
|
||||
group.ICEFilename = filepath.Join(dataDir, "ice-servers.json")
|
||||
|
||||
go group.ReadPublicGroups()
|
||||
|
||||
|
|
|
@ -50,34 +50,6 @@ func (err ProtocolError) Error() string {
|
|||
return string(err)
|
||||
}
|
||||
|
||||
var IceFilename string
|
||||
|
||||
var iceConf webrtc.Configuration
|
||||
var iceOnce sync.Once
|
||||
|
||||
func IceConfiguration() webrtc.Configuration {
|
||||
iceOnce.Do(func() {
|
||||
var iceServers []webrtc.ICEServer
|
||||
file, err := os.Open(IceFilename)
|
||||
if err != nil {
|
||||
log.Printf("Open %v: %v", IceFilename, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
d := json.NewDecoder(file)
|
||||
err = d.Decode(&iceServers)
|
||||
if err != nil {
|
||||
log.Printf("Get ICE configuration: %v", err)
|
||||
return
|
||||
}
|
||||
iceConf = webrtc.Configuration{
|
||||
ICEServers: iceServers,
|
||||
}
|
||||
})
|
||||
|
||||
return iceConf
|
||||
}
|
||||
|
||||
type ChatHistoryEntry struct {
|
||||
Id string
|
||||
User string
|
||||
|
|
78
group/ice.go
Normal file
78
group/ice.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package group
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/pion/webrtc/v3"
|
||||
)
|
||||
|
||||
type ICEServer struct {
|
||||
URLs []string `json:"urls"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Credential interface{} `json:"credential,omitempty"`
|
||||
CredentialType string `json:"credentialType,omitempty"`
|
||||
}
|
||||
|
||||
type RTCConfiguration struct {
|
||||
ICEServers []ICEServer `json:"iceServers,omitempty"`
|
||||
ICETransportPolicy string `json:"iceTransportPolicy,omitempty"`
|
||||
}
|
||||
|
||||
var ICEFilename string
|
||||
|
||||
var iceConf RTCConfiguration
|
||||
var iceOnce sync.Once
|
||||
|
||||
func ICEConfiguration() *RTCConfiguration {
|
||||
iceOnce.Do(func() {
|
||||
var iceServers []ICEServer
|
||||
file, err := os.Open(ICEFilename)
|
||||
if err != nil {
|
||||
log.Printf("Open %v: %v", ICEFilename, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
d := json.NewDecoder(file)
|
||||
err = d.Decode(&iceServers)
|
||||
if err != nil {
|
||||
log.Printf("Get ICE configuration: %v", err)
|
||||
return
|
||||
}
|
||||
iceConf = RTCConfiguration{
|
||||
ICEServers: iceServers,
|
||||
}
|
||||
})
|
||||
|
||||
return &iceConf
|
||||
}
|
||||
|
||||
func ToConfiguration(conf *RTCConfiguration) webrtc.Configuration {
|
||||
var iceServers []webrtc.ICEServer
|
||||
for _, s := range conf.ICEServers {
|
||||
tpe := webrtc.ICECredentialTypePassword
|
||||
if s.CredentialType == "oauth" {
|
||||
tpe = webrtc.ICECredentialTypeOauth
|
||||
}
|
||||
iceServers = append(iceServers,
|
||||
webrtc.ICEServer{
|
||||
URLs: s.URLs,
|
||||
Username: s.Username,
|
||||
Credential: s.Credential,
|
||||
CredentialType: tpe,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
policy := webrtc.ICETransportPolicyAll
|
||||
if conf.ICETransportPolicy == "relay" {
|
||||
policy = webrtc.ICETransportPolicyRelay
|
||||
}
|
||||
|
||||
return webrtc.Configuration{
|
||||
ICEServers: iceServers,
|
||||
ICETransportPolicy: policy,
|
||||
}
|
||||
}
|
|
@ -138,7 +138,9 @@ 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(
|
||||
group.ToConfiguration(group.ICEConfiguration()),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -457,7 +459,9 @@ 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(
|
||||
group.ToConfiguration(group.ICEConfiguration()),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -161,22 +161,23 @@ func (v rateMap) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
type clientMessage struct {
|
||||
Type string `json:"type"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Id string `json:"id,omitempty"`
|
||||
Dest string `json:"dest,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Privileged bool `json:"privileged,omitempty"`
|
||||
Permissions *group.ClientPermissions `json:"permissions,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Value interface{} `json:"value,omitempty"`
|
||||
Time int64 `json:"time,omitempty"`
|
||||
Offer *webrtc.SessionDescription `json:"offer,omitempty"`
|
||||
Answer *webrtc.SessionDescription `json:"answer,omitempty"`
|
||||
Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Request rateMap `json:"request,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Id string `json:"id,omitempty"`
|
||||
Dest string `json:"dest,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Privileged bool `json:"privileged,omitempty"`
|
||||
Permissions *group.ClientPermissions `json:"permissions,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Value interface{} `json:"value,omitempty"`
|
||||
Time int64 `json:"time,omitempty"`
|
||||
Offer *webrtc.SessionDescription `json:"offer,omitempty"`
|
||||
Answer *webrtc.SessionDescription `json:"answer,omitempty"`
|
||||
Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Request rateMap `json:"request,omitempty"`
|
||||
RTCConfiguration *group.RTCConfiguration `json:"rtcConfiguration,omitempty"`
|
||||
}
|
||||
|
||||
type closeMessage struct {
|
||||
|
@ -866,16 +867,17 @@ func clientLoop(c *webClient, ws *websocket.Conn) error {
|
|||
}
|
||||
|
||||
case permissionsChangedAction:
|
||||
group := c.Group()
|
||||
if group == nil {
|
||||
g := c.Group()
|
||||
if g == nil {
|
||||
return errors.New("Permissions changed in no group")
|
||||
}
|
||||
perms := c.permissions
|
||||
c.write(clientMessage{
|
||||
Type: "joined",
|
||||
Kind: "change",
|
||||
Group: group.Name(),
|
||||
Permissions: &perms,
|
||||
Type: "joined",
|
||||
Kind: "change",
|
||||
Group: g.Name(),
|
||||
Permissions: &perms,
|
||||
RTCConfiguration: group.ICEConfiguration(),
|
||||
})
|
||||
if !c.permissions.Present {
|
||||
up := getUpConns(c)
|
||||
|
@ -1078,10 +1080,11 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||
c.group = g
|
||||
perms := c.permissions
|
||||
err = c.write(clientMessage{
|
||||
Type: "joined",
|
||||
Kind: "join",
|
||||
Group: m.Group,
|
||||
Permissions: &perms,
|
||||
Type: "joined",
|
||||
Kind: "join",
|
||||
Group: m.Group,
|
||||
Permissions: &perms,
|
||||
RTCConfiguration: group.ICEConfiguration(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -85,9 +85,9 @@ function ServerConnection() {
|
|||
/**
|
||||
* The ICE configuration used by all associated streams.
|
||||
*
|
||||
* @type {RTCIceServer[]}
|
||||
* @type {RTCConfiguration}
|
||||
*/
|
||||
this.iceServers = null;
|
||||
this.rtcConfiguration = null;
|
||||
/**
|
||||
* The permissions granted to this connection.
|
||||
*
|
||||
|
@ -183,6 +183,7 @@ function ServerConnection() {
|
|||
* @property {RTCIceCandidate} [candidate]
|
||||
* @property {Object<string,string>} [labels]
|
||||
* @property {Object<string,(boolean|number)>} [request]
|
||||
* @property {Object<string,any>} [rtcConfiguration]
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -206,26 +207,6 @@ ServerConnection.prototype.send = function(m) {
|
|||
return this.socket.send(JSON.stringify(m));
|
||||
}
|
||||
|
||||
/**
|
||||
* getIceServers fetches an ICE configuration from the server and
|
||||
* populates the iceServers field of a ServerConnection. It is called
|
||||
* lazily by connect.
|
||||
*
|
||||
* @returns {Promise<RTCIceServer[]>}
|
||||
* @function
|
||||
*/
|
||||
ServerConnection.prototype.getIceServers = async function() {
|
||||
let r = await fetch('/ice-servers.json');
|
||||
if(!r.ok)
|
||||
throw new Error("Couldn't fetch ICE servers: " +
|
||||
r.status + ' ' + r.statusText);
|
||||
let servers = await r.json();
|
||||
if(!(servers instanceof Array))
|
||||
throw new Error("couldn't parse ICE servers");
|
||||
this.iceServers = servers;
|
||||
return servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* connect connects to the server.
|
||||
*
|
||||
|
@ -240,14 +221,6 @@ ServerConnection.prototype.connect = async function(url) {
|
|||
sc.socket = null;
|
||||
}
|
||||
|
||||
if(!sc.iceServers) {
|
||||
try {
|
||||
await sc.getIceServers();
|
||||
} catch(e) {
|
||||
console.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
sc.socket = new WebSocket(url);
|
||||
|
||||
return await new Promise((resolve, reject) => {
|
||||
|
@ -311,7 +284,8 @@ ServerConnection.prototype.connect = async function(url) {
|
|||
} else {
|
||||
sc.group = m.group;
|
||||
}
|
||||
sc.permissions = m.permissions;
|
||||
sc.permissions = m.permissions || [];
|
||||
sc.rtcConfiguration = m.rtcConfiguration || null;
|
||||
if(sc.onjoined)
|
||||
sc.onjoined.call(sc, m.kind, m.group,
|
||||
m.permissions || {},
|
||||
|
@ -432,9 +406,7 @@ ServerConnection.prototype.newUpStream = function(id) {
|
|||
if(sc.up[id])
|
||||
throw new Error('Eek!');
|
||||
}
|
||||
let pc = new RTCPeerConnection({
|
||||
iceServers: sc.iceServers || [],
|
||||
});
|
||||
let pc = new RTCPeerConnection(sc.rtcConfiguration);
|
||||
if(!pc)
|
||||
throw new Error("Couldn't create peer connection");
|
||||
if(sc.up[id]) {
|
||||
|
@ -568,9 +540,7 @@ ServerConnection.prototype.gotOffer = async function(id, labels, offer, renegoti
|
|||
throw new Error('Duplicate connection id');
|
||||
|
||||
if(!c) {
|
||||
let pc = new RTCPeerConnection({
|
||||
iceServers: this.iceServers,
|
||||
});
|
||||
let pc = new RTCPeerConnection(sc.rtcConfiguration);
|
||||
c = new Stream(this, id, pc, false);
|
||||
sc.down[id] = c;
|
||||
|
||||
|
|
|
@ -45,12 +45,6 @@ func Serve(address string, dataDir string) error {
|
|||
})
|
||||
http.HandleFunc("/recordings/", recordingsHandler)
|
||||
http.HandleFunc("/ws", wsHandler)
|
||||
http.HandleFunc("/ice-servers.json",
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
mungeHeader(w)
|
||||
serveFile(w, r,
|
||||
filepath.Join(dataDir, "ice-servers.json"))
|
||||
})
|
||||
http.HandleFunc("/public-groups.json", publicHandler)
|
||||
http.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
|
||||
statsHandler(w, r, dataDir)
|
||||
|
|
Loading…
Reference in a new issue