diff --git a/rtpconn/whipclient.go b/rtpconn/whipclient.go index 4c36b4b..6bc2e52 100644 --- a/rtpconn/whipclient.go +++ b/rtpconn/whipclient.go @@ -21,6 +21,7 @@ type WhipClient struct { mu sync.Mutex permissions []string connection *rtpUpConnection + etag string } func NewWhipClient(g *group.Group, id string, token string, addr net.Addr) *WhipClient { @@ -67,6 +68,18 @@ func (c *WhipClient) Data() map[string]interface{} { return nil } +func (c *WhipClient) ETag() string { + c.mu.Lock() + defer c.mu.Unlock() + return c.etag +} + +func (c *WhipClient) SetETag(etag string) { + c.mu.Lock() + defer c.mu.Unlock() + c.etag = etag +} + func (c *WhipClient) PushConn(g *group.Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error { return nil } diff --git a/webserver/whip.go b/webserver/whip.go index 2e5379a..a4504c8 100644 --- a/webserver/whip.go +++ b/webserver/whip.go @@ -243,6 +243,8 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) { return } + c.SetETag("\"" + newId() + "\"") + answer, err := c.NewConnection(r.Context(), body) if err != nil { group.DelClient(c) @@ -253,9 +255,10 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Location", path.Join(r.URL.Path, obfuscated)) w.Header().Set("Access-Control-Expose-Headers", - "Location, Content-Type, Link") + "Location, Content-Type, Link, ETag") whipICEServers(w) w.Header().Set("Content-Type", "application/sdp") + w.Header().Set("ETag", c.ETag()) w.WriteHeader(http.StatusCreated) w.Write(answer) @@ -322,12 +325,16 @@ func whipResourceHandler(w http.ResponseWriter, r *http.Request) { "OPTIONS, DELETE, PATCH", ) w.Header().Set("Access-Control-Allow-Headers", - "Authorization, Content-Type", + "Authorization, Content-Type, If-Match, If-None-Match", ) return } if r.Method == "DELETE" { + done := checkPreconditions(w, r, c.ETag()) + if done { + return + } c.Close() return } @@ -338,6 +345,11 @@ func whipResourceHandler(w http.ResponseWriter, r *http.Request) { } + done := checkPreconditions(w, r, c.ETag()) + if done { + return + } + ctype := r.Header.Get("content-type") if !strings.EqualFold(ctype, "application/trickle-ice-sdpfrag") { w.Header().Set("Accept", "application/trickle-ice-sdpfrag")