Skip to content

Commit

Permalink
webrtc: upgrade to the latest whip/whep protocol draft version
Browse files Browse the repository at this point in the history
  • Loading branch information
rgl committed Oct 21, 2023
1 parent ccc8256 commit d86e765
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 17 deletions.
40 changes: 35 additions & 5 deletions internal/core/webrtc_http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import (
_ "embed"
"fmt"
"io"
"log"
"net"
"net/http"
"net/url"
standardPathPackage "path"
"strings"
"time"

Expand All @@ -32,6 +35,8 @@ type webRTCHTTPServerParent interface {
addSessionCandidates(req webRTCAddSessionCandidatesReq) webRTCAddSessionCandidatesRes
}

// This implements https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
// This implements https://datatracker.ietf.org/doc/draft-murillo-whep/
type webRTCHTTPServer struct {
allowOrigin string
pathManager *pathManager
Expand Down Expand Up @@ -104,14 +109,26 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
// remove leading prefix
pa := ctx.Request.URL.Path[1:]

// remove the trailing url uuid secret path segment (when it exists).
secret := uuid.Nil
secretPathSegment := standardPathPackage.Base(pa)
if len(secretPathSegment) == 36 {
s, err := uuid.Parse(secretPathSegment)
if err != nil {
ctx.Writer.WriteHeader(http.StatusBadRequest)
}
secret = s
pa = standardPathPackage.Dir(pa)
}

isWHIPorWHEP := strings.HasSuffix(pa, "/whip") || strings.HasSuffix(pa, "/whep")
isPreflight := ctx.Request.Method == http.MethodOptions &&
ctx.Request.Header.Get("Access-Control-Request-Method") != ""

if !isWHIPorWHEP || isPreflight {
switch ctx.Request.Method {
case http.MethodOptions:
ctx.Writer.Header().Set("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PATCH")
ctx.Writer.Header().Set("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PATCH, DELETE")
ctx.Writer.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, If-Match")
ctx.Writer.WriteHeader(http.StatusNoContent)
return
Expand Down Expand Up @@ -262,19 +279,24 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
return
}

location, err := url.JoinPath(ctx.Request.URL.String(), res.sx.secret.String())
if err != nil {
ctx.Writer.WriteHeader(http.StatusInternalServerError)
return
}

ctx.Writer.Header().Set("Content-Type", "application/sdp")
ctx.Writer.Header().Set("Access-Control-Expose-Headers", "ETag, Accept-Patch, Link, Location")
ctx.Writer.Header().Set("ETag", res.sx.secret.String())
ctx.Writer.Header().Set("ETag", "*")
ctx.Writer.Header().Set("ID", res.sx.uuid.String())
ctx.Writer.Header().Set("Accept-Patch", "application/trickle-ice-sdpfrag")
ctx.Writer.Header()["Link"] = whip.LinkHeaderMarshal(servers)
ctx.Writer.Header().Set("Location", ctx.Request.URL.String())
ctx.Writer.Header().Set("Location", location)
ctx.Writer.WriteHeader(http.StatusCreated)
ctx.Writer.Write(res.answer)

case http.MethodPatch:
secret, err := uuid.Parse(ctx.Request.Header.Get("If-Match"))
if err != nil {
if secret == uuid.Nil {
ctx.Writer.WriteHeader(http.StatusBadRequest)
return
}
Expand Down Expand Up @@ -305,6 +327,14 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
}

ctx.Writer.WriteHeader(http.StatusNoContent)

case http.MethodDelete:
if secret == uuid.Nil {
ctx.Writer.WriteHeader(http.StatusBadRequest)
return
}
log.Printf("TODO delete session %s", secret.String())
ctx.Writer.WriteHeader(http.StatusOK)
}
}
}
26 changes: 20 additions & 6 deletions internal/core/webrtc_publish_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@
this.stream = stream;
this.pc = null;
this.restartTimeout = null;
this.eTag = '';
this.sessionUrl = '';
this.queuedCandidates = [];
this.start();
}
Expand Down Expand Up @@ -366,7 +366,7 @@
if (res.status !== 201) {
throw new Error('bad status code');
}
this.eTag = res.headers.get('ETag');
this.sessionUrl = new URL(res.headers.get('location'), window.location.href).toString();
return res.text();
})
.then((sdp) => this.onRemoteAnswer(new RTCSessionDescription({
Expand Down Expand Up @@ -420,7 +420,7 @@
}

if (evt.candidate !== null) {
if (this.eTag === '') {
if (this.sessionUrl === '') {
this.queuedCandidates.push(evt.candidate);
} else {
this.sendLocalCandidates([evt.candidate])
Expand All @@ -429,11 +429,11 @@
}

sendLocalCandidates(candidates) {
fetch(new URL('whip', window.location.href) + window.location.search, {
fetch(this.sessionUrl + window.location.search, {
method: 'PATCH',
headers: {
'Content-Type': 'application/trickle-ice-sdpfrag',
'If-Match': this.eTag,
'If-Match': '*',
},
body: generateSdpFragment(this.offerData, candidates),
})
Expand Down Expand Up @@ -463,7 +463,21 @@
this.start();
}, restartPause);

this.eTag = '';
if (this.sessionUrl) {
fetch(this.sessionUrl, {
method: 'DELETE',
})
.then((res) => {
if (res.status !== 200) {
throw new Error('bad status code');
}
})
.catch((err) => {
console.log('delete session error: ' + err);
});
}
this.sessionUrl = '';

this.queuedCandidates = [];
}
}
Expand Down
26 changes: 20 additions & 6 deletions internal/core/webrtc_read_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
this.video = video;
this.pc = null;
this.restartTimeout = null;
this.eTag = '';
this.sessionUrl = '';
this.queuedCandidates = [];
this.start();
}
Expand Down Expand Up @@ -199,7 +199,7 @@
if (res.status !== 201) {
throw new Error('bad status code');
}
this.eTag = res.headers.get('ETag');
this.sessionUrl = new URL(res.headers.get('location'), window.location.href).toString();
return res.text();
})
.then((sdp) => this.onRemoteAnswer(new RTCSessionDescription({
Expand Down Expand Up @@ -244,7 +244,7 @@
}

if (evt.candidate !== null) {
if (this.eTag === '') {
if (this.sessionUrl === '') {
this.queuedCandidates.push(evt.candidate);
} else {
this.sendLocalCandidates([evt.candidate])
Expand All @@ -253,11 +253,11 @@
}

sendLocalCandidates(candidates) {
fetch(new URL('whep', window.location.href) + window.location.search, {
fetch(this.sessionUrl + window.location.search, {
method: 'PATCH',
headers: {
'Content-Type': 'application/trickle-ice-sdpfrag',
'If-Match': this.eTag,
'If-Match': '*',
},
body: generateSdpFragment(this.offerData, candidates),
})
Expand Down Expand Up @@ -287,7 +287,21 @@
this.start();
}, restartPause);

this.eTag = '';
if (this.sessionUrl) {
fetch(this.sessionUrl, {
method: 'DELETE',
})
.then((res) => {
if (res.status !== 200) {
throw new Error('bad status code');
}
})
.catch((err) => {
console.log('delete session error: ' + err);
});
}
this.sessionUrl = '';

this.queuedCandidates = [];
}
}
Expand Down

0 comments on commit d86e765

Please sign in to comment.