diff --git a/client.go b/client.go
index 5598813..d7b0088 100644
--- a/client.go
+++ b/client.go
@@ -105,6 +105,7 @@ type clientMessage struct {
Answer *webrtc.SessionDescription `json:"answer,omitempty"`
Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"`
Del bool `json:"del,omitempty"`
+ Request []string `json:"request,omitempty"`
}
type closeMessage struct {
@@ -934,21 +935,48 @@ func gotICE(c *client, candidate *webrtc.ICECandidateInit, id string) error {
return pc.AddICECandidate(*candidate)
}
+func (c *client) setRequested(audio, video bool) error {
+ if audio == c.requestedAudio && video == c.requestedVideo {
+ return nil
+ }
+
+ if c.down != nil {
+ for id := range c.down {
+ c.write(clientMessage{
+ Type: "close",
+ Id: id,
+ })
+ delDownConn(c, id)
+ }
+ }
+
+ c.requestedAudio = audio
+ c.requestedVideo = video
+
+ for _, cc := range c.group.getClients(c) {
+ cc.action(pushTracksAction{c})
+ }
+
+ return nil
+}
+
+func (c *client) requested(kind webrtc.RTPCodecType) bool {
+ switch kind {
+ case webrtc.RTPCodecTypeAudio:
+ return c.requestedAudio
+ case webrtc.RTPCodecTypeVideo:
+ return c.requestedVideo
+ default:
+ return false
+ }
+}
+
func clientLoop(c *client, conn *websocket.Conn) error {
read := make(chan interface{}, 1)
go clientReader(conn, read, c.done)
defer func() {
- if c.down != nil {
- for id := range c.down {
- c.write(clientMessage{
- Type: "close",
- Id: id,
- })
- delDownConn(c, id)
- }
- }
-
+ c.setRequested(false, false)
if c.up != nil {
for id := range c.up {
delUpConn(c, id)
@@ -956,17 +984,11 @@ func clientLoop(c *client, conn *websocket.Conn) error {
}
}()
- g := c.group
-
c.write(clientMessage{
Type: "permissions",
Permissions: c.permissions,
})
- for _, cc := range g.getClients(c) {
- cc.action(pushTracksAction{c})
- }
-
h := c.group.getChatHistory()
for _, m := range h {
err := c.write(clientMessage{
@@ -1007,14 +1029,19 @@ func clientLoop(c *client, conn *websocket.Conn) error {
case a := <-c.actionCh:
switch a := a.(type) {
case addTrackAction:
- down, _, err :=
- addDownTrack(
+ var down *downConnection
+ var err error
+ if c.requested(a.track.track.Kind()) {
+ down, _, err = addDownTrack(
c, a.remote.id, a.track,
a.remote)
- if err != nil {
- return err
+ if err != nil {
+ return err
+ }
+ } else {
+ down = getDownConn(c, a.remote.id)
}
- if a.done {
+ if a.done && down != nil {
err = negotiate(c, a.remote.id, down.pc)
if err != nil {
return err
@@ -1106,6 +1133,19 @@ func clientLoop(c *client, conn *websocket.Conn) error {
func handleClientMessage(c *client, m clientMessage) error {
switch m.Type {
+ case "request":
+ var audio, video bool
+ for _, s := range m.Request {
+ switch(s) {
+ case "audio": audio = true
+ case "video": video = true
+ default: log.Printf("Unknown request %v", s)
+ }
+ }
+ err := c.setRequested(audio, video)
+ if err != nil {
+ return err
+ }
case "offer":
if !c.permissions.Present {
c.write(clientMessage{
diff --git a/group.go b/group.go
index 5a120a5..2006fb7 100644
--- a/group.go
+++ b/group.go
@@ -150,14 +150,16 @@ type downConnection struct {
}
type client struct {
- group *group
- id string
- username string
- permissions userPermission
- done chan struct{}
- writeCh chan interface{}
- writerDone chan struct{}
- actionCh chan interface{}
+ group *group
+ id string
+ username string
+ permissions userPermission
+ requestedAudio bool
+ requestedVideo bool
+ done chan struct{}
+ writeCh chan interface{}
+ writerDone chan struct{}
+ actionCh chan interface{}
mu sync.Mutex
down map[string]*downConnection
diff --git a/static/sfu.html b/static/sfu.html
index f0c5225..e3a0d70 100644
--- a/static/sfu.html
+++ b/static/sfu.html
@@ -47,6 +47,8 @@
+
+
diff --git a/static/sfu.js b/static/sfu.js
index 35e914e..dbc47b4 100644
--- a/static/sfu.js
+++ b/static/sfu.js
@@ -141,6 +141,11 @@ document.getElementById('sharebox').onchange = function(e) {
setShareMedia(this.checked);
}
+document.getElementById('requestbox').onchange = function(e) {
+ e.preventDefault();
+ sendRequest(this.checked);
+}
+
async function updateStats(conn, sender) {
let stats;
if(!sender.track)
@@ -481,6 +486,7 @@ function serverConnect() {
username: up.username,
password: up.password,
});
+ sendRequest(document.getElementById('requestbox').checked);
resolve();
};
socket.onclose = function(e) {
@@ -551,6 +557,13 @@ function serverConnect() {
});
}
+function sendRequest(video) {
+ send({
+ type: 'request',
+ request: video ? ['audio', 'video'] : ['audio'],
+ });
+}
+
async function gotOffer(id, offer) {
let c = down[id];
if(!c) {