直播:后台 JWT 推流、前台画中画;WebRTC 服务与 Nginx WebSocket 代理

Made-with: Cursor
This commit is contained in:
whm
2026-03-25 15:00:14 +08:00
parent b83ec91b1a
commit 7811adca66
1050 changed files with 146524 additions and 37 deletions

View File

@@ -0,0 +1,124 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
// Package deadline provides deadline timer used to implement
// net.Conn compatible connection
package deadline
import (
"context"
"sync"
"time"
)
type deadlineState uint8
const (
deadlineStopped deadlineState = iota
deadlineStarted
deadlineExceeded
)
var _ context.Context = (*Deadline)(nil)
// Deadline signals updatable deadline timer.
// Also, it implements context.Context.
type Deadline struct {
mu sync.RWMutex
timer timer
done chan struct{}
deadline time.Time
state deadlineState
pending uint8
}
// New creates new deadline timer.
func New() *Deadline {
return &Deadline{
done: make(chan struct{}),
}
}
func (d *Deadline) timeout() {
d.mu.Lock()
if d.pending--; d.pending != 0 || d.state != deadlineStarted {
d.mu.Unlock()
return
}
d.state = deadlineExceeded
done := d.done
d.mu.Unlock()
close(done)
}
// Set new deadline. Zero value means no deadline.
func (d *Deadline) Set(t time.Time) {
d.mu.Lock()
defer d.mu.Unlock()
if d.state == deadlineStarted && d.timer.Stop() {
d.pending--
}
d.deadline = t
d.pending++
if d.state == deadlineExceeded {
d.done = make(chan struct{})
}
if t.IsZero() {
d.pending--
d.state = deadlineStopped
return
}
if dur := time.Until(t); dur > 0 {
d.state = deadlineStarted
if d.timer == nil {
d.timer = afterFunc(dur, d.timeout)
} else {
d.timer.Reset(dur)
}
return
}
d.pending--
d.state = deadlineExceeded
close(d.done)
}
// Done receives deadline signal.
func (d *Deadline) Done() <-chan struct{} {
d.mu.RLock()
defer d.mu.RUnlock()
return d.done
}
// Err returns context.DeadlineExceeded if the deadline is exceeded.
// Otherwise, it returns nil.
func (d *Deadline) Err() error {
d.mu.RLock()
defer d.mu.RUnlock()
if d.state == deadlineExceeded {
return context.DeadlineExceeded
}
return nil
}
// Deadline returns current deadline.
func (d *Deadline) Deadline() (time.Time, bool) {
d.mu.RLock()
defer d.mu.RUnlock()
if d.deadline.IsZero() {
return d.deadline, false
}
return d.deadline, true
}
// Value returns nil.
func (d *Deadline) Value(interface{}) interface{} {
return nil
}

View File

@@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package deadline
import (
"time"
)
type timer interface {
Stop() bool
Reset(time.Duration) bool
}

View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
//go:build !js
// +build !js
package deadline
import (
"time"
)
func afterFunc(d time.Duration, f func()) timer {
return time.AfterFunc(d, f)
}

View File

@@ -0,0 +1,67 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
//go:build js
// +build js
package deadline
import (
"sync"
"time"
)
// jsTimer is a timer utility for wasm with a working Reset function.
type jsTimer struct {
f func()
mu sync.Mutex
timer *time.Timer
version uint64
started bool
}
func afterFunc(d time.Duration, f func()) timer {
t := &jsTimer{f: f}
t.Reset(d)
return t
}
func (t *jsTimer) Stop() bool {
t.mu.Lock()
defer t.mu.Unlock()
t.version++
t.timer.Stop()
started := t.started
t.started = false
return started
}
func (t *jsTimer) Reset(d time.Duration) bool {
t.mu.Lock()
defer t.mu.Unlock()
if t.timer != nil {
t.timer.Stop()
}
t.version++
version := t.version
t.timer = time.AfterFunc(d, func() {
t.mu.Lock()
if version != t.version {
t.mu.Unlock()
return
}
t.started = false
t.mu.Unlock()
t.f()
})
started := t.started
t.started = true
return started
}