mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
DVR: Support blackbox test based on hooks. v5.0.132 (#3365)
This commit is contained in:
parent
a27ce1d50f
commit
e655948e96
31 changed files with 4704 additions and 3925 deletions
43
.github/workflows/test.yml
vendored
43
.github/workflows/test.yml
vendored
|
@ -4,6 +4,7 @@ name: "Test"
|
|||
on: [push, pull_request]
|
||||
|
||||
# The dependency graph:
|
||||
# test(6m)
|
||||
# multiple-arch-armv7(13m)
|
||||
# multiple-arch-aarch64(7m)
|
||||
# cygwin64-cache(1m)
|
||||
|
@ -16,9 +17,7 @@ on: [push, pull_request]
|
|||
# build-cross-arm(3m)
|
||||
# build-cross-aarch64(3m)
|
||||
# multiple-arch-amd64(2m)
|
||||
# utest(3m)
|
||||
# coverage(3m)
|
||||
# blackbox(3m)
|
||||
|
||||
jobs:
|
||||
cygwin64-cache:
|
||||
|
@ -163,30 +162,8 @@ jobs:
|
|||
run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu20-cross-aarch64 .
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
utest:
|
||||
name: utest
|
||||
needs:
|
||||
- fast
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
# Tests
|
||||
- name: Build test image
|
||||
run: docker build --tag srs:test --build-arg MAKEARGS='-j2' -f trunk/Dockerfile.test .
|
||||
# For utest
|
||||
- name: Run SRS utest
|
||||
run: docker run --rm srs:test ./objs/srs_utest
|
||||
# For regression-test
|
||||
- name: Run SRS regression-test
|
||||
run: |
|
||||
docker run --rm srs:test bash -c './objs/srs -c conf/regression-test.conf && \
|
||||
cd 3rdparty/srs-bench && ./objs/srs_test -test.v && ./objs/srs_gb28181_test -test.v'
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
blackbox:
|
||||
name: blackbox
|
||||
needs:
|
||||
- fast
|
||||
test:
|
||||
name: utest-regression-blackbox-test
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
@ -196,10 +173,21 @@ jobs:
|
|||
# For blackbox-test
|
||||
- name: Run SRS blackbox-test
|
||||
run: |
|
||||
#docker run --rm -w /srs/trunk/3rdparty/srs-bench srs:test ./objs/srs_blackbox_test -test.v \
|
||||
# -test.run 'TestFast_RtmpPublish_DvrFlv_Basic' -srs-log -srs-stdout srs-ffmpeg-stderr -srs-dvr-stderr \
|
||||
# -srs-ffprobe-stdout
|
||||
docker run --rm -w /srs/trunk/3rdparty/srs-bench srs:test \
|
||||
./objs/srs_blackbox_test -test.v -test.run '^TestFast' -test.parallel 64
|
||||
docker run --rm -w /srs/trunk/3rdparty/srs-bench srs:test \
|
||||
./objs/srs_blackbox_test -test.v -test.run '^TestSlow' -test.parallel 4
|
||||
# For utest
|
||||
- name: Run SRS utest
|
||||
run: docker run --rm srs:test ./objs/srs_utest
|
||||
# For regression-test
|
||||
- name: Run SRS regression-test
|
||||
run: |
|
||||
docker run --rm srs:test bash -c './objs/srs -c conf/regression-test.conf && \
|
||||
cd 3rdparty/srs-bench && ./objs/srs_test -test.v && ./objs/srs_gb28181_test -test.v'
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
coverage:
|
||||
|
@ -312,8 +300,7 @@ jobs:
|
|||
needs:
|
||||
- cygwin64
|
||||
- coverage
|
||||
- blackbox
|
||||
- utest
|
||||
- test
|
||||
- build-centos7
|
||||
- build-ubuntu16
|
||||
- build-ubuntu18
|
||||
|
|
143
trunk/3rdparty/srs-bench/blackbox/dvr_test.go
vendored
Normal file
143
trunk/3rdparty/srs-bench/blackbox/dvr_test.go
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// # Copyright (c) 2023 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
package blackbox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFast_RtmpPublish_DvrFlv_Basic(t *testing.T) {
|
||||
// This case is run in parallel.
|
||||
t.Parallel()
|
||||
|
||||
// Setup the max timeout for this case.
|
||||
ctx, cancel := context.WithTimeout(logger.WithContext(context.Background()), time.Duration(*srsTimeout)*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
// Check a set of errors.
|
||||
var r0, r1, r2, r3, r4, r5, r6 error
|
||||
defer func(ctx context.Context) {
|
||||
if err := filterTestError(ctx.Err(), r0, r1, r2, r3, r4, r5, r6); err != nil {
|
||||
t.Errorf("Fail for err %+v", err)
|
||||
} else {
|
||||
logger.Tf(ctx, "test done with err %+v", err)
|
||||
}
|
||||
}(ctx)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
// Start hooks service.
|
||||
hooks := NewHooksService()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
r6 = hooks.Run(ctx, cancel)
|
||||
}()
|
||||
|
||||
// Start SRS server and wait for it to be ready.
|
||||
svr := NewSRSServer(func(v *srsServer) {
|
||||
v.envs = []string{
|
||||
"SRS_VHOST_DVR_ENABLED=on",
|
||||
"SRS_VHOST_DVR_DVR_PLAN=session",
|
||||
"SRS_VHOST_DVR_DVR_PATH=./objs/nginx/html/[app]/[stream].[timestamp].flv",
|
||||
fmt.Sprintf("SRS_VHOST_DVR_DVR_DURATION=%v", *srsFFprobeDuration),
|
||||
"SRS_VHOST_HTTP_HOOKS_ENABLED=on",
|
||||
fmt.Sprintf("SRS_VHOST_HTTP_HOOKS_ON_DVR=http://localhost:%v/api/v1/dvrs", hooks.HooksAPI()),
|
||||
}
|
||||
})
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-hooks.ReadyCtx().Done()
|
||||
r0 = svr.Run(ctx, cancel)
|
||||
}()
|
||||
|
||||
// Start FFmpeg to publish stream.
|
||||
duration := time.Duration(*srsFFprobeDuration) * time.Millisecond
|
||||
streamID := fmt.Sprintf("stream-%v-%v", os.Getpid(), rand.Int())
|
||||
streamURL := fmt.Sprintf("rtmp://localhost:%v/live/%v", svr.RTMPPort(), streamID)
|
||||
ffmpeg := NewFFmpeg(func(v *ffmpegClient) {
|
||||
// When process quit, still keep case to run.
|
||||
v.cancelCaseWhenQuit, v.ffmpegDuration = false, duration
|
||||
v.args = []string{
|
||||
"-stream_loop", "-1", "-re", "-i", *srsPublishAvatar, "-c", "copy", "-f", "flv", streamURL,
|
||||
}
|
||||
})
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-svr.ReadyCtx().Done()
|
||||
r1 = ffmpeg.Run(ctx, cancel)
|
||||
}()
|
||||
|
||||
// Start FFprobe to detect and verify stream.
|
||||
ffprobe := NewFFprobe(func(v *ffprobeClient) {
|
||||
v.dvrByFFmpeg, v.streamURL = false, streamURL
|
||||
v.duration, v.timeout = duration, time.Duration(*srsFFprobeTimeout)*time.Millisecond
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for evt := range hooks.HooksEvents() {
|
||||
if onDvrEvt, ok := evt.(*HooksEventOnDvr); ok {
|
||||
fp := path.Join(svr.WorkDir(), onDvrEvt.File)
|
||||
logger.Tf(ctx, "FFprobe: Set the dvrFile=%v from callback", fp)
|
||||
v.dvrFile = fp
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-svr.ReadyCtx().Done()
|
||||
r2 = ffprobe.Run(ctx, cancel)
|
||||
}()
|
||||
|
||||
// Fast quit for probe done.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-ffprobe.ProbeDoneCtx().Done():
|
||||
defer cancel()
|
||||
|
||||
str, m := ffprobe.Result()
|
||||
if len(m.Streams) != 2 {
|
||||
r3 = errors.Errorf("invalid streams=%v, %v, %v", len(m.Streams), m.String(), str)
|
||||
}
|
||||
|
||||
if ts := 90; m.Format.ProbeScore < ts {
|
||||
r4 = errors.Errorf("low score=%v < %v, %v, %v", m.Format.ProbeScore, ts, m.String(), str)
|
||||
}
|
||||
if dv := m.Duration(); dv < duration/2 {
|
||||
r5 = errors.Errorf("short duration=%v < %v, %v, %v", dv, duration/2, m.String(), str)
|
||||
}
|
||||
}
|
||||
}
|
297
trunk/3rdparty/srs-bench/blackbox/util.go
vendored
297
trunk/3rdparty/srs-bench/blackbox/util.go
vendored
|
@ -27,6 +27,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
ohttp "github.com/ossrs/go-oryx-lib/http"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
|
@ -200,6 +201,8 @@ type backendService struct {
|
|||
name string
|
||||
args []string
|
||||
env []string
|
||||
// If timeout, kill the process.
|
||||
duration time.Duration
|
||||
|
||||
// The process stdout and stderr.
|
||||
stdout bytes.Buffer
|
||||
|
@ -315,6 +318,22 @@ func (v *backendService) Run(ctx context.Context, cancel context.CancelFunc) err
|
|||
// The context for SRS process.
|
||||
processDone, processDoneCancel := context.WithCancel(context.Background())
|
||||
|
||||
// If exceed timeout, kill the process.
|
||||
v.wg.Add(1)
|
||||
go func() {
|
||||
defer v.wg.Done()
|
||||
if v.duration <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <- ctx.Done():
|
||||
case <-time.After(v.duration):
|
||||
logger.Tf(ctx, "Process killed duration=%v, pid=%v, name=%v, args=%v", v.duration, v.pid, v.name, v.args)
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
}()
|
||||
|
||||
// If SRS process terminated, notify case to stop.
|
||||
v.wg.Add(1)
|
||||
go func() {
|
||||
|
@ -327,12 +346,12 @@ func (v *backendService) Run(ctx context.Context, cancel context.CancelFunc) err
|
|||
defer processDoneCancel()
|
||||
|
||||
if err := cmd.Wait(); err != nil && !v.ignoreExitStatusError {
|
||||
v.r0 = errors.Wrapf(err, "Process wait err, name=%v, args=%v", v.name, v.args)
|
||||
v.r0 = errors.Wrapf(err, "Process wait err, pid=%v, name=%v, args=%v", v.pid, v.name, v.args)
|
||||
}
|
||||
if v.onStop != nil {
|
||||
if err := v.onStop(ctx, v, cmd, v.r0, &v.stdout, &v.stderr); err != nil {
|
||||
if v.r0 == nil {
|
||||
v.r0 = errors.Wrapf(err, "Process onStop err, name=%v, args=%v", v.name, v.args)
|
||||
v.r0 = errors.Wrapf(err, "Process onStop err, pid=%v, name=%v, args=%v", v.pid, v.name, v.args)
|
||||
} else {
|
||||
logger.Ef(ctx, "Process onStop err %v", err)
|
||||
}
|
||||
|
@ -435,7 +454,7 @@ type srsServer struct {
|
|||
func NewSRSServer(opts ...func(v *srsServer)) SRSServer {
|
||||
rid := fmt.Sprintf("%v-%v", os.Getpid(), rand.Int())
|
||||
v := &srsServer{
|
||||
workDir: "./",
|
||||
workDir: path.Join("objs", fmt.Sprintf("%v", rand.Int())),
|
||||
srsID: fmt.Sprintf("srs-id-%v", rid),
|
||||
process: newBackendService(),
|
||||
}
|
||||
|
@ -443,7 +462,7 @@ func NewSRSServer(opts ...func(v *srsServer)) SRSServer {
|
|||
|
||||
// If we run in GoLand, the current directory is in blackbox, so we use parent directory.
|
||||
if _, err := os.Stat("objs"); err != nil {
|
||||
v.workDir = "../"
|
||||
v.workDir = path.Join("..", "objs", fmt.Sprintf("%v", rand.Int()))
|
||||
}
|
||||
|
||||
// Do allocate resource.
|
||||
|
@ -461,22 +480,12 @@ func NewSRSServer(opts ...func(v *srsServer)) SRSServer {
|
|||
allocator.Free(v.httpListen)
|
||||
allocator.Free(v.srtListen)
|
||||
|
||||
pidFile := path.Join(v.workDir, v.srsRelativePidFile)
|
||||
if _, err := os.Stat(pidFile); err == nil {
|
||||
os.Remove(pidFile)
|
||||
if _, err := os.Stat(v.workDir); err == nil {
|
||||
os.RemoveAll(v.workDir)
|
||||
}
|
||||
|
||||
idFile := path.Join(v.workDir, v.srsRelativeIDFile)
|
||||
if _, err := os.Stat(idFile); err == nil {
|
||||
os.Remove(idFile)
|
||||
}
|
||||
|
||||
hlsFiles := path.Join(v.workDir, "objs", "live")
|
||||
if _, err := os.Stat(hlsFiles); err == nil {
|
||||
os.RemoveAll(hlsFiles)
|
||||
}
|
||||
|
||||
logger.Tf(ctx, "SRS server is closed, id=%v, pid=%v, r0=%v", v.srsID, bs.pid, bs.r0)
|
||||
logger.Tf(ctx, "SRS server is closed, id=%v, pid=%v, cleanup=%v r0=%v",
|
||||
v.srsID, bs.pid, v.workDir, bs.r0)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -512,20 +521,39 @@ func (v *srsServer) Run(ctx context.Context, cancel context.CancelFunc) error {
|
|||
v.workDir, *srsBinary, v.srsID, v.srsRelativePidFile, v.rtmpListen,
|
||||
)
|
||||
|
||||
// Create directories.
|
||||
if err := os.MkdirAll(path.Join(v.workDir, "./objs/nginx/html"), os.FileMode(0755) | os.ModeDir); err != nil {
|
||||
return errors.Wrapf(err, "SRS create directory %v", path.Join(v.workDir, "./objs/nginx/html"))
|
||||
}
|
||||
|
||||
// Setup the name and args of process.
|
||||
v.process.name = *srsBinary
|
||||
v.process.args = []string{"-e"}
|
||||
|
||||
// Setup the envrionment variables.
|
||||
// Setup the constant values.
|
||||
v.process.env = []string{
|
||||
// SRS working directory.
|
||||
fmt.Sprintf("SRS_WORK_DIR=%v", v.workDir),
|
||||
// Run in frontend.
|
||||
"SRS_DAEMON=off",
|
||||
// Write logs to stdout and stderr.
|
||||
"SRS_SRS_LOG_FILE=console",
|
||||
// Disable warning for asan.
|
||||
"MallocNanoZone=0",
|
||||
// Avoid error for macOS, which ulimit to 256.
|
||||
"SRS_MAX_CONNECTIONS=100",
|
||||
}
|
||||
// For directories.
|
||||
v.process.env = append(v.process.env, []string{
|
||||
// SRS working directory.
|
||||
fmt.Sprintf("SRS_WORK_DIR=%v", v.workDir),
|
||||
// Setup the default directory for HTTP server.
|
||||
"SRS_HTTP_SERVER_DIR=./objs/nginx/html",
|
||||
// Setup the default directory for HLS stream.
|
||||
"SRS_VHOST_HLS_HLS_PATH=./objs/nginx/html",
|
||||
"SRS_VHOST_HLS_HLS_M3U8_FILE=[app]/[stream].m3u8",
|
||||
"SRS_VHOST_HLS_HLS_TS_FILE=[app]/[stream]-[seq].ts",
|
||||
}...)
|
||||
// For variables.
|
||||
v.process.env = append(v.process.env, []string{
|
||||
// SRS PID file.
|
||||
fmt.Sprintf("SRS_PID=%v", v.srsRelativePidFile),
|
||||
// SRS ID file.
|
||||
|
@ -533,19 +561,13 @@ func (v *srsServer) Run(ctx context.Context, cancel context.CancelFunc) error {
|
|||
// HTTP API to detect the service.
|
||||
fmt.Sprintf("SRS_HTTP_API_ENABLED=on"),
|
||||
fmt.Sprintf("SRS_HTTP_API_LISTEN=%v", v.apiListen),
|
||||
// Avoid error for macOS, which ulimit to 256.
|
||||
"SRS_MAX_CONNECTIONS=100",
|
||||
// Setup the default directory for HTTP server.
|
||||
"SRS_HTTP_SERVER_DIR=objs",
|
||||
// Setup the default directory for HLS stream.
|
||||
"SRS_VHOST_HLS_HLS_PATH=objs",
|
||||
// Setup the RTMP listen port.
|
||||
fmt.Sprintf("SRS_LISTEN=%v", v.rtmpListen),
|
||||
// Setup the HTTP sever listen port.
|
||||
fmt.Sprintf("SRS_HTTP_SERVER_LISTEN=%v", v.httpListen),
|
||||
// Setup the SRT server listen port.
|
||||
fmt.Sprintf("SRS_SRT_SERVER_LISTEN=%v", v.srtListen),
|
||||
}
|
||||
}...)
|
||||
// Rewrite envs by case.
|
||||
if v.envs != nil {
|
||||
v.process.env = append(v.process.env, v.envs...)
|
||||
|
@ -588,8 +610,8 @@ func (v *srsServer) Run(ctx context.Context, cancel context.CancelFunc) error {
|
|||
|
||||
// Hooks for process.
|
||||
v.process.onBeforeStart = func(ctx context.Context, bs *backendService, cmd *exec.Cmd) error {
|
||||
logger.Tf(ctx, "SRS id=%v, env=%v, cmd is %v %v",
|
||||
v.srsID, cmd.Env, bs.name, strings.Join(bs.args, " "))
|
||||
logger.Tf(ctx, "SRS id=%v, env %v %v %v",
|
||||
v.srsID, strings.Join(cmd.Env, " "), bs.name, strings.Join(bs.args, " "))
|
||||
return nil
|
||||
}
|
||||
v.process.onAfterStart = func(ctx context.Context, bs *backendService, cmd *exec.Cmd) error {
|
||||
|
@ -625,11 +647,16 @@ type ffmpegClient struct {
|
|||
|
||||
// FFmpeg cli args, without ffmpeg binary.
|
||||
args []string
|
||||
// Let the process quit, do not cancel the case.
|
||||
cancelCaseWhenQuit bool
|
||||
// When timeout, stop FFmpeg, sometimes the '-t' does not work.
|
||||
ffmpegDuration time.Duration
|
||||
}
|
||||
|
||||
func NewFFmpeg(opts ...func(v *ffmpegClient)) FFmpegClient {
|
||||
v := &ffmpegClient{
|
||||
process: newBackendService(),
|
||||
cancelCaseWhenQuit: true,
|
||||
}
|
||||
|
||||
// Do cleanup.
|
||||
|
@ -657,6 +684,7 @@ func (v *ffmpegClient) Run(ctx context.Context, cancel context.CancelFunc) error
|
|||
v.process.name = *srsFFmpeg
|
||||
v.process.args = v.args
|
||||
v.process.env = os.Environ()
|
||||
v.process.duration = v.ffmpegDuration
|
||||
|
||||
v.process.onStop = func(ctx context.Context, bs *backendService, cmd *exec.Cmd, r0 error, stdout, stderr *bytes.Buffer) error {
|
||||
logger.Tf(ctx, "FFmpeg process pid=%v exit, r0=%v, stdout=%v", bs.pid, r0, stdout.String())
|
||||
|
@ -666,7 +694,20 @@ func (v *ffmpegClient) Run(ctx context.Context, cancel context.CancelFunc) error
|
|||
return nil
|
||||
}
|
||||
|
||||
return v.process.Run(ctx, cancel)
|
||||
// We might not want to cancel the case, for example, when check DVR by session, we just let the FFmpeg process to
|
||||
// quit and we should check the callback and DVR file.
|
||||
ffCtx, ffCancel := context.WithCancel(ctx)
|
||||
go func() {
|
||||
select {
|
||||
case <- ctx.Done():
|
||||
case <-ffCtx.Done():
|
||||
if v.cancelCaseWhenQuit {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return v.process.Run(ffCtx, ffCancel)
|
||||
}
|
||||
|
||||
type FFprobeClient interface {
|
||||
|
@ -678,16 +719,19 @@ type FFprobeClient interface {
|
|||
}
|
||||
|
||||
type ffprobeClient struct {
|
||||
// The stream to probe.
|
||||
streamURL string
|
||||
|
||||
// The DVR file for ffprobe. We DVR stream to file, then use ffprobe to detect it.
|
||||
// The DVR file for ffprobe. Stream should be DVR to file, then use ffprobe to detect it. If DVR by FFmpeg, we will
|
||||
// start a FFmpeg process to do the DVR, or the DVR should be done by other tools.
|
||||
dvrFile string
|
||||
// The duration of video file for DVR.
|
||||
duration time.Duration
|
||||
// The timeout to wait for task to done.
|
||||
timeout time.Duration
|
||||
|
||||
// Whether do DVR by FFmpeg, if using SRS DVR, please set to false.
|
||||
dvrByFFmpeg bool
|
||||
// The stream to DVR for probing. Ignore if not DVR by ffmpeg
|
||||
streamURL string
|
||||
// The duration of video file for DVR and probing.
|
||||
duration time.Duration
|
||||
|
||||
// When probe stream metadata object.
|
||||
doneCtx context.Context
|
||||
doneCancel context.CancelFunc
|
||||
|
@ -700,6 +744,7 @@ type ffprobeClient struct {
|
|||
func NewFFprobe(opts ...func(v *ffprobeClient)) FFprobeClient {
|
||||
v := &ffprobeClient{
|
||||
metadata: &ffprobeObject{},
|
||||
dvrByFFmpeg: true,
|
||||
}
|
||||
v.doneCtx, v.doneCancel = context.WithCancel(context.Background())
|
||||
|
||||
|
@ -728,9 +773,12 @@ func (v *ffprobeClient) Run(ctxCase context.Context, cancelCase context.CancelFu
|
|||
|
||||
// Try to start a DVR process.
|
||||
for ctx.Err() == nil {
|
||||
// If not DVR by FFmpeg, we just wait the DVR file to be ready, and it should be done by SRS or other tools.
|
||||
if v.dvrByFFmpeg {
|
||||
// If error, just ignore and retry, because the stream might not be ready. For example, for HLS, the DVR process
|
||||
// might need to wait for a duration of segment, 10s as such.
|
||||
_ = v.doDVR(ctx)
|
||||
}
|
||||
|
||||
// Check whether DVR file is ok.
|
||||
if fs, err := os.Stat(v.dvrFile); err == nil && fs.Size() > 1024 {
|
||||
|
@ -738,9 +786,14 @@ func (v *ffprobeClient) Run(ctxCase context.Context, cancelCase context.CancelFu
|
|||
break
|
||||
}
|
||||
|
||||
// If not DVR by FFmpeg, must be by other tools, only need to wait.
|
||||
if !v.dvrByFFmpeg {
|
||||
logger.Tf(ctx, "Waiting stream=%v to be DVR", v.streamURL)
|
||||
}
|
||||
|
||||
// Wait for a while and retry. Use larger timeout for HLS.
|
||||
retryTimeout := 1 * time.Second
|
||||
if strings.Contains(v.streamURL, ".m3u8") {
|
||||
if strings.Contains(v.streamURL, ".m3u8") || v.dvrFile == "" {
|
||||
retryTimeout = 3 * time.Second
|
||||
}
|
||||
|
||||
|
@ -763,6 +816,10 @@ func (v *ffprobeClient) Run(ctxCase context.Context, cancelCase context.CancelFu
|
|||
func (v *ffprobeClient) doDVR(ctx context.Context) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
if !v.dvrByFFmpeg {
|
||||
return nil
|
||||
}
|
||||
|
||||
process := newBackendService()
|
||||
process.name = *srsFFmpeg
|
||||
process.args = []string{
|
||||
|
@ -1070,3 +1127,167 @@ func (v *ffprobeObject) Audio() *ffprobeObjectMedia {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type HooksEvent interface {
|
||||
HookAction() string
|
||||
}
|
||||
|
||||
type HooksEventBase struct {
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
func (v *HooksEventBase) HookAction() string {
|
||||
return v.Action
|
||||
}
|
||||
|
||||
type HooksEventOnDvr struct {
|
||||
HooksEventBase
|
||||
Stream string `json:"stream"`
|
||||
StreamUrl string `json:"stream_url"`
|
||||
StreamID string `json:"stream_id"`
|
||||
CWD string `json:"cwd"`
|
||||
File string `json:"file"`
|
||||
TcUrl string `json:"tcUrl"`
|
||||
App string `json:"app"`
|
||||
Vhost string `json:"vhost"`
|
||||
IP string `json:"ip"`
|
||||
ClientIP string `json:"client_id"`
|
||||
ServerID string `json:"server_id"`
|
||||
}
|
||||
|
||||
type HooksService interface {
|
||||
ServiceRunner
|
||||
ServiceReadyQuerier
|
||||
HooksAPI() int
|
||||
HooksEvents() <-chan HooksEvent
|
||||
}
|
||||
|
||||
type hooksService struct {
|
||||
readyCtx context.Context
|
||||
readyCancel context.CancelFunc
|
||||
|
||||
httpPort int
|
||||
dispose func()
|
||||
|
||||
r0 error
|
||||
hooksOnDvr chan HooksEvent
|
||||
}
|
||||
|
||||
func NewHooksService(opts ...func(v *hooksService)) HooksService {
|
||||
v := &hooksService{}
|
||||
|
||||
v.httpPort = allocator.Allocate()
|
||||
v.dispose = func() {
|
||||
allocator.Free(v.httpPort)
|
||||
close(v.hooksOnDvr)
|
||||
}
|
||||
v.hooksOnDvr = make(chan HooksEvent, 64)
|
||||
v.readyCtx, v.readyCancel = context.WithCancel(context.Background())
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(v)
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *hooksService) ReadyCtx() context.Context {
|
||||
return v.readyCtx
|
||||
}
|
||||
|
||||
func (v *hooksService) HooksAPI() int {
|
||||
return v.httpPort
|
||||
}
|
||||
|
||||
func (v *hooksService) HooksEvents() <-chan HooksEvent {
|
||||
return v.hooksOnDvr
|
||||
}
|
||||
|
||||
func (v *hooksService) Run(ctx context.Context, cancel context.CancelFunc) error {
|
||||
defer func() {
|
||||
v.readyCancel()
|
||||
v.dispose()
|
||||
}()
|
||||
|
||||
handler := http.ServeMux{}
|
||||
handler.HandleFunc("/api/v1/ping", func(w http.ResponseWriter, r *http.Request) {
|
||||
ohttp.WriteData(ctx, w, r, "pong")
|
||||
})
|
||||
|
||||
handler.HandleFunc("/api/v1/dvrs", func(w http.ResponseWriter, r *http.Request) {
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
ohttp.WriteError(ctx, w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
evt := HooksEventOnDvr{}
|
||||
if err := json.Unmarshal(b, &evt); err != nil {
|
||||
ohttp.WriteError(ctx, w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case v.hooksOnDvr <- &evt:
|
||||
}
|
||||
|
||||
logger.Tf(ctx, "Callback: Got on_dvr request %v", string(b))
|
||||
ohttp.WriteData(ctx, w, r, nil)
|
||||
})
|
||||
|
||||
server := &http.Server{Addr: fmt.Sprintf(":%v", v.httpPort), Handler: &handler}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
logger.Tf(ctx, "Callback: Start hooks server, listen=%v", v.httpPort)
|
||||
|
||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
logger.Wf(ctx, "Callback: Service listen=%v, err %v", v.httpPort, err)
|
||||
v.r0 = errors.Wrapf(err, "server listen=%v", v.httpPort)
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
logger.Tf(ctx, "Callback: Hooks done, listen=%v", v.httpPort)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-ctx.Done()
|
||||
|
||||
go server.Shutdown(context.Background())
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
for ctx.Err() == nil {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
r := fmt.Sprintf("http://localhost:%v/api/v1/ping", v.httpPort)
|
||||
res, err := http.Get(r)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Tf(ctx, "Callback: API is ready, %v %v", r, string(b))
|
||||
v.readyCancel()
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
return v.r0
|
||||
}
|
||||
|
|
1
trunk/3rdparty/srs-bench/go.mod
vendored
1
trunk/3rdparty/srs-bench/go.mod
vendored
|
@ -12,6 +12,7 @@ require (
|
|||
github.com/pion/sdp/v3 v3.0.4
|
||||
github.com/pion/transport v0.12.2
|
||||
github.com/pion/webrtc/v3 v3.0.13
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25
|
||||
github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25
|
||||
)
|
||||
|
|
4
trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go
generated
vendored
4
trunk/3rdparty/srs-bench/vendor/github.com/ghettovoice/gosip/sip/parser/error.go
generated
vendored
|
@ -11,9 +11,7 @@ type InvalidStartLineError string
|
|||
func (err InvalidStartLineError) Syntax() bool { return true }
|
||||
func (err InvalidStartLineError) Malformed() bool { return false }
|
||||
func (err InvalidStartLineError) Broken() bool { return true }
|
||||
func (err InvalidStartLineError) Error() string {
|
||||
return "parser.InvalidStartLineError: " + string(err)
|
||||
}
|
||||
func (err InvalidStartLineError) Error() string { return "parser.InvalidStartLineError: " + string(err) }
|
||||
|
||||
type InvalidMessageFormat string
|
||||
|
||||
|
|
87
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/api.go
generated
vendored
Normal file
87
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/api.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2013-2017 Oryx(ossrs)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// The oryx http package, the response parse service.
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Read http api by HTTP GET and parse the code/data.
|
||||
func ApiRequest(url string) (code int, body []byte, err error) {
|
||||
if body, err = apiGet(url); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if code, _, err = apiParse(url, body); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Read http api by HTTP GET.
|
||||
func apiGet(url string) (body []byte, err error) {
|
||||
var resp *http.Response
|
||||
if resp, err = http.Get(url); err != nil {
|
||||
err = fmt.Errorf("api get failed, url=%v, err is %v", url, err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if body, err = ioutil.ReadAll(resp.Body); err != nil {
|
||||
err = fmt.Errorf("api read failed, url=%v, err is %v", url, err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Parse the standard response {code:int,data:object}.
|
||||
func apiParse(url string, body []byte) (code int, data interface{}, err error) {
|
||||
obj := make(map[string]interface{})
|
||||
if err = json.Unmarshal(body, &obj); err != nil {
|
||||
err = fmt.Errorf("api parse failed, url=%v, body=%v, err is %v", url, string(body), err)
|
||||
return
|
||||
}
|
||||
|
||||
if value, ok := obj["code"]; !ok {
|
||||
err = fmt.Errorf("api no code, url=%v, body=%v", url, string(body))
|
||||
return
|
||||
} else if value, ok := value.(float64); !ok {
|
||||
err = fmt.Errorf("api code not number, code=%v, url=%v, body=%v", value, url, string(body))
|
||||
return
|
||||
} else {
|
||||
code = int(value)
|
||||
}
|
||||
|
||||
data, _ = obj["data"]
|
||||
if code != 0 {
|
||||
err = fmt.Errorf("api error, code=%v, url=%v, body=%v, data=%v", code, url, string(body), data)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
274
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/http.go
generated
vendored
Normal file
274
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/http/http.go
generated
vendored
Normal file
|
@ -0,0 +1,274 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2013-2017 Oryx(ossrs)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// The oryx http package provides standard request and response in json.
|
||||
// Error, when error, use this handler.
|
||||
// CplxError, for complex error, use this handler.
|
||||
// Data, when no error, use this handler.
|
||||
// SystemError, application level error code.
|
||||
// SetHeader, for direclty response the raw stream.
|
||||
// The standard server response:
|
||||
// code, an int error code.
|
||||
// data, specifies the data.
|
||||
// The api for simple api:
|
||||
// WriteVersion, to directly response the version.
|
||||
// WriteData, to directly write the data in json.
|
||||
// WriteError, to directly write the error.
|
||||
// WriteCplxError, to directly write the complex error.
|
||||
// The global variables:
|
||||
// oh.Server, to set the response header["Server"].
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
ol "github.com/ossrs/go-oryx-lib/logger"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// header["Content-Type"] in response.
|
||||
const (
|
||||
HttpJson = "application/json"
|
||||
HttpJavaScript = "application/javascript"
|
||||
)
|
||||
|
||||
// header["Server"] in response.
|
||||
var Server = "Oryx"
|
||||
|
||||
// system int error.
|
||||
type SystemError int
|
||||
|
||||
func (v SystemError) Error() string {
|
||||
return fmt.Sprintf("System error=%d", int(v))
|
||||
}
|
||||
|
||||
// system conplex error.
|
||||
type SystemComplexError struct {
|
||||
// the system error code.
|
||||
Code SystemError `json:"code"`
|
||||
// the description for this error.
|
||||
Message string `json:"data"`
|
||||
}
|
||||
|
||||
func (v SystemComplexError) Error() string {
|
||||
return fmt.Sprintf("%v, %v", v.Code.Error(), v.Message)
|
||||
}
|
||||
|
||||
// application level, with code.
|
||||
type AppError interface {
|
||||
Code() int
|
||||
error
|
||||
}
|
||||
|
||||
// HTTP Status Code
|
||||
type HTTPStatus interface {
|
||||
Status() int
|
||||
}
|
||||
|
||||
// http standard error response.
|
||||
// @remark for not SystemError, we will use logger.E to print it.
|
||||
// @remark user can use WriteError() for simple api.
|
||||
func Error(ctx ol.Context, err error) http.Handler {
|
||||
// for complex error, use code instead.
|
||||
if v, ok := err.(SystemComplexError); ok {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
jsonHandler(ctx, FilterCplxSystemError(ctx, w, r, v)).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// for int error, use code instead.
|
||||
if v, ok := err.(SystemError); ok {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
jsonHandler(ctx, FilterSystemError(ctx, w, r, v)).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// for application error, use code instead.
|
||||
if v, ok := err.(AppError); ok {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
jsonHandler(ctx, FilterAppError(ctx, w, r, v)).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// unknown error, log and response detail
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
SetHeader(w)
|
||||
w.Header().Set("Content-Type", HttpJson)
|
||||
|
||||
status := http.StatusInternalServerError
|
||||
if v, ok := err.(HTTPStatus); ok {
|
||||
status = v.Status()
|
||||
}
|
||||
|
||||
http.Error(w, FilterError(ctx, w, r, err), status)
|
||||
})
|
||||
}
|
||||
|
||||
// Wrapper for complex error use Error(ctx, SystemComplexError{})
|
||||
// @remark user can use WriteCplxError() for simple api.
|
||||
func CplxError(ctx ol.Context, code SystemError, message string) http.Handler {
|
||||
return Error(ctx, SystemComplexError{code, message})
|
||||
}
|
||||
|
||||
// http normal response.
|
||||
// @remark user can use nil v to response success, which data is null.
|
||||
// @remark user can use WriteData() for simple api.
|
||||
func Data(ctx ol.Context, v interface{}) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
jsonHandler(ctx, FilterData(ctx, w, r, v)).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// set http header, for directly use the w,
|
||||
// for example, user want to directly write raw text.
|
||||
func SetHeader(w http.ResponseWriter) {
|
||||
w.Header().Set("Server", Server)
|
||||
}
|
||||
|
||||
// response json directly.
|
||||
func jsonHandler(ctx ol.Context, rv interface{}) http.Handler {
|
||||
var err error
|
||||
var b []byte
|
||||
if b, err = json.Marshal(rv); err != nil {
|
||||
return Error(ctx, err)
|
||||
}
|
||||
|
||||
status := http.StatusOK
|
||||
if v, ok := rv.(HTTPStatus); ok {
|
||||
status = v.Status()
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
SetHeader(w)
|
||||
|
||||
q := r.URL.Query()
|
||||
if cb := q.Get("callback"); cb != "" {
|
||||
w.Header().Set("Content-Type", HttpJavaScript)
|
||||
if status != http.StatusOK {
|
||||
w.WriteHeader(status)
|
||||
}
|
||||
|
||||
// TODO: Handle error.
|
||||
fmt.Fprintf(w, "%s(%s)", cb, string(b))
|
||||
} else {
|
||||
w.Header().Set("Content-Type", HttpJson)
|
||||
if status != http.StatusOK {
|
||||
w.WriteHeader(status)
|
||||
}
|
||||
// TODO: Handle error.
|
||||
w.Write(b)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// response the standard version info:
|
||||
// {code, server, data} where server is the server pid, and data is below object:
|
||||
// {major, minor, revision, extra, version, signature}
|
||||
// @param version in {major.minor.revision-extra}, where -extra is optional,
|
||||
// for example: 1.0.0 or 1.0.0-0 or 1.0.0-1
|
||||
func WriteVersion(w http.ResponseWriter, r *http.Request, version string) {
|
||||
var major, minor, revision, extra int
|
||||
|
||||
versions := strings.Split(version, "-")
|
||||
if len(versions) > 1 {
|
||||
extra, _ = strconv.Atoi(versions[1])
|
||||
}
|
||||
|
||||
versions = strings.Split(versions[0], ".")
|
||||
if len(versions) > 0 {
|
||||
major, _ = strconv.Atoi(versions[0])
|
||||
}
|
||||
if len(versions) > 1 {
|
||||
minor, _ = strconv.Atoi(versions[1])
|
||||
}
|
||||
if len(versions) > 2 {
|
||||
revision, _ = strconv.Atoi(versions[2])
|
||||
}
|
||||
|
||||
Data(nil, map[string]interface{}{
|
||||
"major": major,
|
||||
"minor": minor,
|
||||
"revision": revision,
|
||||
"extra": extra,
|
||||
"version": version,
|
||||
"signature": Server,
|
||||
}).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// Directly write json data, a wrapper for Data().
|
||||
// @remark user can use Data() for group of complex apis.
|
||||
func WriteData(ctx ol.Context, w http.ResponseWriter, r *http.Request, v interface{}) {
|
||||
Data(ctx, v).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// Directly write success json response, same to WriteData(ctx, w, r, nil).
|
||||
func Success(ctx ol.Context, w http.ResponseWriter, r *http.Request) {
|
||||
WriteData(ctx, w, r, nil)
|
||||
}
|
||||
|
||||
// Directly write error, a wrapper for Error().
|
||||
// @remark user can use Error() for group of complex apis.
|
||||
func WriteError(ctx ol.Context, w http.ResponseWriter, r *http.Request, err error) {
|
||||
Error(ctx, err).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// Directly write complex error, a wrappter for CplxError().
|
||||
// @remark user can use CplxError() for group of complex apis.
|
||||
func WriteCplxError(ctx ol.Context, w http.ResponseWriter, r *http.Request, code SystemError, message string) {
|
||||
CplxError(ctx, code, message).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// for hijack to define the response structure.
|
||||
// user can redefine these functions for special response.
|
||||
var FilterCplxSystemError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o SystemComplexError) interface{} {
|
||||
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, o)
|
||||
return o
|
||||
}
|
||||
var FilterSystemError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o SystemError) interface{} {
|
||||
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, o)
|
||||
return map[string]int{"code": int(o)}
|
||||
}
|
||||
var FilterAppError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, err AppError) interface{} {
|
||||
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err)
|
||||
return map[string]interface{}{"code": err.Code(), "data": err.Error()}
|
||||
}
|
||||
var FilterError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, err error) string {
|
||||
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err)
|
||||
return err.Error()
|
||||
}
|
||||
var FilterData = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o interface{}) interface{} {
|
||||
rv := map[string]interface{}{
|
||||
"code": 0,
|
||||
"server": os.Getpid(),
|
||||
"data": o,
|
||||
}
|
||||
|
||||
// for string, directly use it without convert,
|
||||
// for the type covert by golang maybe modify the content.
|
||||
if v, ok := o.(string); ok {
|
||||
rv["data"] = v
|
||||
}
|
||||
|
||||
return rv
|
||||
}
|
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
generated
vendored
|
@ -10,3 +10,4 @@ func isTerminal(fd int) bool {
|
|||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
|
@ -10,3 +10,4 @@ func isTerminal(fd int) bool {
|
|||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/mgutz/ansi"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/mgutz/ansi"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
|
|
2
trunk/3rdparty/srs-bench/vendor/modules.txt
vendored
2
trunk/3rdparty/srs-bench/vendor/modules.txt
vendored
|
@ -33,6 +33,7 @@ github.com/ossrs/go-oryx-lib/amf0
|
|||
github.com/ossrs/go-oryx-lib/avc
|
||||
github.com/ossrs/go-oryx-lib/errors
|
||||
github.com/ossrs/go-oryx-lib/flv
|
||||
github.com/ossrs/go-oryx-lib/http
|
||||
github.com/ossrs/go-oryx-lib/logger
|
||||
github.com/ossrs/go-oryx-lib/rtmp
|
||||
# github.com/pion/datachannel v1.4.21
|
||||
|
@ -116,6 +117,7 @@ github.com/pion/webrtc/v3/pkg/media/oggreader
|
|||
github.com/pion/webrtc/v3/pkg/media/oggwriter
|
||||
github.com/pion/webrtc/v3/pkg/rtcerr
|
||||
# github.com/pkg/errors v0.9.1
|
||||
## explicit
|
||||
github.com/pkg/errors
|
||||
# github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b
|
||||
github.com/satori/go.uuid
|
||||
|
|
|
@ -1515,6 +1515,7 @@ vhost http.remux.srs.com {
|
|||
vhost hooks.callback.srs.com {
|
||||
http_hooks {
|
||||
# whether the http hooks enable.
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ENABLED for all vhosts.
|
||||
# default off.
|
||||
enabled on;
|
||||
# when client(encoder) publish to vhost/app/stream, call the hook,
|
||||
|
@ -1533,6 +1534,7 @@ vhost hooks.callback.srs.com {
|
|||
# on_publish http://xxx/api0 http://xxx/api1 http://xxx/apiN
|
||||
# @remark For SRS4, the HTTPS url is supported, for example:
|
||||
# on_publish https://xxx/api0 https://xxx/api1 https://xxx/apiN
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_PUBLISH for all vhosts.
|
||||
on_publish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams;
|
||||
# when client(encoder) stop publish to vhost/app/stream, call the hook,
|
||||
# the request in the POST data string is a object encode by json:
|
||||
|
@ -1550,6 +1552,7 @@ vhost hooks.callback.srs.com {
|
|||
# on_unpublish http://xxx/api0 http://xxx/api1 http://xxx/apiN
|
||||
# @remark For SRS4, the HTTPS url is supported, for example:
|
||||
# on_unpublish https://xxx/api0 https://xxx/api1 https://xxx/apiN
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_UNPUBLISH for all vhosts.
|
||||
on_unpublish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams;
|
||||
# when client start to play vhost/app/stream, call the hook,
|
||||
# the request in the POST data string is a object encode by json:
|
||||
|
@ -1568,6 +1571,7 @@ vhost hooks.callback.srs.com {
|
|||
# on_play http://xxx/api0 http://xxx/api1 http://xxx/apiN
|
||||
# @remark For SRS4, the HTTPS url is supported, for example:
|
||||
# on_play https://xxx/api0 https://xxx/api1 https://xxx/apiN
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_PLAY for all vhosts.
|
||||
on_play http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions;
|
||||
# when client stop to play vhost/app/stream, call the hook,
|
||||
# the request in the POST data string is a object encode by json:
|
||||
|
@ -1585,6 +1589,7 @@ vhost hooks.callback.srs.com {
|
|||
# on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN
|
||||
# @remark For SRS4, the HTTPS url is supported, for example:
|
||||
# on_stop https://xxx/api0 https://xxx/api1 https://xxx/apiN
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_STOP for all vhosts.
|
||||
on_stop http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions;
|
||||
# when srs reap a dvr file, call the hook,
|
||||
# the request in the POST data string is a object encode by json:
|
||||
|
@ -1600,6 +1605,7 @@ vhost hooks.callback.srs.com {
|
|||
# if valid, the hook must return HTTP code 200(Status OK) and response
|
||||
# an int value specifies the error code(0 corresponding to success):
|
||||
# 0
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_DVR for all vhosts.
|
||||
on_dvr http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs;
|
||||
# when srs reap a ts file of hls, call the hook,
|
||||
# the request in the POST data string is a object encode by json:
|
||||
|
@ -1620,6 +1626,7 @@ vhost hooks.callback.srs.com {
|
|||
# if valid, the hook must return HTTP code 200(Status OK) and response
|
||||
# an int value specifies the error code(0 corresponding to success):
|
||||
# 0
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_HLS for all vhosts.
|
||||
on_hls http://127.0.0.1:8085/api/v1/hls http://localhost:8085/api/v1/hls;
|
||||
# when srs reap a ts file of hls, call this hook,
|
||||
# used to push file to cdn network, by get the ts file from cdn network.
|
||||
|
@ -1631,6 +1638,7 @@ vhost hooks.callback.srs.com {
|
|||
# [ts_url], replace with the ts url.
|
||||
# ignore any return data of server.
|
||||
# @remark random select a url to report, not report all.
|
||||
# Overwrite by env SRS_VHOST_HTTP_HOOKS_ON_HLS_NOTIFY for all vhosts.
|
||||
on_hls_notify http://127.0.0.1:8085/api/v1/hls/[server_id]/[app]/[stream]/[ts_url][param];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ The changelog for SRS.
|
|||
|
||||
## SRS 5.0 Changelog
|
||||
|
||||
* v5.0, 2023-01-05, FFmpeg: Support build with FFmpeg native opus. v5.0.131 (#3140)
|
||||
* v5.0, 2023-01-06, DVR: Support blackbox test based on hooks. v5.0.132
|
||||
* v5.0, 2023-01-06, FFmpeg: Support build with FFmpeg native opus. v5.0.131 (#3140)
|
||||
* v5.0, 2023-01-05, CORS: Refine HTTP CORS headers. v5.0.130
|
||||
* v5.0, 2023-01-03, Add blackbox test for HLS and MP3 codec. v5.0.129
|
||||
* v5.0, 2023-01-02, Merge [#3355](https://github.com/ossrs/srs/pull/3355): Test: Support blackbox test by FFmpeg. v5.0.128
|
||||
|
|
|
@ -68,6 +68,16 @@ const char* _srs_version = "XCORE-" RTMP_SIG_SRS_SERVER;
|
|||
#define SRS_OVERWRITE_BY_ENV_MILLISECONDS(key) if (!srs_getenv(key).empty()) return (srs_utime_t)(::atoi(srs_getenv(key).c_str()) * SRS_UTIME_MILLISECONDS)
|
||||
#define SRS_OVERWRITE_BY_ENV_FLOAT_SECONDS(key) if (!srs_getenv(key).empty()) return srs_utime_t(::atof(srs_getenv(key).c_str()) * SRS_UTIME_SECONDS)
|
||||
#define SRS_OVERWRITE_BY_ENV_FLOAT_MILLISECONDS(key) if (!srs_getenv(key).empty()) return srs_utime_t(::atof(srs_getenv(key).c_str()) * SRS_UTIME_MILLISECONDS)
|
||||
#define SRS_OVERWRITE_BY_ENV_DIRECTIVE(key) { \
|
||||
static SrsConfDirective* dir = NULL; \
|
||||
if (!dir && !srs_getenv(key).empty()) { \
|
||||
string v = srs_getenv(key); \
|
||||
dir = new SrsConfDirective(); \
|
||||
dir->name = key; \
|
||||
dir->args.push_back(v); \
|
||||
} \
|
||||
if (dir) return dir; \
|
||||
}
|
||||
|
||||
/**
|
||||
* dumps the ingest/transcode-engine in @param dir to amf0 object @param engine.
|
||||
|
@ -5359,6 +5369,8 @@ SrsConfDirective* SrsConfig::get_vhost_http_hooks(string vhost)
|
|||
|
||||
bool SrsConfig::get_vhost_http_hooks_enabled(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_BOOL("srs.vhost.http_hooks.enabled"); // SRS_VHOST_HTTP_HOOKS_ENABLED
|
||||
|
||||
static bool DEFAULT = false;
|
||||
|
||||
SrsConfDirective* conf = get_vhost(vhost);
|
||||
|
@ -5371,6 +5383,8 @@ bool SrsConfig::get_vhost_http_hooks_enabled(string vhost)
|
|||
|
||||
bool SrsConfig::get_vhost_http_hooks_enabled(SrsConfDirective* vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_BOOL("srs.vhost.http_hooks.enabled"); // SRS_VHOST_HTTP_HOOKS_ENABLED
|
||||
|
||||
static bool DEFAULT = false;
|
||||
|
||||
SrsConfDirective* conf = vhost->get("http_hooks");
|
||||
|
@ -5388,6 +5402,8 @@ bool SrsConfig::get_vhost_http_hooks_enabled(SrsConfDirective* vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_connect(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_connect"); // SRS_VHOST_HTTP_HOOKS_ON_CONNECT
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5398,6 +5414,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_close(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_close"); // SRS_VHOST_HTTP_HOOKS_ON_CLOSE
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5408,6 +5426,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_publish(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_publish"); // SRS_VHOST_HTTP_HOOKS_ON_PUBLISH
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5418,6 +5438,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_unpublish(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_unpublish"); // SRS_VHOST_HTTP_HOOKS_ON_UNPUBLISH
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5428,6 +5450,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_play(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_play"); // SRS_VHOST_HTTP_HOOKS_ON_PLAY
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5438,6 +5462,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_stop"); // SRS_VHOST_HTTP_HOOKS_ON_STOP
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5448,6 +5474,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_dvr(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_dvr"); // SRS_VHOST_HTTP_HOOKS_ON_DVR
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5458,6 +5486,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_dvr(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_hls(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_hls"); // SRS_VHOST_HTTP_HOOKS_ON_HLS
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
@ -5468,6 +5498,8 @@ SrsConfDirective* SrsConfig::get_vhost_on_hls(string vhost)
|
|||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_hls_notify(string vhost)
|
||||
{
|
||||
SRS_OVERWRITE_BY_ENV_DIRECTIVE("srs.vhost.http_hooks.on_hls_notify"); // SRS_VHOST_HTTP_HOOKS_ON_HLS_NOTIFY
|
||||
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 131
|
||||
#define VERSION_REVISION 132
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3937,8 +3937,6 @@ VOID TEST(ConfigMainTest, SrtServerTlpktDrop)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesGlobal)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4035,8 +4033,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesGlobal)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesthreads)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4047,8 +4043,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesthreads)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesRtmp)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4082,8 +4076,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesRtmp)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesHttpApi)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4126,8 +4118,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpApi)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesHttpServer)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4163,8 +4153,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpServer)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesSrtServer)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4220,8 +4208,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesSrtServer)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesVhostSrt)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4235,8 +4221,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostSrt)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesRtcServer)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4303,8 +4287,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesRtcServer)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesVhostRtc)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4362,8 +4344,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostRtc)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPlay)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4433,8 +4413,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPlay)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPublish)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4460,8 +4438,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPublish)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesCircuitBreaker)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4490,8 +4466,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesCircuitBreaker)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudCls)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4539,8 +4513,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudCls)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudApm)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4566,8 +4538,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesTencentcloudApm)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesExporter)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4587,8 +4557,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesExporter)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesHeartbeat)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4611,8 +4579,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHeartbeat)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesScope)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4646,8 +4612,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesScope)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesHttpStatic)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4664,8 +4628,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpStatic)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesHttpRemux)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
MockSrsConfig conf;
|
||||
|
||||
if (true) {
|
||||
|
@ -4722,8 +4684,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHttpRemux)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesDash)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4776,8 +4736,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHds)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesDvr)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4806,8 +4764,6 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesDvr)
|
|||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesHls)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
if (true) {
|
||||
MockSrsConfig conf;
|
||||
|
||||
|
@ -4887,3 +4843,70 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesHls)
|
|||
EXPECT_FALSE(conf.get_vhost_hls_dts_directly("__defaultVhost__"));
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(ConfigEnvTest, CheckEnvValuesHooks)
|
||||
{
|
||||
MockSrsConfig conf;
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ENABLED", "on");
|
||||
EXPECT_TRUE(conf.get_vhost_http_hooks_enabled("__defaultVhost__"));
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_PUBLISH", "http://server/api/publish");
|
||||
SrsConfDirective* dir = conf.get_vhost_on_publish("__defaultVhost__");
|
||||
ASSERT_TRUE(dir != NULL);
|
||||
ASSERT_TRUE((int)dir->args.size() == 1);
|
||||
ASSERT_STREQ("http://server/api/publish", dir->arg0().c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_UNPUBLISH", "http://server/api/unpublish");
|
||||
SrsConfDirective* dir = conf.get_vhost_on_unpublish("__defaultVhost__");
|
||||
ASSERT_TRUE(dir != NULL);
|
||||
ASSERT_TRUE((int)dir->args.size() == 1);
|
||||
ASSERT_STREQ("http://server/api/unpublish", dir->arg0().c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_PLAY", "http://server/api/play");
|
||||
SrsConfDirective* dir = conf.get_vhost_on_play("__defaultVhost__");
|
||||
ASSERT_TRUE(dir != NULL);
|
||||
ASSERT_TRUE((int)dir->args.size() == 1);
|
||||
ASSERT_STREQ("http://server/api/play", dir->arg0().c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_STOP", "http://server/api/stop");
|
||||
SrsConfDirective* dir = conf.get_vhost_on_stop("__defaultVhost__");
|
||||
ASSERT_TRUE(dir != NULL);
|
||||
ASSERT_TRUE((int)dir->args.size() == 1);
|
||||
ASSERT_STREQ("http://server/api/stop", dir->arg0().c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_DVR", "http://server/api/dvr");
|
||||
SrsConfDirective* dir = conf.get_vhost_on_dvr("__defaultVhost__");
|
||||
ASSERT_TRUE(dir != NULL);
|
||||
ASSERT_TRUE((int)dir->args.size() == 1);
|
||||
ASSERT_STREQ("http://server/api/dvr", dir->arg0().c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_HLS", "http://server/api/hls");
|
||||
SrsConfDirective* dir = conf.get_vhost_on_hls("__defaultVhost__");
|
||||
ASSERT_TRUE(dir != NULL);
|
||||
ASSERT_TRUE((int)dir->args.size() == 1);
|
||||
ASSERT_STREQ("http://server/api/hls", dir->arg0().c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
SrsSetEnvConfig(hooks, "SRS_VHOST_HTTP_HOOKS_ON_HLS_NOTIFY", "http://server/api/hls_notify");
|
||||
SrsConfDirective* dir = conf.get_vhost_on_hls_notify("__defaultVhost__");
|
||||
ASSERT_TRUE(dir != NULL);
|
||||
ASSERT_TRUE((int)dir->args.size() == 1);
|
||||
ASSERT_STREQ("http://server/api/hls_notify", dir->arg0().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue